diff --git a/DEPS b/DEPS
index 6ee50a37..c3a5ea31 100644
--- a/DEPS
+++ b/DEPS
@@ -303,19 +303,19 @@
   # 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': 'e5dcffd10068cddca18339825f2c00f95e51a385',
+  'skia_revision': '1161451d903b47647c31aa0b463623ff58071b56',
   # 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': '299a02b2c82bfd6bffe69b1675d154190290bbcd',
+  'v8_revision': '1610539c8018d743b4aeb2a24a12aa5a0190159f',
   # 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': '34d30914048ac98a6f50f84aa630cc285b75bc79',
+  'angle_revision': '99eb1ceb5895d57a8859447411f4ccf68c2038d9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '0e75e7030ccbd9d1d7354bd6df68ae4b59acf4a0',
+  'swiftshader_revision': '7545980c939d086da9021c2e51975d1b3eb4eb71',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -323,7 +323,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': 'cccf8525db8a57153d3cb3e22efed2db4b71a8ab',
+  'boringssl_revision': '34492c89a8e381e0e856a686cc71b1eb5bd728db',
   # 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.
@@ -355,7 +355,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '1019b1c2b9f5faf75f4d12d938cc2f874be25a65',
+  'freetype_revision': '3467c2177cc90af3547c0b15e419e01976ebe71f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -395,7 +395,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': '4c5c7fd1931eaa285aa1ee7484a158529e32138a',
+  'devtools_frontend_revision': '0874945064c9c9b4b8a99db48bc097d7f48b8f6b',
   # 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.
@@ -419,7 +419,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': '5e815131e2179fa7ab3ceca4e0ad8f09ad04ca37',
+  'dawn_revision': 'a78978efe0b237a00be1d5879598cafa5d7bd4b4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -523,7 +523,7 @@
   # 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':    '64a6b82928934c23e2d75ae78b7c3714907210f5',
+  'llvm_libc_revision':    'ce2146789ec6ea882edee56c3d7b40dff851eb6b',
   # 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.
@@ -841,143 +841,143 @@
     'objects': [
       {
         # The Android libclang_rt.builtins libraries are currently only included in the Linux clang package.
-        'object_name': 'Linux_x64/clang-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '17d9277d32a87f856c6d0a5ee3f662015d423d876315d7736ca7b05b2b6f047e',
-        'size_bytes': 54610924,
-        'generation': 1743178947242029,
+        'object_name': 'Linux_x64/clang-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '2cccd3a5b04461f17a2e78d2f8bd18b448443a9dd4d6dfac50e8e84b4d5176f1',
+        'size_bytes': 54914604,
+        'generation': 1745271343199398,
         'condition': '(host_os == "linux" or checkout_android) and non_git_source',
       },
       {
-        'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '426b5f0daf964c3e1a9b9e7626311e8544a3e4768c8ef80d31464894b0fead68',
-        'size_bytes': 13573888,
-        'generation': 1743178947383618,
+        'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'f0e7dae567266055c9cfa2fba5b3dafa311dc86955f5a3f7a4047ce3096e7b27',
+        'size_bytes': 13559360,
+        'generation': 1745271343282399,
         'condition': 'host_os == "linux" and checkout_clang_tidy and non_git_source',
       },
       {
-        'object_name': 'Linux_x64/clangd-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': 'e419c7db3d30a163fdd8692cfeef26a1fb22db039f2f6ab42b930edfc4e5fd43',
-        'size_bytes': 13829552,
-        'generation': 1743178947404834,
+        'object_name': 'Linux_x64/clangd-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'd87ec8e9cd959cf5d12e0de2970f4a88a67f9884467dac5285813d02bbe50bcb',
+        'size_bytes': 13767836,
+        'generation': 1745271343386108,
         'condition': 'host_os == "linux" and checkout_clangd and non_git_source',
       },
       {
-        'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '935be59242458aa5849133c5a47b4ae11f6d8cae92401188e7db070dcae11326',
-        'size_bytes': 2303256,
-        'generation': 1743178947639495,
+        'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '08f9cdbdc1e3f78dfb11aa9815727e8af0cf8f2b9c9a0e3749ceb4d3584fc900',
+        'size_bytes': 2293720,
+        'generation': 1745271343569971,
         'condition': 'host_os == "linux" and checkout_clang_coverage_tools and non_git_source',
       },
       {
-        'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '3617952c541889b46806f66223bb4e8342e4c714938e7c83c7b9ca27b8e94cec',
-        'size_bytes': 5699348,
-        'generation': 1743178947497618,
+        'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '4b9c20478c015a03a44842d0bc24a9bd01a87890c76c4496577843ea31a21ed1',
+        'size_bytes': 5702536,
+        'generation': 1745271343407073,
         'condition': '((checkout_linux or checkout_mac or checkout_android) and host_os == "linux") and non_git_source',
       },
       {
-        'object_name': 'Mac/clang-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '690ae86dbd1c3689713db944059e7249760bdc30d4e06fdee79851780d62b255',
-        'size_bytes': 51731764,
-        'generation': 1743178948995628,
+        'object_name': 'Mac/clang-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '159cc811ee2882098086a426e83cb6744ff59d422d005a54630bc519e782d154',
+        'size_bytes': 51986012,
+        'generation': 1745271345031799,
         'condition': 'host_os == "mac" and host_cpu == "x64"',
       },
       {
-        'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '6e5b19f3ef4f2a84b2137f64c66cf7dc559c399ee070b69c26791ad4530dc84a',
-        'size_bytes': 980732,
-        'generation': 1743178955913911,
+        'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'ef380bc751dc8b137e294ac1aca295f3e49eb57b938ab011c38c70271d8582fc',
+        'size_bytes': 988872,
+        'generation': 1745271352425938,
         'condition': 'checkout_mac and not host_os == "mac"',
       },
       {
-        'object_name': 'Mac/clang-tidy-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '05c89e445986aece87cf514b0e877c6cb1b847ac32c8fe24baf5386fa2874956',
-        'size_bytes': 13595068,
-        'generation': 1743178949025853,
+        'object_name': 'Mac/clang-tidy-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '75907ac8d2ab310fd7272715c5d98cd4382dbd0b867872aa9216cede48c274d5',
+        'size_bytes': 13609872,
+        'generation': 1745271345094426,
         'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_tidy',
       },
       {
-        'object_name': 'Mac/clangd-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '27945ba4a22b9e59b0c28dd299919a1da3a18a2d76e10f30a5e0e72242af6b55',
-        'size_bytes': 15018860,
-        'generation': 1743178949033402,
+        'object_name': 'Mac/clangd-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'e2bcab0b3961fdc7a63286cf7a98397026ff1b5143d34c8a50844b26a7b023c6',
+        'size_bytes': 14998604,
+        'generation': 1745271345196743,
         'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clangd',
       },
       {
-        'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '3eb87f93194f7fe3177d4796c8d6376421811538747d1e65c825654ec4ecceea',
-        'size_bytes': 2257340,
-        'generation': 1743178949227666,
+        'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '6e4c8ed691948981d799f4af747288cdd5e90ae873dc36ada66726ad3e6caef1',
+        'size_bytes': 2262400,
+        'generation': 1745271345385127,
         'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_coverage_tools',
       },
       {
-        'object_name': 'Mac_arm64/clang-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': 'd4478bb335f9555fe6b0c888a4c0f5d48695081b02ce662cfe7a125f3f501eca',
-        'size_bytes': 43908296,
-        'generation': 1743178957140254,
+        'object_name': 'Mac_arm64/clang-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '3d437a643cc5838963254a39ab0528f49f2b65cd4dba2c80e628ad88eb419536',
+        'size_bytes': 43999512,
+        'generation': 1745271353863965,
         'condition': 'host_os == "mac" and host_cpu == "arm64"',
       },
       {
-        'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '06bd6ba46d4c0fc51e018d53c41f1ab81f7222f99dde95a10d57cb7f6c340eb7',
-        'size_bytes': 11774556,
-        'generation': 1743178957285392,
+        'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '0b4150c9e699e1e904495807aff48d2e5396527bf775d6597818dd4f73a9c38f',
+        'size_bytes': 11776260,
+        'generation': 1745271353927359,
         'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_tidy',
       },
       {
-        'object_name': 'Mac_arm64/clangd-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '1cb1d20b1d9bcf5bfab05f333c1cd21ff723a463f8b3a84c3b1f79758fc8d834',
-        'size_bytes': 12058388,
-        'generation': 1743178957310593,
+        'object_name': 'Mac_arm64/clangd-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '9fcd151cfffa01e6befe3760b9bc91d645135c79449dc378af4cb2fe0187150c',
+        'size_bytes': 12041956,
+        'generation': 1745271354010497,
         'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clangd',
       },
       {
-        'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '932bd7fb9dd4b8da2a59880f71f9f9fb4c66b071a4e481b19bbc340b9336dd11',
-        'size_bytes': 1978748,
-        'generation': 1743178957577801,
+        'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '1e62752ef5fd9d425699ed44098d5a0eec3be3f827990470aa9f9199d34a2fb8',
+        'size_bytes': 1975116,
+        'generation': 1745271354276821,
         'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_coverage_tools',
       },
       {
-        'object_name': 'Win/clang-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '6f486adfb406b0fcb9d3b83485ed4fca3467a3565d67baf0d9fd822721b780a1',
-        'size_bytes': 46895260,
-        'generation': 1743178966458891,
+        'object_name': 'Win/clang-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'd53230dbb7db57ddcda5a8377b5dd8388deee9ff2766617d54c6159c51e806be',
+        'size_bytes': 47036964,
+        'generation': 1745271363166454,
         'condition': 'host_os == "win"',
       },
       {
-        'object_name': 'Win/clang-tidy-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '3fd9808e08070f84920d22ad537e1f2445bcf5773c134ddef28b14cfe46a67e1',
-        'size_bytes': 13459292,
-        'generation': 1743178966633313,
+        'object_name': 'Win/clang-tidy-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'c6022f5923be5afc1685723a2383fcd8f9334cc6ee097ce3c71963de6ded0764',
+        'size_bytes': 13415856,
+        'generation': 1745271363272778,
         'condition': 'host_os == "win" and checkout_clang_tidy',
       },
       {
-        'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': 'bcf2e1a93afb20f384dbbcc484815989cb0aa2e593f2235251498c97d7f22493',
-        'size_bytes': 2477288,
-        'generation': 1743178973852867,
+        'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '555a34dd110a5fe3f7578745e9f0074cc341e550bed4ec5888accffb0200a7bb',
+        'size_bytes': 2483656,
+        'generation': 1745271370423782,
         'condition': 'checkout_win and not host_os == "win"',
       },
       {
-        'object_name': 'Win/clangd-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '12978a7e84b777aa10857e13f1e5e999061091126891631bf29df486f4bb2770',
-        'size_bytes': 13891176,
-        'generation': 1743178966674825,
+        'object_name': 'Win/clangd-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '66aafde760608c4c0de94a3947a179db8c8f93c8e474e3081b4401287abe4ee4',
+        'size_bytes': 13838692,
+        'generation': 1745271363368641,
        'condition': 'host_os == "win" and checkout_clangd',
       },
       {
-        'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '14842204c68030e276bb054bd5058a561be025d1ee1a0909943ea4f8c31cd715',
-        'size_bytes': 2367868,
-        'generation': 1743178966817841,
+        'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': '6944dc39b33dca3bb8f219ffb221e3f345fe56a5fa0447c60ea6a2894ae72687',
+        'size_bytes': 2373032,
+        'generation': 1745271363562596,
         'condition': 'host_os == "win" and checkout_clang_coverage_tools',
       },
       {
-        'object_name': 'Win/llvmobjdump-llvmorg-21-init-6681-g5b36835d-1.tar.xz',
-        'sha256sum': '6c505137fcc3879c3f0ad3562ec1f530a4b83f725d2a91363d1cfdcc3536252e',
-        'size_bytes': 5673896,
-        'generation': 1743178966726617,
+        'object_name': 'Win/llvmobjdump-llvmorg-21-init-9266-g09006611-1.tar.xz',
+        'sha256sum': 'e8b3e9f7cd7512edc7c05a12e818386cdb8d43bea9affbf0bf4db83a553092a5',
+        'size_bytes': 5684140,
+        'generation': 1745271363450942,
         'condition': '(checkout_linux or checkout_mac or checkout_android) and host_os == "win"',
       },
     ]
@@ -988,31 +988,31 @@
     'bucket': 'chromium-browser-clang',
     'objects': [
       {
-        'object_name': 'Linux_x64/rust-toolchain-3f690c2257b7080cd3a8cce64e082fc972148990-1-llvmorg-21-init-6681-g5b36835d.tar.xz',
-        'sha256sum': 'f3132b0b1fa412c2fb35e068e47b3fade679a1446d9a08b67c403d143931f2ec',
-        'size_bytes': 118335848,
-        'generation': 1743178941814849,
+        'object_name': 'Linux_x64/rust-toolchain-c8f94230282a8e8c1148f3e657f0199aad909228-1-llvmorg-21-init-9266-g09006611.tar.xz',
+        'sha256sum': '378c432f7739bb5da11aad7b3a2687f8252565eae5f0dcfc55c39a15382c519c',
+        'size_bytes': 118598336,
+        'generation': 1745271335898717,
         'condition': 'host_os == "linux" and non_git_source',
       },
       {
-        'object_name': 'Mac/rust-toolchain-3f690c2257b7080cd3a8cce64e082fc972148990-1-llvmorg-21-init-6681-g5b36835d.tar.xz',
-        'sha256sum': '093ad50477633cb98719ace92995ad0e11dfa491b97835997a30fc1078d63cbe',
-        'size_bytes': 111607824,
-        'generation': 1743178943094518,
+        'object_name': 'Mac/rust-toolchain-c8f94230282a8e8c1148f3e657f0199aad909228-1-llvmorg-21-init-9266-g09006611.tar.xz',
+        'sha256sum': 'bf05c8b5e90d6904de02dca9b3e4cb5e45a1a56207e7af1fbb3a10707704a26a',
+        'size_bytes': 111932536,
+        'generation': 1745271337336068,
         'condition': 'host_os == "mac" and host_cpu == "x64"',
       },
       {
-        'object_name': 'Mac_arm64/rust-toolchain-3f690c2257b7080cd3a8cce64e082fc972148990-1-llvmorg-21-init-6681-g5b36835d.tar.xz',
-        'sha256sum': 'e5db937e64017390f52c1cb68445ed5101855e0b9318c7de71dfaea37649b4cb',
-        'size_bytes': 101058976,
-        'generation': 1743178944397528,
+        'object_name': 'Mac_arm64/rust-toolchain-c8f94230282a8e8c1148f3e657f0199aad909228-1-llvmorg-21-init-9266-g09006611.tar.xz',
+        'sha256sum': '1aec99f479ff28cefe44ed739844833e016a1da255cf3c17d79e59a273246615',
+        'size_bytes': 101605468,
+        'generation': 1745271339727037,
         'condition': 'host_os == "mac" and host_cpu == "arm64"',
       },
       {
-        'object_name': 'Win/rust-toolchain-3f690c2257b7080cd3a8cce64e082fc972148990-1-llvmorg-21-init-6681-g5b36835d.tar.xz',
-        'sha256sum': '3f8d34895c880301e2805164b7b5e4e487769b65d5fcadb4384a10228f559c85',
-        'size_bytes': 192615112,
-        'generation': 1743178945657202,
+        'object_name': 'Win/rust-toolchain-c8f94230282a8e8c1148f3e657f0199aad909228-1-llvmorg-21-init-9266-g09006611.tar.xz',
+        'sha256sum': 'b291520613a3ebc415e4576a7fa31d840a5ebf4ab9be6e9dc5d90062dc001c1e',
+        'size_bytes': 193280372,
+        'generation': 1745271341223097,
         'condition': 'host_os == "win"',
       },
     ],
@@ -1152,7 +1152,7 @@
   },
 
   'src/chrome/release_scripts': {
-      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '6e0c25fb2cf1d16a46c03138d9745536a185e93e',
+      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '2dd15ef4b070d15f38ca3a4238d8de7095557bed',
       'condition': 'checkout_chrome_release_scripts',
   },
 
@@ -1484,7 +1484,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/variations/cipd',
-        'version': 'QXYquhXfxWlfiPs4Il75Srs65SFK5POLxWjWZofYJrcC',
+        'version': 'b4PXk0pYOjOEiNnfyCFp9Nd5JTbI8UctLptBz16HA6YC',
       },
     ],
     'dep_type': 'cipd',
@@ -1495,7 +1495,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '86860c4de44765ed2d195926b9d3dd6ed1d20efd',
+    '72d9d8f0bcf477b826e8abd3986b2b24eff275ff',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1654,7 +1654,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'JF5sZnHpxvqTCPlwlSSvr296yGpWharAZaJzJ6I9EGwC',
+          'version': 'G89DVlKhY4pOqWg7hiMtXu9y20yZdUbM5VCmQ0YNMWwC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -2535,7 +2535,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '6acaf607621ce5a117dc1a9773f27aa0d4c77b5b',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'b9acf7ff3553f8cf7545dc5e2bfb1b1e1a4a7081',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2712,7 +2712,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'OYELKv1Z-yH4xw9qL3QhIZ6orhoBStNNpyWKTNudpjsC',
+              'version': 'bA3htCoEd_EArHekDGQSNpmBzQrcby2ioG6SFyl3AtwC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2849,16 +2849,16 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@b9aab6c35f37e6532011ddab976c3ca71819c074',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@96793fb0ff6fb5d4328cc6f71d84f5cb2d835daf',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@fc9889c889561c5882e83819dcaffef5ed45529b',
   'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3',
   'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@bab63ff679c41eb75fc67dac76e1dc44426101e1',
-  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@b6a83226d75d15b1733d35ee9e26b8f895ecffcb',
-  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@409c16be502e39fe70dd6fe2d9ad4842ef2c9a53',
+  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@8e9165a3d162967a424dcf2ff645a98b50381cce',
+  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@e2e53a724677f6eba8ff0ce1ccb64ee321785cbd',
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@fb78607414e154c7a5c01b23177ba719c8a44909',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@0b8196724e4ad28cc7459b82a9b75f252c08cb3e',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@4e246c56ec5afb5ad66b9b04374d39ac04675c8e',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@6530df51e0db74d50241c3a0f2c2798e99d0d9dd',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@cea6ec1cdd37494c1f0fc5619c6c356ac33372fb',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21',
@@ -2903,7 +2903,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'de7866f6cab90d0dc7279cde6c2560fcae90c2d3',
+    Var('webrtc_git') + '/src.git' + '@' + '41051bb035492367ec74795db9eada3321d1ef98',
 
   # 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.
@@ -3036,7 +3036,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'Ak7-qaRgm-rXDCM8_wBZPxTLi0xiBZHrOUp7mXfz8h8C',
+        'version': 'CaP3m503X4y4vFw4S-b3Qht78KsHJZtQo2lj89bqv0MC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3047,7 +3047,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'EU1i4ckt22zgg-GxrJjaA0AMmj-mESO3KMgZSKREQ_kC',
+        'version': '5OFFXje9ZKohuj_FC0Lrw2Fyi863aSkiDHbbFxtVTqwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4623,7 +4623,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        '0d3bfd72d3a7957232b6e5a7e9c67ea38775a661',
+        '7d0a3c2435fe79279ba2a404cecb24a8b6015e4a',
       'condition': 'checkout_src_internal',
   },
 
@@ -4689,7 +4689,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '5faebbb3e45a687dae0a0cd09f8f8c69e9897386',
+        '09a455234a0af038336d80a2f116dc4602e49a5c',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 4b7b42d..9ba42bfe 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -5985,6 +5985,7 @@
     """Groups commit checks that target android code."""
     results = []
     results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
+    results.extend(_CheckAndroidNullAwayAnnotatedClasses(input_api, output_api))
     return results
 
 # TODO(chrishall): could we additionally match on any path owned by
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index ef59f6f..e9fc738 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -6734,6 +6734,9 @@
       <message name="IDS_ASH_SCREEN_CAPTURE_ALERT_OPEN" desc="Alert spoken by screen readers on entering capture mode.">
         Capture Mode, default is <ph name="SOURCE">$1<ex>partial</ex></ph> <ph name="TYPE">$2<ex>screenshot</ex></ph>. Press tab for keyboard navigation.
       </message>
+      <message name="IDS_ASH_SCREEN_CAPTURE_KEYBOARD_NAVIGATION_ALERT_OPEN" desc="Alert spoken by screen readers on entering capture mode. Contains details about using keyboard navigation in a session.">
+        In screen capture, set to <ph name="SOURCE">$1<ex>partial</ex></ph> <ph name="TYPE">$2<ex>screenshot</ex></ph>. Press tab to choose capture type. Press space to select region. Press enter to capture.
+      </message>
       <message name="IDS_ASH_SUNFISH_MODE_ALERT_OPEN" desc="Alert spoken by screen readers on entering a mode where users can select a region on their screen to search.">
         Select to search my screen. Press tab then space for keyboard navigation.
       </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_KEYBOARD_NAVIGATION_ALERT_OPEN.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_KEYBOARD_NAVIGATION_ALERT_OPEN.png.sha1
new file mode 100644
index 0000000..ee61bfd0
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_KEYBOARD_NAVIGATION_ALERT_OPEN.png.sha1
@@ -0,0 +1 @@
+436e7f1f6308cb25276fddef9ca3ec75be546c3b
\ No newline at end of file
diff --git a/ash/capture_mode/capture_mode_behavior.cc b/ash/capture_mode/capture_mode_behavior.cc
index e7c6f40..abdd1841 100644
--- a/ash/capture_mode/capture_mode_behavior.cc
+++ b/ash/capture_mode/capture_mode_behavior.cc
@@ -681,7 +681,7 @@
   }
 
   return l10n_util::GetStringFUTF8(
-      IDS_ASH_SCREEN_CAPTURE_ALERT_OPEN,
+      IDS_ASH_SCREEN_CAPTURE_KEYBOARD_NAVIGATION_ALERT_OPEN,
       l10n_util::GetStringUTF16(capture_source_id),
       l10n_util::GetStringUTF16(
           controller->type() == CaptureModeType::kImage
diff --git a/ash/webui/boca_ui/boca_app_page_handler.cc b/ash/webui/boca_ui/boca_app_page_handler.cc
index 144c062..4596c71 100644
--- a/ash/webui/boca_ui/boca_app_page_handler.cc
+++ b/ash/webui/boca_ui/boca_app_page_handler.cc
@@ -351,6 +351,7 @@
   if (GetSessionManager()->disabled_on_non_managed_network()) {
     std::move(callback).Run(
         mojom::SessionResult::NewError(mojom::GetSessionError::kEmpty));
+    GetSessionManager()->UpdateCurrentSession(nullptr, /*dispatch_event=*/true);
     return;
   }
   auto get_session_request = std::make_unique<GetSessionRequest>(
diff --git a/ash/webui/boca_ui/boca_app_page_handler_unittest.cc b/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
index eb474ca4..427f55cc 100644
--- a/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
+++ b/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
@@ -1045,8 +1045,8 @@
               GetSession(_, /*can_skip_duplicate_request=*/false))
       .Times(0);
   EXPECT_CALL(*session_manager(),
-              UpdateCurrentSession(NotNull(), /*dispatch_event=*/true))
-      .Times(0);
+              UpdateCurrentSession(testing::IsNull(), /*dispatch_event=*/true))
+      .Times(1);
   EXPECT_CALL(*session_manager(), disabled_on_non_managed_network())
       .WillOnce(Return(true));
   boca_app_handler()->GetSession(future_1.GetCallback());
diff --git a/base/BUILD.gn b/base/BUILD.gn
index b2c4562a..acec47a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1232,6 +1232,7 @@
       "message_loop/message_pump_android.h",
       "os_compat_android.cc",
       "os_compat_android.h",
+      "power_monitor/energy_monitor_android.h",
       "process/process_android.cc",
       "profiler/native_unwinder_android_map_delegate.h",
       "profiler/native_unwinder_android_memory_regions_map.h",
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
index 6bfe1de..9f3ab14e 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -4,25 +4,37 @@
 
 package org.chromium.base;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
 import android.os.Build;
+import android.os.OutcomeReceiver;
 import android.os.PowerManager;
+import android.os.PowerMonitorReadings;
+import android.os.health.SystemHealthManager;
 
 import org.jni_zero.CalledByNative;
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.power_monitor.BatteryPowerStatus;
 import org.chromium.base.task.PostTask;
+import org.chromium.base.task.SequencedTaskRunner;
 import org.chromium.base.task.TaskTraits;
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /** Integrates native PowerMonitor with the java side. */
 @NullMarked
@@ -32,6 +44,26 @@
 
     @PowerStatus private static int sBatteryPowerStatus = PowerStatus.UNKNOWN;
 
+    private static final int SYSTEM_HEALTH_MANAGER_API_TIMEOUT_MS = 1000;
+    private static final String SYSTEM_HEALTH_MANAGER_ERROR_HISTOGRAM =
+            "Power.SystemHealthManagerError";
+
+    private static final List<android.os.PowerMonitor> sPowerMonitors = new ArrayList<>();
+    private static @Nullable SystemHealthManager sSystemHealthManager;
+    private static @Nullable SequencedTaskRunner sTaskRunner;
+
+    // These values are persisted to logs. Entries should not be renumbered and
+    // numeric values should never be reused.
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SystemHealthManagerError {
+        // LINT.IfChange(SystemHealthManagerError)
+        int NO_POWER_MONITORS = 0;
+        int GET_POWER_MONITOR_READINGS_INTERRUPTED = 1;
+        int GET_POWER_MONITOR_READINGS_TIMEOUT = 2;
+        int COUNT = 3;
+        // LINT.ThenChange(/tools/metrics/histograms/metadata/power/enums.xml:SystemHealthManagerError)
+    };
+
     @Retention(RetentionPolicy.SOURCE)
     @interface PowerStatus {
         int UNKNOWN = 0;
@@ -105,6 +137,33 @@
                         }
                     });
         }
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+            sTaskRunner = PostTask.createSequencedTaskRunner(TaskTraits.BEST_EFFORT_MAY_BLOCK);
+            sSystemHealthManager =
+                    (SystemHealthManager)
+                            ContextUtils.getApplicationContext()
+                                    .getSystemService(Context.SYSTEM_HEALTH_SERVICE);
+            if (sSystemHealthManager != null) {
+                sSystemHealthManager.getSupportedPowerMonitors(
+                        Runnable::run,
+                        (monitors) -> {
+                            synchronized (sPowerMonitors) {
+                                for (android.os.PowerMonitor monitor : monitors) {
+                                    // Ignore direct rails measurements. Their meaning is
+                                    // effectively unknown.
+                                    // https://developer.android.com/reference/android/os/PowerMonitor#POWER_MONITOR_TYPE_CONSUMER
+                                    // https://developer.android.com/reference/android/os/PowerMonitor#POWER_MONITOR_TYPE_MEASUREMENT
+                                    if (monitor.getType()
+                                            == android.os.PowerMonitor
+                                                    .POWER_MONITOR_TYPE_CONSUMER) {
+                                        sPowerMonitors.add(monitor);
+                                    }
+                                }
+                            }
+                        });
+            }
+        }
     }
 
     private PowerMonitor() {}
@@ -139,6 +198,72 @@
     }
 
     @CalledByNative
+    private static long getTotalEnergyConsumed() {
+        ThreadUtils.assertOnBackgroundThread();
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+            return 0;
+        }
+        CountDownLatch ready = new CountDownLatch(1);
+        class TotalEnergyReceiver
+                implements OutcomeReceiver<PowerMonitorReadings, RuntimeException> {
+            private long mTotalEnergy;
+
+            @Override
+            public void onResult(PowerMonitorReadings readings) {
+                ThreadUtils.assertOnBackgroundThread();
+                // No need to synchronize sPowerMonitors because it is never mutated once populated.
+                for (android.os.PowerMonitor monitor : sPowerMonitors) {
+                    long consumed = readings.getConsumedEnergy(monitor);
+                    if (consumed != PowerMonitorReadings.ENERGY_UNAVAILABLE) {
+                        mTotalEnergy += consumed;
+                    }
+                }
+                ready.countDown();
+            }
+
+            public long getTotalEnergy() {
+                return mTotalEnergy;
+            }
+        }
+
+        TotalEnergyReceiver receiver = new TotalEnergyReceiver();
+        // We start monitoring power use only after we know the battery status. Thus we don't need
+        // to call `create` here.
+        synchronized (sPowerMonitors) {
+            if (sPowerMonitors.isEmpty()) {
+                RecordHistogram.recordEnumeratedHistogram(
+                        SYSTEM_HEALTH_MANAGER_ERROR_HISTOGRAM,
+                        SystemHealthManagerError.NO_POWER_MONITORS,
+                        SystemHealthManagerError.COUNT);
+                return 0;
+            }
+            // If power monitors are not empty, the system health manager and the task runner are
+            // initialized.
+            assumeNonNull(sSystemHealthManager);
+            assumeNonNull(sTaskRunner);
+            sSystemHealthManager.getPowerMonitorReadings(sPowerMonitors, sTaskRunner, receiver);
+        }
+        boolean isReady = false;
+        try {
+            isReady = ready.await(SYSTEM_HEALTH_MANAGER_API_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            RecordHistogram.recordEnumeratedHistogram(
+                    SYSTEM_HEALTH_MANAGER_ERROR_HISTOGRAM,
+                    SystemHealthManagerError.GET_POWER_MONITOR_READINGS_INTERRUPTED,
+                    SystemHealthManagerError.COUNT);
+            return 0;
+        }
+        if (!isReady) {
+            RecordHistogram.recordEnumeratedHistogram(
+                    SYSTEM_HEALTH_MANAGER_ERROR_HISTOGRAM,
+                    SystemHealthManagerError.GET_POWER_MONITOR_READINGS_TIMEOUT,
+                    SystemHealthManagerError.COUNT);
+            return 0;
+        }
+        return receiver.getTotalEnergy();
+    }
+
+    @CalledByNative
     private static int getRemainingBatteryCapacity() {
         // Creation of the PowerMonitor can be deferred based on the browser startup path.  If the
         // battery power is requested prior to the browser triggering the creation, force it to be
diff --git a/base/power_monitor/energy_monitor_android.h b/base/power_monitor/energy_monitor_android.h
new file mode 100644
index 0000000..e7577c3
--- /dev/null
+++ b/base/power_monitor/energy_monitor_android.h
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_POWER_MONITOR_ENERGY_MONITOR_ANDROID_H_
+#define BASE_POWER_MONITOR_ENERGY_MONITOR_ANDROID_H_
+
+#include <cstdint>
+
+#include "base/base_export.h"
+#include "build/build_config.h"
+
+namespace base {
+namespace android {
+
+// Read and return the current remaining battery capacity (microampere-hours).
+// Only supported with a device power source (i.e. not in child processes in
+// Chrome) and on devices with Android >= Lollipop as well as a power supply
+// that supports this counter. Returns 0 if unsupported.
+int BASE_EXPORT GetRemainingBatteryCapacity();
+// Read and return the total energy consumed since boot in microwatt-seconds.
+// Only supported on specific devices with Android >= Vanilla Ice Cream.
+// Returns 0 if unsupported.
+// This should be called only after we know the battery status from
+// PowerMonitor::AddPowerStateObserverAndReturnBatteryPowerStatus. Otherwise the
+// monitor might be not initialized, and this function may return 0.
+int64_t BASE_EXPORT GetTotalEnergyConsumed();
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_POWER_MONITOR_ENERGY_MONITOR_ANDROID_H_
diff --git a/base/power_monitor/power_monitor.cc b/base/power_monitor/power_monitor.cc
index 9a572c0b..df28a48 100644
--- a/base/power_monitor/power_monitor.cc
+++ b/base/power_monitor/power_monitor.cc
@@ -63,13 +63,6 @@
   return is_system_suspended_;
 }
 
-// static
-bool PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState(
-    PowerStateObserver* obs) {
-  return AddPowerStateObserverAndReturnBatteryPowerStatus(obs) ==
-         PowerStateObserver::BatteryPowerStatus::kBatteryPower;
-}
-
 PowerStateObserver::BatteryPowerStatus
 PowerMonitor::AddPowerStateObserverAndReturnBatteryPowerStatus(
     PowerStateObserver* obs) {
@@ -141,13 +134,6 @@
   source_->SetCurrentThermalState(state);
 }
 
-#if BUILDFLAG(IS_ANDROID)
-int PowerMonitor::GetRemainingBatteryCapacity() const {
-  DCHECK(IsInitialized());
-  return Source()->GetRemainingBatteryCapacity();
-}
-#endif  // BUILDFLAG(IS_ANDROID)
-
 void PowerMonitor::NotifyPowerStateChange(bool on_battery_power) {
   DCHECK(IsInitialized());
   NotifyPowerStateChange(
diff --git a/base/power_monitor/power_monitor.h b/base/power_monitor/power_monitor.h
index 0ddc965e..6213ed7 100644
--- a/base/power_monitor/power_monitor.h
+++ b/base/power_monitor/power_monitor.h
@@ -66,9 +66,7 @@
   // Returns true if the system is currently suspended.
   bool AddPowerSuspendObserverAndReturnSuspendedState(
       PowerSuspendObserver* observer);
-  // Returns true if the system is on-battery.
-  bool AddPowerStateObserverAndReturnOnBatteryState(
-      PowerStateObserver* observer);
+  // Returns the battery power status (battery power, external power, unknown).
   PowerStateObserver::BatteryPowerStatus
   AddPowerStateObserverAndReturnBatteryPowerStatus(
       PowerStateObserver* observer);
@@ -98,14 +96,6 @@
   // Update the result of thermal state.
   void SetCurrentThermalState(PowerThermalObserver::DeviceThermalState state);
 
-#if BUILDFLAG(IS_ANDROID)
-  // Read and return the current remaining battery capacity (microampere-hours).
-  // Only supported with a device power source (i.e. not in child processes in
-  // Chrome) and on devices with Android >= Lollipop as well as a power supply
-  // that supports this counter. Returns 0 if unsupported.
-  int GetRemainingBatteryCapacity() const;
-#endif  // BUILDFLAG(IS_ANDROID)
-
   // Uninitializes the PowerMonitor. Should be called at the end of any unit
   // test that mocks out the PowerMonitor, to avoid affecting subsequent tests.
   // There must be no live observers when invoked. Safe to call even if the
diff --git a/base/power_monitor/power_monitor_device_source.h b/base/power_monitor/power_monitor_device_source.h
index 673c9c0..24668792 100644
--- a/base/power_monitor/power_monitor_device_source.h
+++ b/base/power_monitor/power_monitor_device_source.h
@@ -116,7 +116,6 @@
 #if BUILDFLAG(IS_ANDROID)
   PowerThermalObserver::DeviceThermalState GetCurrentThermalState()
       const override;
-  int GetRemainingBatteryCapacity() const override;
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_WIN)
diff --git a/base/power_monitor/power_monitor_device_source_android.cc b/base/power_monitor/power_monitor_device_source_android.cc
index 19df844e..c72989a60 100644
--- a/base/power_monitor/power_monitor_device_source_android.cc
+++ b/base/power_monitor/power_monitor_device_source_android.cc
@@ -4,6 +4,7 @@
 
 #include "base/power_monitor/power_monitor_device_source.h"
 
+#include "base/power_monitor/energy_monitor_android.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
 #include "base/power_monitor/power_observer.h"
@@ -77,6 +78,16 @@
   ProcessThermalEventHelper(MapToDeviceThermalState(thermal_status));
 }
 
+int GetRemainingBatteryCapacity() {
+  JNIEnv* env = jni_zero::AttachCurrentThread();
+  return base::android::Java_PowerMonitor_getRemainingBatteryCapacity(env);
+}
+
+int64_t GetTotalEnergyConsumed() {
+  JNIEnv* env = jni_zero::AttachCurrentThread();
+  return base::android::Java_PowerMonitor_getTotalEnergyConsumed(env);
+}
+
 // Note: Android does not have the concept of suspend / resume as it's known by
 // other platforms. Thus we do not send Suspend/Resume notifications. See
 // http://crbug.com/644515
@@ -91,11 +102,6 @@
   return static_cast<PowerStateObserver::BatteryPowerStatus>(battery_power);
 }
 
-int PowerMonitorDeviceSource::GetRemainingBatteryCapacity() const {
-  JNIEnv* env = jni_zero::AttachCurrentThread();
-  return base::android::Java_PowerMonitor_getRemainingBatteryCapacity(env);
-}
-
 PowerThermalObserver::DeviceThermalState
 PowerMonitorDeviceSource::GetCurrentThermalState() const {
   JNIEnv* env = jni_zero::AttachCurrentThread();
diff --git a/base/power_monitor/power_monitor_source.cc b/base/power_monitor/power_monitor_source.cc
index 9e42d724..c53dfe9 100644
--- a/base/power_monitor/power_monitor_source.cc
+++ b/base/power_monitor/power_monitor_source.cc
@@ -26,12 +26,6 @@
 void PowerMonitorSource::SetCurrentThermalState(
     PowerThermalObserver::DeviceThermalState state) {}
 
-#if BUILDFLAG(IS_ANDROID)
-int PowerMonitorSource::GetRemainingBatteryCapacity() const {
-  return 0;
-}
-#endif  // BUILDFLAG(IS_ANDROID)
-
 // static
 void PowerMonitorSource::ProcessPowerEvent(PowerEvent event_id) {
   auto* power_monitor = base::PowerMonitor::GetInstance();
diff --git a/base/power_monitor/power_monitor_source.h b/base/power_monitor/power_monitor_source.h
index 01145b5..095299c 100644
--- a/base/power_monitor/power_monitor_source.h
+++ b/base/power_monitor/power_monitor_source.h
@@ -49,11 +49,6 @@
   virtual PowerStateObserver::BatteryPowerStatus GetBatteryPowerStatus()
       const = 0;
 
-#if BUILDFLAG(IS_ANDROID)
-  // Read and return the current remaining battery capacity (microampere-hours).
-  virtual int GetRemainingBatteryCapacity() const;
-#endif  // BUILDFLAG(IS_ANDROID)
-
   static const char* DeviceThermalStateToString(
       PowerThermalObserver::DeviceThermalState state);
 
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Condition.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Condition.java
index e09e4c4b..b32e5e3 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/Condition.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Condition.java
@@ -20,6 +20,7 @@
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 
+import java.util.Objects;
 import java.util.function.Function;
 
 /**
@@ -286,6 +287,18 @@
     }
 
     /**
+     * {@link #checkWithSuppliers()} should return this as a convenience method to compare Objects
+     * (including Strings).
+     */
+    public static ConditionStatus whetherEquals(Object expected, Object actual) {
+        return whether(
+                Objects.equals(expected, actual),
+                "Expected: \"%s\"; Actual: \"%s\"",
+                expected,
+                actual);
+    }
+
+    /**
      * {@link #checkWithSuppliers()} should return this when it does not have information to check
      * the Condition yet.
      *
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/README.md b/base/test/android/javatests/src/org/chromium/base/test/transit/README.md
index c983be7..a3a35668 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/README.md
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/README.md
@@ -349,20 +349,20 @@
 ```java
 /** The tab switcher screen, with the tab grid and the tab management toolbar. */
 public class TabSwitcherStation extends Station<ChromeTabbedActivity> {
-    public static final ViewSpec NEW_TAB_BUTTON =
-            viewSpec(withId(R.id.new_tab_button));
-    public static final ViewSpec INCOGNITO_TOGGLE_TABS =
-            viewSpec(withId(R.id.incognito_toggle_tabs));
+    public ViewElement<View> newTabButtonElement;
+    public ViewElement<View> incognitoToggleTabsElement;
 
     @Override
     public void declareElements(Elements.Builder elements) {
-        elements.declareView(NEW_TAB_BUTTON);
-        elements.declareView(INCOGNITO_TOGGLE_TABS);
+        newTabButtonElement =
+                elements.declareView(viewSpec(withId(R.id.new_tab_button)));
+        incognitoToggleTabsElement =
+                elements.declareView(viewSpec(withId(R.id.incognito_toggle_tabs)));
     }
 
     public NewTabPageStation openNewTabFromButton() {
         NewTabPageStation newTab = new NewTabPageStation();
-        return travelToSync(this, newTab, () -> NEW_TAB_BUTTON.perform(click()))
+        return travelToSync(this, newTab, newTabButtonElement.getClickTrigger())
     }
 }
 ```
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ScrollableFacility.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ScrollableFacility.java
index 92cca32..cd7d4a7c 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ScrollableFacility.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ScrollableFacility.java
@@ -399,7 +399,7 @@
         return mHostStation.swapFacilitySync(
                 List.of(this, itemOnScreenFacility),
                 destination,
-                itemOnScreenFacility.viewElement.clickTrigger());
+                itemOnScreenFacility.viewElement.getClickTrigger());
     }
 
     private <DestinationStationT extends Station<?>> DestinationStationT travelToStation(
@@ -414,7 +414,7 @@
 
         assumeNonNull(itemOnScreenFacility.viewElement);
         return mHostStation.travelToSync(
-                destination, itemOnScreenFacility.viewElement.clickTrigger());
+                destination, itemOnScreenFacility.viewElement.getClickTrigger());
     }
 
     /** Get all {@link Item}s declared in this {@link ScrollableFacility}. */
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
index 809815c..8c143a6 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
@@ -107,7 +107,7 @@
     }
 
     /** Trigger an Espresso action on this View. */
-    public Transition.Trigger performTrigger(ViewAction action) {
+    public Transition.Trigger getPerformTrigger(ViewAction action) {
         return () -> {
             View view = get();
             Espresso.onView(is(view)).perform(action);
@@ -119,29 +119,34 @@
      *
      * <p>Requires it to be >90% displayed.
      */
+    public Transition.Trigger getClickTrigger() {
+        return getPerformTrigger(ViewActions.click());
+    }
+
+    @Deprecated
     public Transition.Trigger clickTrigger() {
-        return performTrigger(ViewActions.click());
+        return getClickTrigger();
     }
 
     /**
      * Trigger an Espresso click on this View.
      *
-     * <p>Does not require the View to be > 90% displayed like {@link #clickTrigger()}.
+     * <p>Does not require the View to be > 90% displayed like {@link #getClickTrigger()}.
      *
      * <p>TODO(crbug.com/411140394): Rename clickTrigger() to strictClickTrigger() and rename this
      * to clickTrigger().
      */
-    public Transition.Trigger forgivingClickTrigger() {
-        return performTrigger(ForgivingClickAction.forgivingClick());
+    public Transition.Trigger getForgivingClickTrigger() {
+        return getPerformTrigger(ForgivingClickAction.forgivingClick());
     }
 
     /**
-     * Trigger an Espresso long click on this View.
+     * Trigger an Espresso long press on this View.
      *
      * <p>Requires it to be >90% displayed.
      */
-    public Transition.Trigger longClickTrigger() {
-        return performTrigger(ViewActions.longClick());
+    public Transition.Trigger getLongPressTrigger() {
+        return getPerformTrigger(ViewActions.longClick());
     }
 
     /** Trigger an Espresso ViewAssertion on this View. */
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewSpec.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewSpec.java
index 96e7539..ceedc38 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewSpec.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewSpec.java
@@ -14,8 +14,6 @@
 import androidx.test.espresso.Espresso;
 import androidx.test.espresso.UiController;
 import androidx.test.espresso.ViewAction;
-import androidx.test.espresso.ViewInteraction;
-import androidx.test.espresso.action.ViewActions;
 
 import org.hamcrest.Matcher;
 import org.hamcrest.StringDescription;
@@ -120,16 +118,6 @@
     }
 
     /**
-     * Perform an Espresso click() on a displayed View that matches this ViewSpec's Matcher.
-     *
-     * @deprecated Use {@link ViewElement#clickTrigger()}
-     */
-    @Deprecated
-    public ViewInteraction click() {
-        return Espresso.onView(mViewMatcher).perform(ViewActions.click());
-    }
-
-    /**
      * Print the whole View hierarchy that contains the View matched to this ViewElement.
      *
      * <p>For debugging.
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/getting_started.md b/base/test/android/javatests/src/org/chromium/base/test/transit/getting_started.md
index 6836689e..dec0323 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/getting_started.md
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/getting_started.md
@@ -151,25 +151,19 @@
 ```
 
 We need the View instance to pass to `mRenderTestRule.render()`. The View can be
-retrieved from the Element declared in `PageStation#declareElements()`:
+retrieved from the Element already declared in `PageStation#declareElements()`:
 
 ```java
 public class PageStation extends Station {
-    public static final ViewElement TAB_SWITCHER_BUTTON =
-             unscopedViewElement(withId(R.id.tab_switcher_button));
-
-+   ViewElement mTabSwitcherButton;
+    public ViewElement<ToggleTabStackButton> tabSwitcherButtonElement;
 
     public void declareElements(Elements.Builder elements) {
         [...]
--       elements.declareView(TAB_SWITCHER_BUTTON);
-+       mTabSwitcherButton = elements.declareView(TAB_SWITCHER_BUTTON);
+        tabSwitcherButtonElement =
+                elements.declareView(
+                    viewSpec(ToggleTabStackButton.class, withId(R.id.tab_switcher_button)));
         [...]
     }
-
-+   public ImageButton getTabSwitcherButton() {
-+       return (ImageButton) mTabSwitcherButton.get();
-+   }
 }
 ```
 
@@ -192,7 +186,7 @@
     public void testOneTab_I() {
         PageStation page = mCtaTestRule.start();
 
-        ImageButton tabSwitcherButton = page.getTabSwitcherButton();
+        ImageButton tabSwitcherButton = page.tabSwitcherButtonElement.get();
         TabSwitcherDrawable tabSwitcherDrawable = (TabSwitcherDrawable) tabSwitcherButton.getDrawable();
         assertEquals("I", tabSwitcherDrawable.getTextRenderedForTesting());
         TransitAsserts.assertFinalDestination(page);
@@ -210,7 +204,7 @@
         PageStation page = mCtaTestRule.start();
         NewTabPageStation ntp = page.openGenericAppMenu().openNewTab();
 
-        ImageButton tabSwitcherButton = ntp.getTabSwitcherButton();
+        ImageButton tabSwitcherButton = ntp.tabSwitcherButtonElement.get();
         TabSwitcherDrawable tabSwitcherDrawable =
                 (TabSwitcherDrawable) tabSwitcherButton.getDrawable();
         assertEquals("II", tabSwitcherDrawable.getTextRenderedForTesting());
@@ -290,7 +284,7 @@
         PageStation page = mCtaTestRule.startOnBlankPage();
         page = Journeys.prepareTabs(page, 5, 0, "about:blank");
 
-        ImageButton tabSwitcherButton = page.getTabSwitcherButton();
+        ImageButton tabSwitcherButton = page.tabSwitcherButtonElement.get();
         TabSwitcherDrawable tabSwitcherDrawable =
             (TabSwitcherDrawable) tabSwitcherButton.getDrawable();
         assertEquals("V", tabSwitcherDrawable.getTextRenderedForTesting());
@@ -305,7 +299,8 @@
 are useful when the state they model is optional, or when the state is
 interesting to only a small number of tests.
 
-Let's make a `TabSwitcherButtonFacility` representing the button we're testing.
+Just for the sake of this guide, let's make a `TabSwitcherButtonFacility`
+representing the button we're testing.
 `chrome/test/android/javatests/src/org/chromium/chrome/test/transit/` is where
 Chrome's Transit Layer is located, so create `TabSwitcherButtonFacility.java`
 there:
@@ -316,19 +311,18 @@
 [imports]
 
 public class TabSwitcherButtonFacility extends Facility<PageStation> {
-    private Supplier<View> mTabSwitcherButton;
+    public ViewElement<ToggleTabStackButton> tabSwitcherButtonElement;
 
     @Override
     public void declareElements(Elements.Builder elements) {
-        mTabSwitcherButton = elements.declareView(PageStation.TAB_SWITCHER_BUTTON);
-    }
-
-    public ImageButton getView() {
-        return (ImageButton) mTabSwitcherButton.get();
+        tabSwitcherButtonElement =
+                elements.declareView(
+                    viewSpec(ToggleTabStackButton.class, withId(R.id.tab_switcher_button)));
     }
 
     public String getTextRendered() {
-        TabSwitcherDrawable tabSwitcherDrawable = (TabSwitcherDrawable) getView().getDrawable();
+        TabSwitcherDrawable tabSwitcherDrawable =
+                (TabSwitcherDrawable) tabSwitcherButtonElement.get().getDrawable();
         return tabSwitcherDrawable.getTextRenderedForTesting();
     }
 }
@@ -347,10 +341,6 @@
 
 ```java
 public class PageStation extends Station {
--   public ImageButton getTabSwitcherButton() {
--       return (ImageButton) mTabSwitcherButton.get();
--   }
-
 +   public TabSwitcherButtonFacility focusOnTabSwitcherButton() {
 +       return enterFacilitySync(new TabSwitcherButtonFacility(), /* trigger= */ null);
 +   }
@@ -376,16 +366,18 @@
 }
 ```
 
-It's debatable if the Facility is warranted here just to encapsulate the logic
-of getting the rendered text. To wait on the rendered text with a Condition,
-though, a Facility is necessary. Let's create this Condition.
+The Facility is not really warranted here just to encapsulate the logic of
+getting the rendered text. To wait on the rendered text with a Condition, you
+can subclass Condition or use SimpleConditions. For illustration, let's create a
+subclass, which is recommended for more complex Conditions:
 
 ## Adding a Custom Condition
 
 ```java
 public class TabSwitcherButtonFacility extends Facility<PageStation> {
+    public ViewElement<ToggleTabStackButton> tabSwitcherButtonElement;
+
 +   private final String mExpectedText;
-    private Supplier<View> mTabSwitcherButton;
 
 +   public TabSwitcherButtonFacility(String expectedText) {
 +       mExpectedText = expectedText;
@@ -393,22 +385,24 @@
 
     @Override
     public void declareElements(Elements.Builder elements) {
-        mTabSwitcherButton = elements.declareView(PageStation.TAB_SWITCHER_BUTTON);
+        tabSwitcherButtonElement =
+                elements.declareView(
+                    viewSpec(ToggleTabStackButton.class, withId(R.id.tab_switcher_button)));
 +       elements.declareEnterCondition(new TextRenderedCondition());
     }
 
 +   private class TextRenderedCondition extends Condition {
 +       public TextRenderedCondition() {
 +           super(/* isRunOnUiThread= */ true);
-+           dependOnSupplier(mTabSwitcherButton, "ButtonView");
++           dependOnSupplier(tabSwitcherButtonElement, "ButtonView");
 +       }
 +
 +       @Override
 +       protected ConditionStatus checkWithSuppliers() {
-+           ImageButton button = (ImageButton) mTabSwitcherButton.get();
++           ImageButton button = (ImageButton) tabSwitcherButtonElement.get();
 +           TabSwitcherDrawable tabSwitcherDrawable = (TabSwitcherDrawable) button.getDrawable();
 +           String renderedText = tabSwitcherDrawable.getTextRenderedForTesting();
-+           return whether(mExpectedText.equals(renderedText), "expected=%s actual=%s", mExpectedText, renderedText);
++           return whetherEquals(mExpectedText, renderedText);
 +       }
 +
 +       @Override
@@ -436,8 +430,7 @@
 public class MyPTTest {
     public void testOneTab_I() {
         PageStation page = mCtaTestRule.startOnBlankPage();
-        TabSwitcherButtonFacility tabSwitcherButton = page.focusOnTabSwitcherButton("I");
-+       TransitAsserts.assertFinalDestination(page);
+        page.focusOnTabSwitcherButton("I");
     }
 }
 ```
@@ -461,11 +454,13 @@
 ```java
 public class TabSwitcherButtonFacility extends Facility<PageStation> {
 +   public HubTabSwitcherStation clickToOpenHub() {
-+       return mHostStation.travelToSync(new HubTabSwitcherStation(), () -> PageStation.TAB_SWITCHER_BUTTON.perform(click()));
++       return mHostStation.travelToSync(
++               new HubTabSwitcherStation(), tabSwitcherButtonElement.getClickTrigger());
 +   }
 +
 +   public TabSwitcherActionMenuFacility longClickToOpenActionMenu() {
-+       return mHostStation.enterFacilitySync(new TabSwitcherActionMenuFacility(), () -> PageStation.TAB_SWITCHER_BUTTON.perform(longClick()));
++       return mHostStation.enterFacilitySync(
++               new TabSwitcherActionMenuFacility(), tabSwitcherButtonElement.getLongPressTrigger());
 +   }
 }
 ```
diff --git a/base/tracing/perfetto_platform.cc b/base/tracing/perfetto_platform.cc
index 225f506..0a3ef838 100644
--- a/base/tracing/perfetto_platform.cc
+++ b/base/tracing/perfetto_platform.cc
@@ -27,6 +27,7 @@
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     Options options)
     : process_name_prefix_(std::move(options.process_name_prefix)),
+      defer_delayed_tasks_(options.defer_delayed_tasks),
       task_runner_(std::move(task_runner)),
       thread_local_object_([](void* object) {
         delete static_cast<ThreadLocalObject*>(object);
@@ -49,7 +50,7 @@
   // TODO(b/242965112): Add support for the builtin task runner
   DCHECK(!perfetto_task_runner_);
   auto perfetto_task_runner =
-      std::make_unique<PerfettoTaskRunner>(task_runner_);
+      std::make_unique<PerfettoTaskRunner>(task_runner_, defer_delayed_tasks_);
   perfetto_task_runner_ = perfetto_task_runner->GetWeakPtr();
   return perfetto_task_runner;
 }
diff --git a/base/tracing/perfetto_platform.h b/base/tracing/perfetto_platform.h
index 5deb154..b565ea7 100644
--- a/base/tracing/perfetto_platform.h
+++ b/base/tracing/perfetto_platform.h
@@ -27,6 +27,10 @@
     // TraceConfig.DataSource.producer_name_filter).
     std::string process_name_prefix = "org.chromium-";
 
+    // Defer delayed tasks to PerfettoTaskRunner until task runner resets after
+    // sandbox entry.
+    bool defer_delayed_tasks = false;
+
     // Work around https://bugs.llvm.org/show_bug.cgi?id=36684
     static Options Default() { return {}; }
   };
@@ -50,6 +54,7 @@
 
  private:
   const std::string process_name_prefix_;
+  const bool defer_delayed_tasks_;
   WeakPtr<PerfettoTaskRunner> perfetto_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   ThreadLocalStorage::Slot thread_local_object_;
diff --git a/base/tracing/perfetto_task_runner.cc b/base/tracing/perfetto_task_runner.cc
index ebd0ad8..2a22e005 100644
--- a/base/tracing/perfetto_task_runner.cc
+++ b/base/tracing/perfetto_task_runner.cc
@@ -22,8 +22,10 @@
 namespace base::tracing {
 
 PerfettoTaskRunner::PerfettoTaskRunner(
-    scoped_refptr<base::SequencedTaskRunner> task_runner)
-    : task_runner_(std::move(task_runner)) {
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    bool defer_delayed_tasks)
+    : task_runner_(std::move(task_runner)),
+      defer_delayed_tasks_(defer_delayed_tasks) {
   CHECK(task_runner_);
 }
 
@@ -40,6 +42,10 @@
 
 void PerfettoTaskRunner::PostDelayedTask(std::function<void()> task,
                                          uint32_t delay_ms) {
+  if (defer_delayed_tasks_ && delay_ms) {
+    deferred_delayed_tasks_.emplace_back(task, delay_ms);
+    return;
+  }
   base::ScopedDeferTaskPosting::PostOrDefer(
       task_runner_, FROM_HERE,
       base::BindOnce(
@@ -117,6 +123,11 @@
 void PerfettoTaskRunner::ResetTaskRunner(
     scoped_refptr<base::SequencedTaskRunner> task_runner) {
   task_runner_ = std::move(task_runner);
+  defer_delayed_tasks_ = false;
+  for (auto& task : deferred_delayed_tasks_) {
+    PostDelayedTask(task.task, task.delay);
+  }
+  deferred_delayed_tasks_.clear();
 }
 
 #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
@@ -127,4 +138,12 @@
     default;
 #endif  // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
 
+PerfettoTaskRunner::DeferredTask::DeferredTask(std::function<void()> task,
+                                               uint32_t delay)
+    : task(std::move(task)), delay(delay) {}
+
+PerfettoTaskRunner::DeferredTask::DeferredTask(DeferredTask&& task) = default;
+
+PerfettoTaskRunner::DeferredTask::~DeferredTask() = default;
+
 }  // namespace base::tracing
diff --git a/base/tracing/perfetto_task_runner.h b/base/tracing/perfetto_task_runner.h
index 52bfc02..1e539a5 100644
--- a/base/tracing/perfetto_task_runner.h
+++ b/base/tracing/perfetto_task_runner.h
@@ -5,6 +5,8 @@
 #ifndef BASE_TRACING_PERFETTO_TASK_RUNNER_H_
 #define BASE_TRACING_PERFETTO_TASK_RUNNER_H_
 
+#include <vector>
+
 #include "base/base_export.h"
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
@@ -29,7 +31,8 @@
 // to provide it to Perfetto.
 class BASE_EXPORT PerfettoTaskRunner : public perfetto::base::TaskRunner {
  public:
-  explicit PerfettoTaskRunner(scoped_refptr<base::SequencedTaskRunner>);
+  explicit PerfettoTaskRunner(scoped_refptr<base::SequencedTaskRunner>,
+                              bool defer_delayed_tasks = false);
   ~PerfettoTaskRunner() override;
   PerfettoTaskRunner(const PerfettoTaskRunner&) = delete;
   void operator=(const PerfettoTaskRunner&) = delete;
@@ -58,6 +61,21 @@
  private:
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
+  struct DeferredTask {
+    DeferredTask(std::function<void()> task, uint32_t delay);
+    DeferredTask(const DeferredTask&) = delete;
+    DeferredTask& operator=(const DeferredTask&) = delete;
+    DeferredTask(DeferredTask&& task);
+    ~DeferredTask();
+
+    std::function<void()> task;
+    uint32_t delay;
+  };
+
+  // Delayed tasks will be posted when `task_runner_` resets.
+  std::vector<DeferredTask> deferred_delayed_tasks_;
+  bool defer_delayed_tasks_;
+
 #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
   // FDControllerAndCallback keeps track of the state of FD watching:
   // * |controller| has value: FD watching is added. |callback| is nullopt.
diff --git a/build/android/java/src/org/chromium/build/annotations/MockedInTests.java b/build/android/java/src/org/chromium/build/annotations/MockedInTests.java
index 120864c..8d8db20 100644
--- a/build/android/java/src/org/chromium/build/annotations/MockedInTests.java
+++ b/build/android/java/src/org/chromium/build/annotations/MockedInTests.java
@@ -8,10 +8,7 @@
 import java.lang.annotation.Target;
 
 /**
- * See b/147584922. Proguard and Mockito don't play nicely together, and proguard rules make it
- * impossible to keep the base class/interface for a mocked class without providing additional
- * explicit information, like this annotation. This annotation should only need to be used on a
- * class/interface that is extended/implemented by another class/interface that is then mocked.
+ * Prevents optimization. R8 supports Mockito now, so this should be rarely be needed.
  */
 @Target(ElementType.TYPE)
 public @interface MockedInTests {}
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 6f248e8..fca6c92 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -623,6 +623,13 @@
         default_toolchain != "//build/toolchain/cros:target") {
       cflags += [ "-Wa,--crel,--allow-experimental-crel" ]
     }
+
+    # TODO(crbug.com/413427035): Remove once
+    # https://github.com/llvm/llvm-project/pull/136867/ is landed.
+    if (!is_win && !llvm_android_mainline &&
+        default_toolchain != "//build/toolchain/cros:target") {
+      cflags += [ "-fextend-variable-liveness=none" ]
+    }
   }
 
   # C11/C++11 compiler flags setup.
diff --git a/build/rust/std/rules/BUILD.gn b/build/rust/std/rules/BUILD.gn
index f77241d..a61269db 100644
--- a/build/rust/std/rules/BUILD.gn
+++ b/build/rust/std/rules/BUILD.gn
@@ -288,232 +288,232 @@
 }
 cargo_crate("compiler_builtins") {
   crate_type = "rlib"
-  crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/lib.rs"
+  crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/lib.rs"
   sources = [
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/aarch64.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/aarch64_linux.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/arm.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/arm_linux.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/add.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/cmp.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/conv.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/div.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/extend.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/mul.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/pow.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/sub.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/traits.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/float/trunc.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/hexagon.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/addsub.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/big.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/bswap.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/leading_zeros.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/mul.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/sdiv.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/shift.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/asymmetric.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/binary_long.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/delegate.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/norm_shift.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/specialized_div_rem/trifecta.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/trailing_zeros.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/traits.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/int/udiv.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/lib.miri.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/lib.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/macros.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/math.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/mem/impls.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/mem/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/mem/x86_64.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/probestack.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/riscv.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/x86.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/x86_64.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/aarch64.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/aarch64_linux.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/arm.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/arm_linux.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/add.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/cmp.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/conv.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/div.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/extend.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/mul.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/pow.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/sub.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/traits.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/float/trunc.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/hexagon.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/addsub.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/big.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/bswap.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/leading_zeros.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/mul.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/sdiv.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/shift.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/asymmetric.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/binary_long.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/delegate.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/norm_shift.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/specialized_div_rem/trifecta.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/trailing_zeros.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/traits.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/int/udiv.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/lib.miri.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/lib.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/macros.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/math.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/mem/impls.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/mem/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/mem/x86_64.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/probestack.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/riscv.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/x86.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/x86_64.rs",
   ]
   inputs = [
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/acos.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/acosf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/acosh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/acoshf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/arch/aarch64.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/arch/i586.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/arch/i686.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/arch/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/arch/wasm32.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/asin.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/asinf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/asinh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/asinhf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atan.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atan2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atan2f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atanf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atanh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/atanhf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/cbrt.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/cbrtf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ceil.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ceilf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ceilf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ceilf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/copysign.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/copysignf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/copysignf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/copysignf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/cos.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/cosf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/cosh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/coshf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/erf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/erff.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/exp.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/exp10.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/exp10f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/exp2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/exp2f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/expf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/expm1.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/expm1f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/expo2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fabs.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fabsf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fabsf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fabsf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fdim.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fdimf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fdimf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fdimf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/floor.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/floorf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/floorf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/floorf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fma.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fma_wide.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fmin_fmax.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fminimum_fmaximum.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fminimum_fmaximum_num.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fmod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fmodf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fmodf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/fmodf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/frexp.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/frexpf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/ceil.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/copysign.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fabs.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fdim.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/floor.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fmax.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fmaximum.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fmaximum_num.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fmin.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fminimum.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fminimum_num.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/fmod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/rint.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/round.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/scalbn.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/sqrt.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/generic/trunc.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/hypot.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/hypotf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ilogb.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ilogbf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/j0.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/j0f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/j1.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/j1f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/jn.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/jnf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_cos.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_cosf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_expo2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_expo2f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_sin.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_sinf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_tan.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/k_tanf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ldexp.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ldexpf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ldexpf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/ldexpf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/lgamma.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/lgamma_r.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/lgammaf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/lgammaf_r.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log10.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log10f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log1p.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log1pf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/log2f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/logf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/modf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/modff.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/nextafter.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/nextafterf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/pow.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/powf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/rem_pio2.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/rem_pio2_large.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/rem_pio2f.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/remainder.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/remainderf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/remquo.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/remquof.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/rint.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/round.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/roundeven.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/roundf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/roundf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/roundf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/scalbn.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/scalbnf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/scalbnf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/scalbnf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sin.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sincos.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sincosf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sinf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sinh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sinhf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sqrt.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sqrtf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sqrtf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/sqrtf16.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/big/tests.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/big.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/env.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/float_traits.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/hex_float.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/int_traits.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/macros.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/support/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tan.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tanf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tanh.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tanhf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tgamma.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/tgammaf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/trunc.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/truncf.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/truncf128.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../libm/src/math/truncf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/acos.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/acosf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/acosh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/acoshf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/arch/aarch64.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/arch/i586.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/arch/i686.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/arch/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/arch/wasm32.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/asin.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/asinf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/asinh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/asinhf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atan.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atan2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atan2f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atanf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atanh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/atanhf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/cbrt.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/cbrtf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ceil.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ceilf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ceilf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ceilf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/copysign.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/copysignf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/copysignf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/copysignf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/cos.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/cosf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/cosh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/coshf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/erf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/erff.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/exp.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/exp10.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/exp10f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/exp2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/exp2f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/expf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/expm1.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/expm1f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/expo2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fabs.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fabsf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fabsf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fabsf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fdim.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fdimf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fdimf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fdimf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/floor.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/floorf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/floorf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/floorf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fma.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fma_wide.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fmin_fmax.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fminimum_fmaximum.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fminimum_fmaximum_num.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fmod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fmodf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fmodf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/fmodf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/frexp.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/frexpf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/ceil.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/copysign.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fabs.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fdim.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/floor.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fmax.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fmaximum.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fmaximum_num.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fmin.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fminimum.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fminimum_num.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/fmod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/rint.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/round.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/scalbn.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/sqrt.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/generic/trunc.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/hypot.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/hypotf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ilogb.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ilogbf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/j0.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/j0f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/j1.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/j1f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/jn.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/jnf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_cos.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_cosf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_expo2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_expo2f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_sin.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_sinf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_tan.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/k_tanf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ldexp.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ldexpf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ldexpf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/ldexpf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/lgamma.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/lgamma_r.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/lgammaf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/lgammaf_r.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log10.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log10f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log1p.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log1pf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/log2f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/logf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/modf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/modff.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/nextafter.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/nextafterf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/pow.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/powf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/rem_pio2.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/rem_pio2_large.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/rem_pio2f.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/remainder.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/remainderf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/remquo.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/remquof.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/rint.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/round.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/roundeven.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/roundf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/roundf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/roundf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/scalbn.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/scalbnf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/scalbnf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/scalbnf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sin.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sincos.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sincosf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sinf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sinh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sinhf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sqrt.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sqrtf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sqrtf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/sqrtf16.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/big/tests.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/big.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/env.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/float_traits.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/hex_float.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/int_traits.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/macros.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/support/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tan.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tanf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tanh.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tanhf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tgamma.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/tgammaf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/trunc.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/truncf.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/truncf128.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../libm/src/math/truncf16.rs",
   ]
   no_std = true
 
   # Unit tests skipped. Generate with --with-tests to include them.
   build_native_rust_unit_tests = false
   edition = "2021"
-  cargo_pkg_version = "0.1.152"
+  cargo_pkg_version = "0.1.155"
   cargo_pkg_authors = "Jorge Aparicio <japaricious@gmail.com>"
   cargo_pkg_name = "compiler_builtins"
   cargo_pkg_description = "Compiler intrinsics used by the Rust compiler. Also available for other targets if necessary!"
@@ -541,9 +541,9 @@
     "default",
     "rustc-dep-of-std",
   ]
-  build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/build.rs"
-  build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/build.rs" ]
-  build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.152/src/../configure.rs" ]
+  build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/build.rs"
+  build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/build.rs" ]
+  build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.155/src/../configure.rs" ]
   rustenv = [
     "CFG_DISABLE_UNSTABLE_FEATURES=0",
     "STD_ENV_ARCH=$rust_target_arch",
@@ -573,6 +573,7 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/array/drain.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/array/equality.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/array/iter.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/array/iter/iter_inner.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/array/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ascii.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ascii/ascii_char.rs",
@@ -582,7 +583,8 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/async_iter/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/bool.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/borrow.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/bstr.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/bstr/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/bstr/traits.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/cell.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/cell/lazy.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/cell/once.rs",
@@ -756,6 +758,7 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/panicking.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/pat.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/pin.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/pin/unsafe_pinned.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/prelude/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/prelude/v1.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/primitive.rs",
@@ -1651,20 +1654,22 @@
 }
 cargo_crate("miniz_oxide") {
   crate_type = "rlib"
-  crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/lib.rs"
+  crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/lib.rs"
   sources = [
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/buffer.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/core.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/stored.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/stream.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/deflate/zlib.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/inflate/core.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/inflate/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/inflate/output_buffer.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/inflate/stream.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/lib.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.3/src/shared.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/buffer.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/core.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/stored.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/stream.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/deflate/zlib.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/core.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/output_buffer.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/inflate/stream.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/lib.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/serde/big_array.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/serde/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/miniz_oxide-0.8.8/src/shared.rs",
   ]
   inputs = []
   no_std = true
@@ -1672,7 +1677,7 @@
   # Unit tests skipped. Generate with --with-tests to include them.
   build_native_rust_unit_tests = false
   edition = "2021"
-  cargo_pkg_version = "0.8.3"
+  cargo_pkg_version = "0.8.8"
   cargo_pkg_authors = "Frommi <daniil.liferenko@gmail.com>, oyvindln <oyvindln@users.noreply.github.com>, Rich Geldreich richgel99@gmail.com"
   cargo_pkg_name = "miniz_oxide"
   cargo_pkg_description = "DEFLATE compression and decompression library rewritten in Rust based on miniz"
@@ -2007,6 +2012,7 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   deps = [
     ":core",
+    ":rustc_literal_escaper",
     ":std",
     "//build/rust/std:profiler_builtins_group",
     "//build/rust/std:std_build_deps",
@@ -2113,6 +2119,53 @@
   output_dir =
       "$root_out_dir/local_rustc_sysroot/lib/rustlib/$rust_abi_target/lib/"
 }
+cargo_crate("rustc_literal_escaper") {
+  crate_type = "rlib"
+  crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-literal-escaper-0.0.2/src/lib.rs"
+  sources = [
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-literal-escaper-0.0.2/src/lib.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/rustc-literal-escaper-0.0.2/src/tests.rs",
+  ]
+  inputs = []
+  no_std = true
+
+  # Unit tests skipped. Generate with --with-tests to include them.
+  build_native_rust_unit_tests = false
+  edition = "2021"
+  cargo_pkg_version = "0.0.2"
+  cargo_pkg_name = "rustc-literal-escaper"
+  cargo_pkg_description = "Provides code to unescape string literals"
+  library_configs -= [
+    "//build/config/compiler:chromium_code",
+    "//build/config/compiler:disallow_unstable_features",
+  ]
+  library_configs += [ "//build/config/compiler:no_chromium_code" ]
+  executable_configs -= [
+    "//build/config/compiler:chromium_code",
+    "//build/config/compiler:disallow_unstable_features",
+  ]
+  executable_configs += [ "//build/config/compiler:no_chromium_code" ]
+  deps = [
+    ":rustc_std_workspace_std",
+    "//build/rust/std:profiler_builtins_group",
+    "//build/rust/std:std_build_deps",
+  ]
+  aliased_deps = {
+    std = ":rustc_std_workspace_std"
+  }
+  features = [ "rustc-dep-of-std" ]
+  rustenv = [
+    "CFG_DISABLE_UNSTABLE_FEATURES=0",
+    "STD_ENV_ARCH=$rust_target_arch",
+  ]
+  rustflags = [
+    "--cfg=backtrace_in_libstd",
+    "-Zforce-unstable-if-unmarked",
+    "--cap-lints=allow",  # Suppress all warnings in stdlib crates
+  ]
+  output_dir =
+      "$root_out_dir/local_rustc_sysroot/lib/rustlib/$rust_abi_target/lib/"
+}
 cargo_crate("rustc_std_workspace_alloc") {
   crate_type = "rlib"
   crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/rustc-std-workspace-alloc/lib.rs"
@@ -2506,9 +2559,28 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/anonymous_pipe/unix.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/anonymous_pipe/unsupported.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/anonymous_pipe/windows.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/common.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/hermit.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/sgx.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/uefi.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/unix.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/unsupported.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/wasi.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/windows.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/windows/tests.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/xous.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/args/zkvm.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/cmath.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/env_consts.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/exit_guard.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/hermit.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/sgx.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/unix.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/unix/tests.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fd/wasi.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fs/common.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fs/hermit.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/fs/mod.rs",
@@ -2554,9 +2626,6 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/small_c_string.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/tests.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/env.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/fd.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/futex.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/os.rs",
@@ -2583,9 +2652,6 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/env.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/fd.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/libunwind_integration.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/os.rs",
@@ -2601,7 +2667,6 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/fs.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/sockets.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/error.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/os.rs",
@@ -2610,18 +2675,12 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/os.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/thread.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/trusty/mod.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/helpers.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/os.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/tests.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/thread.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/time.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/env.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fd.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fd/tests.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fuchsia.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/futex.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/kernel_copy.rs",
@@ -2641,17 +2700,12 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_parking.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/time.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/weak.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/args.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/common.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/os.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/pipe.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/thread.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/time.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/env.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/fd.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/helpers.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/os.rs",
@@ -2661,16 +2715,12 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasip2/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/atomics/futex.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/atomics/thread.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/api.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/api/tests.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/args.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/args/tests.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/c.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/c/windows_sys.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/compat.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/futex.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/handle.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/handle/tests.rs",
@@ -2682,7 +2732,6 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/stack_overflow_uwp.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/time.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/args.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/os.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/os/params.rs",
@@ -2690,7 +2739,6 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/thread.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/time.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/abi.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/args.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/env.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/os.rs",
@@ -2809,8 +2857,8 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/native/eager.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/native/lazy.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/native/mod.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/no_threads.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/os.rs",
-    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/statik.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/mod.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/process.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/tests.rs",
@@ -2996,6 +3044,7 @@
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/s390x.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/openbsd/aarch64.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/other.rs",
+    "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/riscv.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/windows/aarch64.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/x86.rs",
     "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/lib.rs",
diff --git a/cc/input/scroll_utils.cc b/cc/input/scroll_utils.cc
index 4204098e..8dd1a6c 100644
--- a/cc/input/scroll_utils.cc
+++ b/cc/input/scroll_utils.cc
@@ -36,4 +36,12 @@
                         std::copysign(delta_y, sign_y));
 }
 
+// static
+int ScrollUtils::CalculatePageStep(int length) {
+  const int min_page_step = length * kMinFractionToStepWhenPaging;
+  const int page_step =
+      std::max(min_page_step, length - kMaxOverlapBetweenPages);
+  return std::max(page_step, 1);
+}
+
 }  // namespace cc
diff --git a/cc/input/scroll_utils.h b/cc/input/scroll_utils.h
index 506e68b..947156e 100644
--- a/cc/input/scroll_utils.h
+++ b/cc/input/scroll_utils.h
@@ -5,6 +5,9 @@
 #ifndef CC_INPUT_SCROLL_UTILS_H_
 #define CC_INPUT_SCROLL_UTILS_H_
 
+#include <limits>
+
+#include "build/build_config.h"
 #include "cc/cc_export.h"
 
 namespace gfx {
@@ -16,6 +19,11 @@
 
 static constexpr int kPixelsPerLineStep = 40;
 static constexpr float kMinFractionToStepWhenPaging = 0.875f;
+#if BUILDFLAG(IS_MAC)
+static constexpr int kMaxOverlapBetweenPages = 40;
+#else
+static constexpr int kMaxOverlapBetweenPages = std::numeric_limits<int>::max();
+#endif  // BUILDFLAG(IS_MAC)
 
 // Class for scroll helper methods in cc and blink.
 class CC_EXPORT ScrollUtils {
@@ -29,6 +37,8 @@
       const gfx::Vector2dF& scroll_delta,
       const gfx::SizeF& scroller_size,
       const gfx::SizeF& viewport_size);
+
+  static int CalculatePageStep(int length);
 };
 
 }  // namespace cc
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc
index 47ce90d4..3814f171 100644
--- a/cc/input/scrollbar_controller.cc
+++ b/cc/input/scrollbar_controller.cc
@@ -714,9 +714,22 @@
         scroll_delta = GetScrollDistanceForAbsoluteJump();
         break;
       }
-      // TODO(savella) Use snapport length instead of viewport length to match
-      // main thread behaviour. See https://crbug.com/1098383.
-      scroll_delta = GetViewportLength() * kMinFractionToStepWhenPaging;
+      int snapport_length = GetViewportLength();
+      const ScrollbarLayerImplBase* scrollbar = ScrollbarLayer();
+      const ScrollNode* target_node =
+          layer_tree_host_impl_->active_tree()
+              ->property_trees()
+              ->scroll_tree()
+              .FindNodeFromElementId(scrollbar->scroll_element_id());
+      if (target_node->snap_container_data) {
+        const gfx::RectF snapport =
+            target_node->snap_container_data.value().rect();
+        snapport_length =
+            scrollbar->orientation() == ScrollbarOrientation::kHorizontal
+                ? snapport.x()
+                : snapport.y();
+      }
+      scroll_delta = ScrollUtils::CalculatePageStep(snapport_length);
       break;
     }
     default:
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index e3462d89..c7392a1 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -3143,6 +3143,8 @@
       CurrentBeginFrameArgs().frame_time;
   metadata.frame_interval_inputs.has_input =
       frame_rate_estimator_.input_priority_mode();
+  metadata.frame_interval_inputs.has_user_input =
+      has_non_fling_input_since_last_frame_;
   has_non_fling_input_since_last_frame_ = false;
 
   if (frame->damage_reasons.Has(DamageReason::kCompositorScroll)) {
@@ -3155,6 +3157,10 @@
       metadata.frame_interval_inputs.major_scroll_speed_in_pixels_per_second =
           frame_max_scroll_delta_ / begin_frame_time_delta_.InSecondsF();
     }
+    metadata.frame_interval_inputs.content_interval_info.push_back(
+        {viz::ContentFrameIntervalType::kCompositorScroll, base::TimeDelta(),
+         1u});
+    frame->damage_reasons.Remove(DamageReason::kCompositorScroll);
   }
 
   if (!frame->video_layer_preferred_intervals.empty() &&
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 661c197d..de6c0adb 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -14662,7 +14662,10 @@
     InputHandlerPointerResult result = GetInputHandler().MouseDown(
         gfx::PointF(350, 400), /*jump_key_modifier*/ false);
     EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll);
-    EXPECT_EQ(result.scroll_delta.y(), 525);
+    EXPECT_EQ(result.scroll_delta.y(),
+              std::max(viewport_size.height() * kMinFractionToStepWhenPaging,
+                       static_cast<float>(viewport_size.height() -
+                                          kMaxOverlapBetweenPages)));
     result = GetInputHandler().MouseUp(gfx::PointF(350, 400));
     EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll);
     EXPECT_EQ(result.scroll_delta.y(), 0);
@@ -14701,7 +14704,10 @@
     InputHandlerPointerResult result = GetInputHandler().MouseDown(
         gfx::PointF(350, 400), /*jump_key_modifier*/ true);
     EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll);
-    EXPECT_EQ(result.scroll_delta.y(), 525);
+    EXPECT_EQ(result.scroll_delta.y(),
+              std::max(viewport_size.height() * kMinFractionToStepWhenPaging,
+                       static_cast<float>(viewport_size.height() -
+                                          kMaxOverlapBetweenPages)));
     result = GetInputHandler().MouseUp(gfx::PointF(350, 400));
     EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll);
     EXPECT_EQ(result.scroll_delta.y(), 0);
@@ -15125,7 +15131,10 @@
       GetInputHandler().MouseDown(gfx::PointF(350, 500),
                                   /*jump_key_modifier*/ false);
   GetInputHandler().MouseUp(gfx::PointF(350, 500));
-  EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(), 525u);
+  EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(),
+            std::max(viewport_size.height() * kMinFractionToStepWhenPaging,
+                     static_cast<float>(viewport_size.height() -
+                                        kMaxOverlapBetweenPages)));
   EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_repaint_reasons);
 
   // Assign a main_thread_scrolling_reason to the scroll node.
@@ -15136,7 +15145,10 @@
   GetInputHandler().MouseUp(gfx::PointF(350, 500));
   // A scrollbar layer track click applies the scroll on the compositor thread
   // even though it has a main thread scrolling reason.
-  EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(), 525u);
+  EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(),
+            std::max(viewport_size.height() * kMinFractionToStepWhenPaging,
+                     static_cast<float>(viewport_size.height() -
+                                        kMaxOverlapBetweenPages)));
 
   // Tear down the LayerTreeHostImpl before the InputHandlerClient.
   host_impl_->ReleaseLayerTreeFrameSink();
diff --git a/chrome/android/features/keyboard_accessory/internal/BUILD.gn b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
index 5b3ea84..4ad7f25 100644
--- a/chrome/android/features/keyboard_accessory/internal/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
@@ -151,8 +151,6 @@
     "java/res/layout/keyboard_accessory_sheet_tab_plus_address_info.xml",
     "java/res/layout/keyboard_accessory_sheet_tab_promo_code_info.xml",
     "java/res/layout/keyboard_accessory_sheet_tab_title.xml",
-    "java/res/layout/keyboard_accessory_suggestion.xml",
-    "java/res/layout/keyboard_accessory_suggestion_large.xml",
     "java/res/layout/password_accessory_passkey_chip.xml",
     "java/res/layout/password_accessory_sheet.xml",
     "java/res/layout/password_accessory_sheet_option.xml",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion.xml
deleted file mode 100644
index 50d02af..0000000
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright 2018 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-
-<org.chromium.components.browser_ui.widget.chips.ChipView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:gravity="center"
-    android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
-    app:iconWidth="@dimen/keyboard_accessory_bar_item_icon_width"
-    style="@style/AssistiveChip" />
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion_large.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion_large.xml
deleted file mode 100644
index a753ce9..0000000
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_suggestion_large.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-
-<org.chromium.components.browser_ui.widget.chips.ChipView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:gravity="center"
-    android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
-    app:iconWidth="@dimen/keyboard_accessory_bar_item_icon_width"
-    style="@style/AssistiveChip"
-    app:verticalInset="2dp" />
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/values/styles.xml b/chrome/android/features/keyboard_accessory/internal/java/res/values/styles.xml
index 28cf5061..749c7745 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/values/styles.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/values/styles.xml
@@ -9,4 +9,12 @@
     <style name="TextAppearance.DividerText" parent="TextAppearance.TextLarge.Secondary">
         <item name="android:textColor">@color/baseline_neutral_70</item>
     </style>
+    <style name="KeyboardAccessoryChip" parent="AssistiveChip">
+        <item name="iconWidth">
+            @dimen/keyboard_accessory_bar_item_icon_width
+        </item>
+    </style>
+    <style name="KeyboardAccessoryLargeChip" parent="KeyboardAccessoryChip">
+        <item name="verticalInset">2dp</item>
+    </style>
 </resources>
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java
index 3acc5b2..4953d45 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java
+++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java
@@ -26,6 +26,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.LayoutRes;
+import androidx.annotation.StyleRes;
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.base.TraceEvent;
@@ -82,8 +83,13 @@
 
     abstract static class BarItemViewHolder<T extends BarItem, V extends View>
             extends RecyclerView.ViewHolder {
+
         BarItemViewHolder(ViewGroup parent, @LayoutRes int layout) {
-            super(LayoutInflater.from(parent.getContext()).inflate(layout, parent, false));
+            this(LayoutInflater.from(parent.getContext()).inflate(layout, parent, false));
+        }
+
+        BarItemViewHolder(View barItem) {
+            super(barItem);
         }
 
         @SuppressWarnings("unchecked")
@@ -115,7 +121,12 @@
                 ViewGroup parent,
                 KeyboardAccessoryView keyboardAccessory,
                 Function<AutofillSuggestion, Drawable> suggestionDrawableFunction) {
-            super(parent, selectLayoutForScale(parent.getContext()));
+            super(
+                    new ChipView(
+                            parent.getContext(),
+                            null,
+                            0,
+                            selectStyleForSuggestion(parent.getContext())));
             mRootViewForIPH = parent.getRootView();
             mKeyboardAccessory = keyboardAccessory;
             mSuggestionDrawableFunction = suggestionDrawableFunction;
@@ -243,14 +254,14 @@
             TraceEvent.end("BarItemChipViewHolder#bind");
         }
 
-        @LayoutRes
-        private static int selectLayoutForScale(Context context) {
+        @StyleRes
+        private static int selectStyleForSuggestion(Context context) {
             if (!ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_ELEGANT_TEXT_HEIGHT)) {
-                return R.layout.keyboard_accessory_suggestion;
+                return R.style.KeyboardAccessoryChip;
             }
             return context.getResources().getConfiguration().fontScale >= LARGE_FONT_THRESHOLD
-                    ? R.layout.keyboard_accessory_suggestion_large
-                    : R.layout.keyboard_accessory_suggestion;
+                    ? R.style.KeyboardAccessoryLargeChip
+                    : R.style.KeyboardAccessoryChip;
         }
     }
 
@@ -270,7 +281,7 @@
 
     static class BarItemActionChipViewHolder extends BarItemViewHolder<BarItem, ChipView> {
         BarItemActionChipViewHolder(ViewGroup parent) {
-            super(parent, R.layout.keyboard_accessory_suggestion);
+            super(new ChipView(parent.getContext(), null, 0, R.style.KeyboardAccessoryChip));
         }
 
         @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupsPane.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupsPane.java
index 8d42cf1..27e8019 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupsPane.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupsPane.java
@@ -103,8 +103,8 @@
             mActionButtonSupplier.set(
                     new DelegateButtonData(
                             new ResourceButtonData(
-                                    R.string.button_new_tab,
-                                    R.string.button_new_tab,
+                                    R.string.button_new_tab_group,
+                                    R.string.button_new_tab_group,
                                     R.drawable.new_tab_icon),
                             flow::newTabGroupFlow));
         }
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 40ebecb..e016b10 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
@@ -2096,8 +2096,12 @@
 
     @VisibleForTesting
     String getLatestTitleForTab(Tab tab, boolean useDefault) {
-        String originalTitle = tab.getTitle();
         if (!mActionsOnAllRelatedTabs || !isTabInTabGroup(tab)) {
+            String originalTitle = tab.getTitle();
+            if (TextUtils.isEmpty(originalTitle)) {
+                String url = tab.getUrl().getSpec();
+                return TextUtils.isEmpty(url) ? "" : url;
+            }
             return originalTitle;
         }
 
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 d3f27a1..d6a8660a 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
@@ -2716,6 +2716,16 @@
     }
 
     @Test
+    public void getLatestTitle_NoTitleUrlFallback() {
+        assertEquals(TAB1_TITLE,
+                mMediator.getLatestTitleForTab(mTab1, /* useDefault= */ true));
+
+        when(mTab1.getTitle()).thenReturn("");
+        assertEquals(TAB1_URL.getSpec(),
+                mMediator.getLatestTitleForTab(mTab1, /* useDefault= */ true));
+    }
+
+    @Test
     public void getLatestTitle_NotGts() {
         setUpTabListMediator(TabListMediatorType.TAB_GRID_DIALOG, TabListMode.GRID);
 
diff --git a/chrome/android/features/tab_ui/public/BUILD.gn b/chrome/android/features/tab_ui/public/BUILD.gn
index 88e8ada..8d939dbe 100644
--- a/chrome/android/features/tab_ui/public/BUILD.gn
+++ b/chrome/android/features/tab_ui/public/BUILD.gn
@@ -36,7 +36,7 @@
     "android/java/res/drawable-xxxhdpi/tabstrip_keyfocus_10dp.9.png",
     "android/java/res/drawable-xxxhdpi/tabstrip_keyfocus_11dp.9.png",
     "android/java/res/drawable-xxxhdpi/tabstrip_keyfocus_8dp.9.png",
-    "android/java/res/drawable/close_button_keyfocus.xml",
+    "android/java/res/drawable/circular_button_keyfocus.xml",
     "android/java/res/values/colors.xml",
     "android/java/res/values/dimens.xml",
   ]
diff --git a/chrome/android/features/tab_ui/public/android/java/res/drawable/close_button_keyfocus.xml b/chrome/android/features/tab_ui/public/android/java/res/drawable/circular_button_keyfocus.xml
similarity index 100%
rename from chrome/android/features/tab_ui/public/android/java/res/drawable/close_button_keyfocus.xml
rename to chrome/android/features/tab_ui/public/android/java/res/drawable/circular_button_keyfocus.xml
diff --git a/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java b/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
index a828c188..459ef384 100644
--- a/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
+++ b/chrome/android/features/tab_ui/public/android/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeUtil.java
@@ -199,8 +199,8 @@
     }
 
     /** {@return The {@link DrawableRes} for the close button keyboard focus ring} */
-    public static @DrawableRes int getCloseButtonKeyboardFocusDrawableRes() {
-        return R.drawable.close_button_keyfocus;
+    public static @DrawableRes int getCircularButtonKeyboardFocusDrawableRes() {
+        return R.drawable.circular_button_keyfocus;
     }
 
     /** {@return The keyboard focus ring's offset in px} */
diff --git a/chrome/android/java/res/layout/incognito_description_layout.xml b/chrome/android/java/res/layout/incognito_description_layout.xml
index f39d2d8..7bf9a07 100644
--- a/chrome/android/java/res/layout/incognito_description_layout.xml
+++ b/chrome/android/java/res/layout/incognito_description_layout.xml
@@ -14,12 +14,13 @@
     android:layout_height="wrap_content"
     android:gravity="start"
     android:orientation="vertical"
-    android:paddingStart="@dimen/md_incognito_ntp_padding_left" >
+    android:paddingStart="@dimen/md_incognito_ntp_padding_horizontal" >
 
     <ImageView
         android:id="@+id/new_tab_incognito_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset"
         tools:ignore="ContentDescription"
         android:src="@drawable/incognito_splash"
         app:tint="@color/ntp_incognito_icon_color" />
@@ -63,6 +64,7 @@
         android:id="@+id/learn_more"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:paddingHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset"
         android:minHeight="@dimen/min_touch_target_size"
         android:gravity="center_vertical"
         android:text="@string/learn_more"
@@ -73,6 +75,7 @@
         android:id="@+id/cookie_card_stub"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset"
         android:layout_marginTop="12dp" />
 
 </org.chromium.chrome.browser.ntp.IncognitoDescriptionView>
diff --git a/chrome/android/java/res/layout/incognito_tracking_protection_card.xml b/chrome/android/java/res/layout/incognito_tracking_protection_card.xml
index 722152e1..0b1a9d4f 100644
--- a/chrome/android/java/res/layout/incognito_tracking_protection_card.xml
+++ b/chrome/android/java/res/layout/incognito_tracking_protection_card.xml
@@ -15,7 +15,8 @@
     android:gravity="start"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="16dp">
+    android:paddingVertical="@dimen/md_incognito_ntp_padding_vertical"
+    android:paddingHorizontal="@dimen/md_incognito_ntp_padding_horizontal">
 
     <org.chromium.ui.widget.TextViewWithLeading
         android:id="@+id/tracking_protection_card_title"
@@ -23,7 +24,8 @@
         android:textAppearance="@style/TextAppearance.TextLarge.Primary.Baseline.Light"
         android:layout_marginBottom="@dimen/md_incognito_ntp_line_spacing"
         android:layout_height="wrap_content"
-        android:layout_width="match_parent" />
+        android:layout_width="match_parent"
+        android:paddingHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset" />
 
     <org.chromium.ui.widget.TextViewWithLeading
         android:id="@+id/tracking_protection_description_one"
@@ -31,6 +33,7 @@
         android:layout_marginBottom="@dimen/md_incognito_ntp_line_spacing"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
+        android:paddingHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset"
         android:visibility="gone"
         style="@style/IncognitoNewTabTextView" />
 
@@ -38,6 +41,7 @@
         android:id="@+id/tracking_protection_description_two"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
+        android:paddingHorizontal="@dimen/md_incognito_ntp_view_horizontal_offset"
         style="@style/IncognitoNewTabTextView" />
 
 </LinearLayout>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 903c79ae..24f11a8 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -139,7 +139,11 @@
     <dimen name="content_suggestions_card_bottom_margin">12dp</dimen>
     <!-- This is in sp because we want the icon to scale with the TextView it sits alongside. -->
     <dimen name="md_incognito_ntp_line_spacing">6sp</dimen>
-    <dimen name="md_incognito_ntp_padding_left">16dp</dimen>
+    <dimen name="md_incognito_ntp_padding_horizontal">12dp</dimen>
+    <dimen name="md_incognito_ntp_padding_vertical">16dp</dimen>
+    <!-- This offset is to account for the span background stroke horizontal padding for clickable
+    text flushed to the edges of the incognito NTP's TextView's. -->
+    <dimen name="md_incognito_ntp_view_horizontal_offset">@dimen/span_background_horizontal_padding</dimen>
 
     <!-- NTP Feed dimensions -->
     <dimen name="feed_header_menu_max_width">225dp</dimen>
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
index 561981b..c4357a3 100644
--- a/chrome/android/java/res/xml/privacy_preferences.xml
+++ b/chrome/android/java/res/xml/privacy_preferences.xml
@@ -57,7 +57,10 @@
 
     <PreferenceCategory
         android:key="security_section"
-        android:title="@string/security_section_title" />
+      android:title="@string/security_section_title" />
+     <org.chromium.chrome.browser.safety_hub.SafetyHubExpandablePreference
+            android:key="advanced_protection_info"
+            android:title="@string/settings_privacy_and_security_advanced_protection_section_title"/>
     <Preference
         android:key="safe_browsing"
         android:title="@string/prefs_safe_browsing_title"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
index 03d6bfedc..4444853 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
@@ -4,6 +4,11 @@
 
 package org.chromium.chrome.browser;
 
+import static org.chromium.ui.KeyboardUtils.ALT;
+import static org.chromium.ui.KeyboardUtils.CTRL;
+import static org.chromium.ui.KeyboardUtils.NO_MODIFIER;
+import static org.chromium.ui.KeyboardUtils.SHIFT;
+
 import android.content.Context;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
@@ -30,6 +35,7 @@
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.device.gamepad.GamepadList;
+import org.chromium.ui.KeyboardUtils;
 import org.chromium.ui.accessibility.AccessibilityState;
 import org.chromium.ui.base.DeviceFormFactor;
 
@@ -41,10 +47,6 @@
 /** Implements app-level keyboard shortcuts for ChromeTabbedActivity and DocumentActivity. */
 public class KeyboardShortcuts {
 
-    private static final int CTRL = 1 << 31;
-    private static final int ALT = 1 << 30;
-    private static final int SHIFT = 1 << 29;
-    private static final int NO_MODIFIER = 0;
     private static final LinkedHashMap<Integer, KeyboardShortcutDefinition>
             KEYBOARD_SHORTCUT_DEFINITION_MAP = new LinkedHashMap<>();
     private static final HashMap<Integer, Integer> KEYBOARD_SHORTCUT_SEMANTIC_MAP = new HashMap<>();
@@ -282,9 +284,6 @@
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_FOCUS_ON_INACTIVE_DIALOGS;
 
                 // Bookmarks.
-            case KeyEvent.KEYCODE_BOOKMARK:
-            case CTRL | KeyEvent.KEYCODE_D:
-                return KeyboardShortcutsSemanticMeaning.BOOKMARK_PAGE;
             case CTRL | SHIFT | KeyEvent.KEYCODE_D:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_BOOKMARK_ALL_TABS;
                 // TODO(crbug.com/412427797): Conform shortcut to KeyboardShortcutDefinition
@@ -310,40 +309,17 @@
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_TASK_MANAGER;
 
                 // Downloads.
-            case CTRL | KeyEvent.KEYCODE_S:
-                return KeyboardShortcutsSemanticMeaning.SAVE_PAGE;
             case CTRL | KeyEvent.KEYCODE_J:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_SHOW_DOWNLOADS;
 
                 // History.
-            case ALT | KeyEvent.KEYCODE_DPAD_LEFT:
-                return KeyboardShortcutsSemanticMeaning.HISTORY_GO_BACK;
-            case ALT | KeyEvent.KEYCODE_DPAD_RIGHT:
-            case KeyEvent.KEYCODE_FORWARD:
-            case KeyEvent.KEYCODE_BUTTON_START:
-                return KeyboardShortcutsSemanticMeaning.HISTORY_GO_FORWARD;
             case CTRL | SHIFT | KeyEvent.KEYCODE_DEL:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_CLEAR_BROWSING_DATA;
 
                 // Print.
-            case CTRL | KeyEvent.KEYCODE_P:
-                return KeyboardShortcutsSemanticMeaning.PRINT;
             case CTRL | SHIFT | KeyEvent.KEYCODE_P:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_BASIC_PRINT;
 
-                // Zoom controls.
-            case CTRL | KeyEvent.KEYCODE_PLUS:
-            case CTRL | KeyEvent.KEYCODE_EQUALS:
-            case CTRL | SHIFT | KeyEvent.KEYCODE_PLUS:
-            case CTRL | SHIFT | KeyEvent.KEYCODE_EQUALS:
-            case KeyEvent.KEYCODE_ZOOM_IN:
-                return KeyboardShortcutsSemanticMeaning.ZOOM_IN;
-            case CTRL | KeyEvent.KEYCODE_MINUS:
-            case KeyEvent.KEYCODE_ZOOM_OUT:
-                return KeyboardShortcutsSemanticMeaning.ZOOM_OUT;
-            case CTRL | KeyEvent.KEYCODE_0:
-                return KeyboardShortcutsSemanticMeaning.ZOOM_RESET;
-
                 // Misc.
             case CTRL | SHIFT | KeyEvent.KEYCODE_M:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_AVATAR_MENU;
@@ -352,9 +328,6 @@
             case ALT | KeyEvent.KEYCODE_HOME:
             case KeyEvent.KEYCODE_HOME:
                 return KeyboardShortcutsSemanticMeaning.NOT_IMPLEMENTED_HOME;
-            case CTRL | SHIFT | KeyEvent.KEYCODE_SLASH: // i.e. Ctrl+?
-            case KeyEvent.KEYCODE_F1:
-                return KeyboardShortcutsSemanticMeaning.OPEN_HELP;
         }
 
         return KeyboardShortcutsSemanticMeaning.UNKNOWN;
@@ -643,14 +616,35 @@
                     new KeyCombo(KeyEvent.KEYCODE_F10, NO_MODIFIER),
                     new KeyCombo(KeyEvent.KEYCODE_BUTTON_Y, NO_MODIFIER)
                 });
+
+        // History shortcuts
         new KeyboardShortcutDefinition(
                 KeyboardShortcutsSemanticMeaning.OPEN_HISTORY,
                 new KeyCombo(KeyEvent.KEYCODE_H, KeyEvent.META_CTRL_ON),
                 R.string.keyboard_shortcut_history_manager,
                 R.string.keyboard_shortcut_chrome_feature_group_header);
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.HISTORY_GO_BACK,
+                new KeyCombo(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_ALT_ON),
+                R.string.keyboard_shortcut_history_go_back,
+                R.string.keyboard_shortcut_chrome_feature_group_header);
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.HISTORY_GO_FORWARD,
+                new KeyCombo(KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_ALT_ON),
+                R.string.keyboard_shortcut_history_go_forward,
+                R.string.keyboard_shortcut_chrome_feature_group_header,
+                new KeyCombo[] {
+                    new KeyCombo(KeyEvent.KEYCODE_FORWARD, NO_MODIFIER),
+                    new KeyCombo(KeyEvent.KEYCODE_BUTTON_START, NO_MODIFIER)
+                });
 
         // Bookmark shortcuts.
         new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.BOOKMARK_PAGE,
+                new KeyCombo(KeyEvent.KEYCODE_D, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_bookmark_page,
+                R.string.keyboard_shortcut_chrome_feature_group_header);
+        new KeyboardShortcutDefinition(
                 KeyboardShortcutsSemanticMeaning.OPEN_BOOKMARKS,
                 new KeyCombo(KeyEvent.KEYCODE_O, (KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)),
                 R.string.keyboard_shortcut_bookmark_manager,
@@ -665,12 +659,54 @@
                     R.string.keyboard_shortcut_developer_tools,
                     R.string.keyboard_shortcut_developer_group_header);
         }
-    }
 
-    private static int getMetaState(KeyEvent event) {
-        return (event.isCtrlPressed() ? CTRL : 0)
-                | (event.isAltPressed() ? ALT : 0)
-                | (event.isShiftPressed() ? SHIFT : 0);
+        // Webpage shortcuts (keyboard_shortcut_webpage_group_header).
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.PRINT,
+                new KeyCombo(KeyEvent.KEYCODE_P, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_print_page,
+                R.string.keyboard_shortcut_webpage_group_header);
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.SAVE_PAGE,
+                new KeyCombo(KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_save_page,
+                R.string.keyboard_shortcut_webpage_group_header);
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.ZOOM_IN,
+                new KeyCombo(KeyEvent.KEYCODE_PLUS, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_zoom_in,
+                R.string.keyboard_shortcut_webpage_group_header,
+                new KeyCombo[] {
+                    new KeyCombo(KeyEvent.KEYCODE_ZOOM_IN, NO_MODIFIER),
+                    new KeyCombo(KeyEvent.KEYCODE_EQUALS, KeyEvent.META_CTRL_ON),
+                    new KeyCombo(
+                            KeyEvent.KEYCODE_PLUS,
+                            (KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)),
+                    new KeyCombo(
+                            KeyEvent.KEYCODE_EQUALS,
+                            (KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON))
+                });
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.ZOOM_OUT,
+                new KeyCombo(KeyEvent.KEYCODE_MINUS, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_zoom_out,
+                R.string.keyboard_shortcut_webpage_group_header,
+                new KeyCombo[] {new KeyCombo(KeyEvent.KEYCODE_ZOOM_OUT, NO_MODIFIER)});
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.ZOOM_RESET,
+                new KeyCombo(KeyEvent.KEYCODE_0, KeyEvent.META_CTRL_ON),
+                R.string.keyboard_shortcut_reset_zoom,
+                R.string.keyboard_shortcut_webpage_group_header);
+        new KeyboardShortcutDefinition(
+                KeyboardShortcutsSemanticMeaning.OPEN_HELP,
+                new KeyCombo(KeyEvent.KEYCODE_F1, NO_MODIFIER),
+                R.string.keyboard_shortcut_help_center,
+                R.string.keyboard_shortcut_webpage_group_header,
+                new KeyCombo[] {
+                    new KeyCombo(
+                            KeyEvent.KEYCODE_SLASH,
+                            (KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON))
+                });
     }
 
     /**
@@ -717,17 +753,23 @@
                 }
                 return true;
             case KeyEvent.KEYCODE_ESCAPE:
-                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                    if (fullscreenManager.getPersistentFullscreenMode()) {
-                        fullscreenManager.exitPersistentFullscreenMode();
-                        return true;
-                    }
-                    if (getMetaState(event) == CTRL
-                            && ChromeFeatureList.isEnabled(ChromeFeatureList.TASK_MANAGER_CLANK)) {
-                        TaskManager taskManager = TaskManagerFactory.createTaskManager();
-                        taskManager.launch(context);
-                        return true;
-                    }
+                if (event.getAction() != KeyEvent.ACTION_DOWN || event.getRepeatCount() != 0) {
+                    break;
+                }
+
+                // Exiting full screen takes priority over other actions when Escape is pressed,
+                // regardless of modifier keys. This means for example that you cannot open the task
+                // manager in full screen mode.
+                if (fullscreenManager.getPersistentFullscreenMode()) {
+                    fullscreenManager.exitPersistentFullscreenMode();
+                    return true;
+                }
+
+                if (KeyboardUtils.getMetaState(event) == CTRL
+                        && ChromeFeatureList.isEnabled(ChromeFeatureList.TASK_MANAGER_CLANK)) {
+                    TaskManager taskManager = TaskManagerFactory.createTaskManager();
+                    taskManager.launch(context);
+                    return true;
                 }
                 break;
             case KeyEvent.KEYCODE_TV:
@@ -762,13 +804,9 @@
      * @return a list of shortcuts organized into groups.
      */
     public static List<KeyboardShortcutGroup> createShortcutGroup(Context context) {
-        final int ctrlShift = KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON;
-
         LinkedHashMap<Integer, KeyboardShortcutGroup> shortcutGroupsById = new LinkedHashMap<>();
-
         for (KeyboardShortcutDefinition shortcutDefinition :
                 KEYBOARD_SHORTCUT_DEFINITION_MAP.values()) {
-
             int groupId = shortcutDefinition.mGroupId;
             if (!shortcutGroupsById.containsKey(groupId)) {
                 shortcutGroupsById.put(
@@ -790,53 +828,9 @@
                     shortcutGroupsById.get(R.string.keyboard_shortcut_chrome_feature_group_header),
                     R.string.keyboard_shortcut_toggle_bookmark_bar,
                     KeyEvent.KEYCODE_B,
-                    ctrlShift);
+                    (KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON));
         }
-
-        List<KeyboardShortcutGroup> shortcutGroups = new ArrayList<>(shortcutGroupsById.values());
-
-        KeyboardShortcutGroup webpageShortcutGroup =
-                new KeyboardShortcutGroup(
-                        context.getString(R.string.keyboard_shortcut_webpage_group_header));
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_print_page,
-                KeyEvent.KEYCODE_P,
-                KeyEvent.META_CTRL_ON);
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_bookmark_page,
-                KeyEvent.KEYCODE_D,
-                KeyEvent.META_CTRL_ON);
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_zoom_in,
-                KeyEvent.KEYCODE_EQUALS,
-                KeyEvent.META_CTRL_ON);
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_zoom_out,
-                KeyEvent.KEYCODE_MINUS,
-                KeyEvent.META_CTRL_ON);
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_reset_zoom,
-                KeyEvent.KEYCODE_0,
-                KeyEvent.META_CTRL_ON);
-        addShortcut(
-                context,
-                webpageShortcutGroup,
-                R.string.keyboard_shortcut_help_center,
-                KeyEvent.KEYCODE_SLASH,
-                ctrlShift);
-        shortcutGroups.add(webpageShortcutGroup);
-
-        return shortcutGroups;
+        return new ArrayList<>(shortcutGroupsById.values());
     }
 
     private static void addShortcut(
@@ -907,7 +901,7 @@
         WebContents currentWebContents = currentTab == null ? null : currentTab.getWebContents();
 
         int tabCount = currentTabModel.getCount();
-        int metaState = getMetaState(event);
+        int metaState = KeyboardUtils.getMetaState(event);
         int keyCodeAndMeta = keyCode | metaState;
         @KeyboardShortcutsSemanticMeaning
         int semanticMeaning = getKeyboardSemanticMeaning(keyCodeAndMeta);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerOpenerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerOpenerImpl.java
index 23a37ee..bb7d26b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerOpenerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerOpenerImpl.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileIntentUtils;
+import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -116,6 +117,7 @@
         Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
         intent.putExtra(
                 Browser.EXTRA_APPLICATION_ID, context.getApplicationContext().getPackageName());
+        IntentHandler.setTabLaunchType(intent, TabLaunchType.FROM_CHROME_UI);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         if (componentName != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegate.java
index 94d13d85..c8f1a59 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegate.java
@@ -12,7 +12,77 @@
 import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackScroller;
 import org.chromium.ui.base.LocalizationUtils;
 
-/** Delegate to manage the scrolling logic for the tab strip. */
+/**
+ * Delegate to manage the scrolling logic for the tab strip.
+ *
+ * <p><b>Important</b>: UI values managed by this class, unless documented otherwise, are in a
+ * <i>dynamic</i> coordinate system, depending on whether the layout is LTR or RTL. This covers:
+ *
+ * <ul>
+ *   <li>internal UI states, such as "scroll offset" vectors,
+ *   <li>parameters passed to public methods, such as a "delta" vector,
+ *   <li>return values of public methods.
+ * </ul>
+ *
+ * <p>For LTR layouts, this class uses the following coordinate system:
+ *
+ * <pre>
+ *     (0,0) (top-left corner of the window)
+ *     +----------------> X
+ *     |
+ *     |
+ *     |
+ *     |
+ *    \|/
+ *     Y
+ * </pre>
+ *
+ * For RTL layouts, this class uses the following coordinate system:
+ *
+ * <pre>
+ *                        (0, 0) (top-right corner of the window)
+ *     X <----------------+
+ *                        |
+ *                        |
+ *                        |
+ *                        |
+ *                       \|/
+ *                        Y
+ * </pre>
+ *
+ * <p>In practice, the following is expected from callers:
+ *
+ * <ul>
+ *   <li>For LTR layouts, no action is needed since the dynamic coordinate system is the same as the
+ *       window coordinate system.
+ *   <li>For RTL layouts: callers must flip input before passing it to this class if the input is a
+ *       1-D vector on the X axis under the window coordinate system. Similarly, callers must also
+ *       flip output from this class before applying it to the window coordinate system.
+ * </ul>
+ *
+ * <p>Example:
+ *
+ * <pre><code>
+ *     // Vector under the window coordinate system, meaning "scroll to the right by 10dp".
+ *     float newScrollOffset = 10.0;
+ *
+ *     // Convert the vector to the dynamic coordinate system before passing it to this class.
+ *     float newScrollOffsetForScrollDelegate =
+ *       MathUtils.flipSignIf(newScrollOffset, LocalizationUtils.isLayoutRtl());
+ *     scrollDelegate.setScrollOffset(newScrollOffsetForScrollDelegate);
+ *
+ *    // Vector under the dynamic coordinate system
+ *    float currentScrollOffset = scrollDelegate.getScrollOffset();
+ *
+ *    // Before using the vector under the window coordinate system, convert the vector.
+ *    float scrollOffsetToBeUsed =
+ *      MathUtils.flipSignIf(currentScrollOffset, LocalizationUtils.isLayoutRtl());
+ * </code></pre>
+ *
+ * <p>Due to historical reasons, a lot of existing code already uses this class in the way
+ * documented above, so it requires time and effort to migrate this class to the <b>static</b>
+ * window coordinate system that doesn't change due to layout configurations (LTR/RTL).
+ */
 public class ScrollDelegate {
     // Constants.
     private static final int SCROLL_DURATION_MS = 250;
@@ -23,25 +93,34 @@
     private static final float EPSILON = 0.001f;
 
     // External influences.
-    private StackScroller mScroller;
+    private final StackScroller mScroller;
 
     // Internal state.
     /**
-     * mScrollOffset represents how far left or right the tab strip is currently scrolled. This is 0
-     * when scrolled all the way left and mMinScrollOffset when scrolled all the way right.
+     * A 1-D vector on the X axis under the dynamic coordinate system (see class doc). It represents
+     * the direction and distance the tab strip is currently scrolled.
+     *
+     * <p>This is 0 when the tab strip is not scrolled and {@code mScrollOffsetLimit} when scrolled
+     * all the way to the limit.
      */
     private float mScrollOffset;
 
     /**
-     * mMinScrollOffset is the scroll offset when the tab strip is scrolled all the way to the
-     * right. e.g. this is ~(totalViewWidth - stripWidth) if the tab strip can scroll, and 0
-     * otherwise.
+     * A 1-D vector on the X axis under the dynamic coordinate system (see class doc). It represents
+     * the direction and maximum distance the tab strip can be scrolled.
+     *
+     * <p>This is 0 when the tab strip can't be scrolled (i.e., all tabs are visible), and
+     * approximately (tabStripWidth - totalTabWidth) otherwise. Note that when the value is not 0,
+     * it's always negative, no matter if the layout is LTR or RTL. This is because this vector is
+     * under the dynamic coordinate system (see class doc).
      */
-    private float mMinScrollOffset;
+    private float mScrollOffsetLimit;
 
     /**
-     * Additional space allocated at the start of the tab strip to allow dragging out of a tab
-     * group, if needed.
+     * A scalar value representing the additional space allocated at the start of the tab strip to
+     * allow dragging out of a tab group, if needed.
+     *
+     * <p>This value should always be non-negative.
      */
     private float mReorderStartMargin;
 
@@ -50,7 +129,7 @@
     }
 
     /**
-     * @return The current scroll offset.
+     * @return The current scroll offset under the dynamic coordinate system (see class doc).
      */
     public float getScrollOffset() {
         return mScrollOffset;
@@ -59,12 +138,14 @@
     /**
      * Sets the new scroll offset, and clamps to a valid value.
      *
-     * @param scrollOffset The new scroll offset.
-     * @return The difference between the new and old scroll offsets, accounting for RTL.
+     * @param scrollOffset The new scroll offset under the dynamic coordinate system (see class
+     *     doc).
+     * @return The 1-D vector along the X axis from the new scroll offset to the old scroll offset,
+     *     under the <b>window</b> coordinate system (see class doc).
      */
     public float setScrollOffset(float scrollOffset) {
         float oldScrollOffset = mScrollOffset;
-        mScrollOffset = MathUtils.clamp(scrollOffset, mMinScrollOffset, 0);
+        mScrollOffset = MathUtils.clamp(scrollOffset, mScrollOffsetLimit, 0);
 
         return MathUtils.flipSignIf(
                 oldScrollOffset - mScrollOffset, LocalizationUtils.isLayoutRtl());
@@ -85,7 +166,7 @@
     }
 
     /**
-     * Calculate the new minimum scroll offset based on the strip's current properties. Called on
+     * Calculate the new scroll offset limit based on the strip's current properties. Called on
      * every layout update.
      *
      * @param stripViews List of all views on the tab strip.
@@ -135,14 +216,16 @@
         // 3. Correct fencepost error in totalViewWidth;
         totalViewWidth = totalViewWidth + tabOverlapWidth;
 
-        // 4. Calculate the minimum scroll offset.
-        mMinScrollOffset = Math.min(0.f, stripWidth - totalViewWidth);
+        // 4. Calculate the scroll offset limit.
+        // Note that this is always non-positive under the dynamic coordinate system (see class
+        // doc).
+        mScrollOffsetLimit = Math.min(0.f, stripWidth - totalViewWidth);
 
-        // 5. Always include the reorder start margin in the minScrollOffset calculations, so it
+        // 5. Always include the reorder start margin in the scrollOffsetLimit calculations, so it
         // can be scrolled offscreen, regardless of how full the rest of the strip is. If needed,
         // round > -EPSILON to 0.
-        mMinScrollOffset -= mReorderStartMargin;
-        if (mMinScrollOffset > -EPSILON) mMinScrollOffset = 0.f;
+        mScrollOffsetLimit -= mReorderStartMargin;
+        if (mScrollOffsetLimit > -EPSILON) mScrollOffsetLimit = 0.f;
 
         // 6. Clamp mScrollOffset to make sure it's in the valid range.
         setScrollOffset(mScrollOffset);
@@ -150,7 +233,7 @@
 
     /**
      * Adjusts the scroll offset based on the change in start margin to make it appear as though the
-     * interacting tab does not move. Also adjusts the minScrollOffset accordingly (without
+     * interacting tab does not move. Also adjusts {@code mScrollOffsetLimit} accordingly (without
      * calculating from scratch) to ensure the new scroll offset will be valid.
      *
      * @param newStartMargin The new reorder start margin.
@@ -159,10 +242,10 @@
         float delta = newStartMargin - mReorderStartMargin;
         mReorderStartMargin = newStartMargin;
 
-        // Adjusts the minScrollOffset here, since the next update cycle (which accounts for the new
-        // reorderStartMargin) will not yet have run.
-        mMinScrollOffset -= delta;
-        if (mMinScrollOffset > -EPSILON) mMinScrollOffset = 0.f;
+        // Adjusts the scrollOffSetLimit here, since the next update cycle (which accounts for the
+        // new reorderStartMargin) will not yet have run.
+        mScrollOffsetLimit -= delta;
+        if (mScrollOffsetLimit > -EPSILON) mScrollOffsetLimit = 0.f;
 
         // Auto-scroll to prevent any apparent movement.
         setScrollOffset(mScrollOffset - delta);
@@ -193,7 +276,8 @@
      * Scroll a given distance from the current position.
      *
      * @param time The current time of the app in ms.
-     * @param delta The signed distance to scroll from the current position.
+     * @param delta The signed distance to scroll from the current position, under the dynamic
+     *     coordinate system (see class doc).
      * @param animate Whether or not this should be animated.
      */
     void startScroll(long time, float delta, boolean animate) {
@@ -214,7 +298,8 @@
      * Scroll in response to a fling.
      *
      * @param time The current time of the app in ms.
-     * @param velocity The velocity in the x direction.
+     * @param velocity The velocity in the x direction, under the dynamic coordinate system (see
+     *     class doc).
      */
     void fling(long time, float velocity) {
         // 1. If we're fast scrolling, figure out the destination of the scroll so we can apply it
@@ -231,7 +316,7 @@
                 /* startY= */ 0,
                 (int) velocity,
                 /* velocityY= */ 0,
-                (int) mMinScrollOffset,
+                (int) mScrollOffsetLimit,
                 /* maxX= */ 0,
                 /* minY= */ 0,
                 /* maxY= */ 0,
@@ -242,18 +327,31 @@
     }
 
     /**
-     * @param isLeft Whether the offset from the left or right side should be returned.
-     * @return The delta from the current scroll offset from the min/max scroll offset based on the
-     *     requested side.
+     * Calculates a 1-D vector under the window coordinate system that represents the delta from the
+     * first/last tab's edge to the tab strip's edge.
+     *
+     * <pre>
+     *     isLeft = true
+     *       LTR layout: vector (first tab's left edge --> tab strip's left edge)
+     *       RTL layout: vector (last tab's left edge --> tab strip's left edge)
+     *     isLeft = false
+     *       LTR layout: vector (last tab's right edge --> tab strip's right edge)
+     *       RTL layout: vector (first tab's right edge --> tab strip's right edge)
+     * </pre>
+     *
+     * @param isLeft Whether the offset for the left or right side should be returned.
+     * @return the 1-D vector as documented above.
      */
     float getEdgeOffset(boolean isLeft) {
+        // Under the dynamic coordinate system used by this class (see class doc):
+        //
         // In RTL, scroll position 0 is on the right side of the screen, whereas in LTR scroll
         // position 0 is on the left. Account for that in the offset calculation.
         boolean isRtl = LocalizationUtils.isLayoutRtl();
         boolean useUnadjustedScrollOffset = isRtl != isLeft;
         float scrollOffset = mScrollOffset;
 
-        return -(useUnadjustedScrollOffset ? scrollOffset : (mMinScrollOffset - scrollOffset));
+        return -(useUnadjustedScrollOffset ? scrollOffset : (mScrollOffsetLimit - scrollOffset));
     }
 
     /**
@@ -277,24 +375,26 @@
     /**
      * Directly sets the scroll offset. This may temporarily set it to an un-clamped value.
      *
-     * @param scrollOffset The new scroll offset.
+     * @param scrollOffset The new scroll offset under the dynamic coordinate system (see class
+     *     doc).
      */
     void setNonClampedScrollOffsetForTesting(float scrollOffset) {
         mScrollOffset = scrollOffset;
     }
 
     /**
-     * @param minScrollOffset The minimum scroll offset.
+     * @param scrollOffsetLimit The scroll offset limit under the dynamic coordinate system (see
+     *     class doc).
      */
-    void setMinScrollOffsetForTesting(float minScrollOffset) {
-        mMinScrollOffset = minScrollOffset;
+    void setScrollOffsetLimitForTesting(float scrollOffsetLimit) {
+        mScrollOffsetLimit = scrollOffsetLimit;
     }
 
     /**
-     * @return The minimum scroll offset.
+     * @return The scroll offset limit under the dynamic coordinate system (see class doc).
      */
-    float getMinScrollOffsetForTesting() {
-        return mMinScrollOffset;
+    float getScrollOffsetLimitForTesting() {
+        return mScrollOffsetLimit;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
index f9e98186..1aa7492 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -3302,7 +3302,7 @@
                 resizeTabStrip(false, false, false);
             } else {
                 // If off-screen, request an update so we re-calculate tab initial positions and the
-                // minimum scroll offset.
+                // scroll offset limit.
                 mUpdateHost.requestUpdate();
             }
         }
@@ -3951,40 +3951,35 @@
 
     /**
      * @param tab The tab to make fully visible.
-     * @return Scroll delta to make the tab fully visible.
+     * @return a 1-D vector on the X axis of the window coordinate system that can make the tab
+     *     fully visible.
      */
     private float calculateDeltaToMakeTabVisible(StripLayoutTab tab) {
         if (tab == null) return 0.f;
 
-        // 1. Calculate offsets to fully show the tab at the start and end of the strip.
-        final boolean isRtl = LocalizationUtils.isLayoutRtl();
+        // 1. Calculate offsets to fully show the tab on the left/right side of the
+        // strip. These offsets are scalars.
         // TODO(wenyufu): Account for offsetX{Left,Right} result too much offset. Is this expected?
         final float rightOffset = mRightFadeWidth + mRightMargin;
         final float leftOffset = mLeftFadeWidth + mLeftMargin;
 
-        // Offsets where tab content is not drawn.
-        final float startOffset = isRtl ? rightOffset : leftOffset;
-        final float endOffset = isRtl ? leftOffset : rightOffset;
-        final float scrollOffset = mScrollDelegate.getScrollOffset();
-        // Tab position in visible area not accounting for any fades.
-        final float tabPosition = tab.getIdealX() - scrollOffset;
+        // 2. Calculate vectors from the tab's ideal position to the farthest left/right point where
+        // the tab can be visible.
+        // These are 1-D vectors on the X axis of the window coordinate system.
+        final float deltaToFarLeft = leftOffset - tab.getIdealX();
+        final float deltaToFarRight =
+                mWidth - rightOffset - mCachedTabWidthSupplier.get() - tab.getIdealX();
 
-        final float optimalStart = startOffset - tabPosition;
-        // Also account for mCachedTabWidth to allocate space to show tab at the end.
-        final float optimalEnd = mWidth - endOffset - tabPosition - mCachedTabWidthSupplier.get();
+        // 3. The following case means the tab is already completely in the visible area of the
+        // strip, i.e., it needs to be:
+        // moved left to reach the far left point, and
+        // moved right to reach the far right point.
+        if (deltaToFarLeft < 0 && deltaToFarRight > 0) return 0.f;
 
-        // 2. Return the scroll delta to make the given tab fully visible with the least scrolling.
-        // This will result in the tab being at either the start or end of the strip.
-        final float deltaToOptimalStart = optimalStart - scrollOffset;
-        final float deltaToOptimalEnd = optimalEnd - scrollOffset;
-
-        // 3. If the delta to the optimal start is negative and the delta to the optimal end is
-        // positive, the given index is already completely in the visible area of the strip.
-        if ((deltaToOptimalStart < 0) && (deltaToOptimalEnd > 0)) return 0.f;
-
-        return Math.abs(deltaToOptimalStart) < Math.abs(deltaToOptimalEnd)
-                ? deltaToOptimalStart
-                : deltaToOptimalEnd;
+        // 4. Return the vector with less distance for the tab to travel.
+        return Math.abs(deltaToFarLeft) < Math.abs(deltaToFarRight)
+                ? deltaToFarLeft
+                : deltaToFarRight;
     }
 
     /**
@@ -4394,10 +4389,11 @@
     }
 
     /**
-     * @return The strip's minimum scroll offset.
+     * @return The strip's scroll offset limit (a 1-D vector along the X axis, under the dynamic
+     *     coordinate system used by {@link ScrollDelegate}).
      */
-    float getMinimumScrollOffsetForTesting() {
-        return mScrollDelegate.getMinScrollOffsetForTesting(); // IN-TEST
+    float getScrollOffsetLimitForTesting() {
+        return mScrollDelegate.getScrollOffsetLimitForTesting(); // IN-TEST
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
index 89e3d7d..4c6ac5be 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
@@ -147,7 +147,8 @@
         TabStripSceneLayerJni.get().updateOffsetTag(mNativePtr, TabStripSceneLayer.this, offsetTag);
     }
 
-    private void pushButtonsAndBackground(
+    @VisibleForTesting
+    /* package */ void pushButtonsAndBackground(
             StripLayoutHelperManager layoutHelper,
             ResourceManager resourceManager,
             float yOffset,
@@ -188,6 +189,9 @@
                         newTabButton.getTint(),
                         newTabButton.getBackgroundTint(),
                         newTabButton.getOpacity(),
+                        newTabButton.isKeyboardFocused(),
+                        TabUiThemeUtil.getCircularButtonKeyboardFocusDrawableRes(),
+                        newTabButton.getKeyboardFocusRingColor(),
                         resourceManager);
 
         CompositorButton modelSelectorButton = layoutHelper.getModelSelectorButton();
@@ -207,6 +211,9 @@
                             ((TintedCompositorButton) modelSelectorButton).getTint(),
                             ((TintedCompositorButton) modelSelectorButton).getBackgroundTint(),
                             modelSelectorButton.getOpacity(),
+                            modelSelectorButton.isKeyboardFocused(),
+                            TabUiThemeUtil.getCircularButtonKeyboardFocusDrawableRes(),
+                            modelSelectorButton.getKeyboardFocusRingColor(),
                             resourceManager);
         }
 
@@ -263,7 +270,7 @@
                             st.getCloseButton().getResourceId(),
                             st.getCloseButton().getBackgroundResourceId(),
                             st.getCloseButton().isKeyboardFocused(),
-                            TabUiThemeUtil.getCloseButtonKeyboardFocusDrawableRes(),
+                            TabUiThemeUtil.getCircularButtonKeyboardFocusDrawableRes(),
                             st.getDividerResourceId(),
                             st.getResourceId(),
                             st.getOutlineResourceId(),
@@ -397,6 +404,9 @@
                 int tint,
                 int backgroundTint,
                 float buttonAlpha,
+                boolean isKeyboardFocused,
+                int keyboardFocusRingResourceId,
+                int keyboardFocusRingColor,
                 ResourceManager resourceManager);
 
         void updateModelSelectorButton(
@@ -411,6 +421,9 @@
                 int tint,
                 int backgroundTint,
                 float buttonAlpha,
+                boolean isKeyboardFocused,
+                int keyboardFocusRingResourceId,
+                int keyboardFocusRingColor,
                 ResourceManager resourceManager);
 
         void updateTabStripLeftFade(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 8f3fd7f..b54e38c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -56,7 +56,6 @@
 import org.chromium.base.task.ChainedTasks;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.IntentHandler;
@@ -119,7 +118,6 @@
  * ChromeApplicationImpl}.
  */
 @JNINamespace("customtabs")
-@MockedInTests
 public class CustomTabsConnection {
     private static final String TAG = "ChromeConnection";
     private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service-requests";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index ad393d9..3e0b1f94 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -153,7 +153,9 @@
         if (isTablet) {
             // Download Home shows up as a tab on tablets.
             LoadUrlParams params = new LoadUrlParams(UrlConstants.DOWNLOADS_URL);
-            if (tab == null || !tab.isInitialized()) {
+            if ((ChromeFeatureList.sAndroidNativePagesInNewTab.isEnabled()
+                    && ChromeFeatureList.sAndroidNativePagesInNewTabDownloadsEnabled.getValue())
+                    || tab == null || !tab.isInitialized()) {
                 // Open a new tab, which pops Chrome into the foreground.
                 ChromeAsyncTabLauncher delegate = new ChromeAsyncTabLauncher(false);
                 delegate.launchNewTab(params, TabLaunchType.FROM_CHROME_UI, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java
index 12da52d..f162cb0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java
@@ -269,11 +269,34 @@
             // Decide the bulletpoints orientation.
             bulletpointsArrangedHorizontally = false;
 
+            // Adjust the horizontal padding for |mContainer| and its children, |mHeader|,
+            // |mSubtitle| and |mBulletpointsContainer| to account for the horizontal offset, when
+            // layout width is small. There should be no additional horizontal padding for these
+            // views when layout width is large.
+            int horizontalOffset =
+                    getContext()
+                            .getResources()
+                            .getDimensionPixelSize(R.dimen.md_incognito_ntp_view_horizontal_offset);
+            float pxToDp = 1.f / getContext().getResources().getDisplayMetrics().density;
+            float horizontalOffsetDp = horizontalOffset * pxToDp;
+            paddingHorizontalDp = (int) (paddingHorizontalDp - horizontalOffsetDp);
+
+            mHeader.setPadding(
+                    horizontalOffset,
+                    mHeader.getPaddingTop(),
+                    horizontalOffset,
+                    mHeader.getPaddingBottom());
+
             // The subtitle is sized automatically, but not wider than CONTENT_WIDTH_DP.
             mSubtitle.setLayoutParams(
                     new LinearLayout.LayoutParams(
                             LinearLayout.LayoutParams.WRAP_CONTENT,
                             LinearLayout.LayoutParams.WRAP_CONTENT));
+            mSubtitle.setPadding(
+                    horizontalOffset,
+                    mSubtitle.getPaddingTop(),
+                    horizontalOffset,
+                    mSubtitle.getPaddingBottom());
             mSubtitle.setMaxWidth(dpToPx(getContext(), CONTENT_WIDTH_DP));
 
             // The bulletpoints container takes the same width as subtitle. Since the width can
@@ -282,6 +305,11 @@
                     dpToPx(
                             getContext(),
                             Math.min(CONTENT_WIDTH_DP, mWidthDp - 2 * paddingHorizontalDp));
+            mBulletpointsContainer.setPadding(
+                    horizontalOffset,
+                    mBulletpointsContainer.getPaddingTop(),
+                    horizontalOffset,
+                    mBulletpointsContainer.getPaddingBottom());
         } else {
             // Large padding.
             paddingHorizontalDp = 0; // Should not be necessary on a screen this large.
@@ -294,10 +322,21 @@
             bulletpointsArrangedHorizontally = true;
 
             int contentWidthPx = dpToPx(getContext(), CONTENT_WIDTH_DP);
+
+            // Reset any horizontal padding added to account for the horizontal offset, for
+            // |mHeader|, |mSubtitle| and |mBulletpointsContainer|. This padding should be applied
+            // only for a small-width layout.
+            mHeader.setPadding(0, mHeader.getPaddingTop(), 0, mHeader.getPaddingBottom());
             mSubtitle.setLayoutParams(
                     new LinearLayout.LayoutParams(
                             contentWidthPx, LinearLayout.LayoutParams.WRAP_CONTENT));
+            mSubtitle.setPadding(0, mSubtitle.getPaddingTop(), 0, mSubtitle.getPaddingBottom());
             mBulletpointsContainer.getLayoutParams().width = contentWidthPx;
+            mBulletpointsContainer.setPadding(
+                    0,
+                    mBulletpointsContainer.getPaddingTop(),
+                    0,
+                    mBulletpointsContainer.getPaddingBottom());
         }
 
         // Apply the bulletpoints orientation.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
index 16420ec..5f49e0e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
@@ -6,6 +6,9 @@
 
 import static org.chromium.components.content_settings.PrefNames.COOKIE_CONTROLS_MODE;
 
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.SpannableString;
@@ -18,14 +21,19 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
+import org.chromium.base.Callback;
+import org.chromium.base.IntentUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.enterprise.util.ManagedBrowserUtils;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthSettingSwitchPreference;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.prefetch.settings.PreloadPagesSettingsFragment;
 import org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings;
@@ -36,6 +44,9 @@
 import org.chromium.chrome.browser.safe_browsing.AdvancedProtectionStatusManagerAndroidBridge;
 import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint;
 import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment;
+import org.chromium.chrome.browser.safety_hub.SafetyHubExpandablePreference;
+import org.chromium.chrome.browser.safety_hub.SafetyHubModuleProperties;
+import org.chromium.chrome.browser.safety_hub.SafetyHubModuleViewBinder;
 import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
 import org.chromium.chrome.browser.settings.SettingsNavigationFactory;
@@ -45,15 +56,24 @@
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.usage_stats.UsageStatsConsentDialog;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+import org.chromium.components.browser_ui.settings.SettingsNavigation;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.browser_ui.site_settings.ContentSettingsResources;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.util.TraceEventVectorDrawableCompat;
 import org.chromium.components.content_settings.CookieControlsMode;
+import org.chromium.components.permissions.OsAdditionalSecurityPermissionProvider;
+import org.chromium.components.permissions.OsAdditionalSecurityPermissionUtil;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+import org.chromium.ui.text.ChromeClickableSpan;
 import org.chromium.ui.text.SpanApplier;
 
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
 /** Fragment to keep track of the all the privacy related preferences. */
 public class PrivacySettings extends ChromeBaseSettingsFragment
         implements Preference.OnPreferenceChangeListener {
@@ -76,10 +96,33 @@
     @VisibleForTesting static final String PREF_DO_NOT_TRACK = "do_not_track";
     @VisibleForTesting static final String PREF_THIRD_PARTY_COOKIES = "third_party_cookies";
     @VisibleForTesting static final String PREF_TRACKING_PROTECTION = "tracking_protection";
+    private static final String PREF_ADVANCED_PROTECTION_INFO = "advanced_protection_info";
 
     private IncognitoLockSettings mIncognitoLockSettings;
     private final ObservableSupplierImpl<String> mPageTitle = new ObservableSupplierImpl<>();
 
+    /** Called when the advanced-protection javascript-optimizer-settings link is clicked. */
+    @VisibleForTesting
+    public static void onJavascriptOptimizerLinkClicked(Context context) {
+        Bundle extras = new Bundle();
+        extras.putString(SingleCategorySettings.EXTRA_CATEGORY, "javascript_optimizer");
+        SettingsNavigation navigation = SettingsNavigationFactory.createSettingsNavigation();
+        navigation.startSettings(context, SingleCategorySettings.class, extras);
+    }
+
+    /** Creates {@link SpanInfo} for link which has the passed-in tag. */
+    private static SpanApplier.SpanInfo createLink(
+            Context context, String tag, @Nullable Consumer<Context> clickCallback) {
+        String startTag = "<" + tag + ">";
+        String endTag = "</" + tag + ">";
+        Callback<View> onClickCallback =
+                v -> {
+                    clickCallback.accept(context);
+                };
+        return new SpanApplier.SpanInfo(
+                startTag, endTag, new ChromeClickableSpan(context, onClickCallback));
+    }
+
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         mPageTitle.set(getString(R.string.prefs_privacy_security));
@@ -140,6 +183,8 @@
         mIncognitoLockSettings = new IncognitoLockSettings(incognitoReauthPreference, getProfile());
         mIncognitoLockSettings.setUpIncognitoReauthPreference(getActivity());
 
+        maybeShowAdvancedProtectionSection();
+
         Preference safeBrowsingPreference = findPreference(PREF_SAFE_BROWSING);
         safeBrowsingPreference.setSummary(
                 SafeBrowsingSettingsFragment.getSafeBrowsingSummaryString(
@@ -420,6 +465,74 @@
                 || ChromeFeatureList.isEnabled(ChromeFeatureList.IP_PROTECTION_UX);
     }
 
+    /** Shows the advanced-protection-section if needed. */
+    private void maybeShowAdvancedProtectionSection() {
+        Context context = getContext();
+        SafetyHubExpandablePreference advancedProtectionInfoPreference =
+                (SafetyHubExpandablePreference) findPreference(PREF_ADVANCED_PROTECTION_INFO);
+
+        @Nullable OsAdditionalSecurityPermissionProvider additionalSecurityProvider =
+                OsAdditionalSecurityPermissionUtil.getProviderInstance();
+        if (!shouldShowAdvancedProtectionInfo() || additionalSecurityProvider == null) {
+            advancedProtectionInfoPreference.setVisible(false);
+            return;
+        }
+
+        @Nullable Drawable additionalSecurityIcon =
+                additionalSecurityProvider.getColorfulAdvancedProtectionIcon(getContext());
+
+        Consumer<Context> androidAdvancedProtectionLinkAction =
+                (linkContext) -> {
+                    Intent intent =
+                            additionalSecurityProvider.getIntentForOsAdvancedProtectionSettings();
+                    if (intent != null) {
+                        IntentUtils.safeStartActivity(linkContext, intent);
+                    }
+                };
+        Consumer<Context> javascriptOptimizerLinkAction =
+                (linkContext) -> {
+                    PrivacySettings.onJavascriptOptimizerLinkClicked(linkContext);
+                };
+        SpanApplier.SpanInfo[] spans =
+                new SpanApplier.SpanInfo[] {
+                    createLink(
+                            context,
+                            "link_android_advanced_protection",
+                            androidAdvancedProtectionLinkAction),
+                    createLink(context, "link_javascript_optimizer", javascriptOptimizerLinkAction)
+                };
+        SpannableString span =
+                SpanApplier.applySpans(
+                        getString(
+                                R.string
+                                        .settings_privacy_and_security_advanced_protection_section_message),
+                        spans);
+
+        PropertyModel advancedProtectionInfoModel =
+                new PropertyModel.Builder(SafetyHubModuleProperties.ALL_KEYS)
+                        .with(SafetyHubModuleProperties.ICON, additionalSecurityIcon)
+                        .with(SafetyHubModuleProperties.SUMMARY, span)
+                        .build();
+        PropertyModelChangeProcessor.create(
+                advancedProtectionInfoModel,
+                advancedProtectionInfoPreference,
+                SafetyHubModuleViewBinder::bindProperties);
+    }
+
+    /** Returns whether the advanced-protection section should be shown. */
+    private boolean shouldShowAdvancedProtectionInfo() {
+        if (!AdvancedProtectionStatusManagerAndroidBridge.isUnderAdvancedProtection()) {
+            return false;
+        }
+        long updateTimeMs =
+                ChromeSharedPreferences.getInstance()
+                        .readLong(
+                                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                                0);
+        return updateTimeMs == 0
+                || ((System.currentTimeMillis() - updateTimeMs) < TimeUnit.DAYS.toMillis(90));
+    }
+
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.clear();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index bc9388b8..3f52137 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -148,6 +148,10 @@
                 return "BookmarkBarBackground";
             case TabLaunchType.FROM_REPARENTING_BACKGROUND:
                 return "ReparentingBackground";
+            case TabLaunchType.FROM_HISTORY_NAVIGATION_BACKGROUND:
+                return "HistoryNavigationBackground";
+            case TabLaunchType.FROM_HISTORY_NAVIGATION_FOREGROUND:
+                return "HistoryNavigationBackground";
             default:
                 assert false : "Unexpected serialization of tabLaunchType: " + tabLaunchType;
                 return "TypeUnknown";
@@ -438,12 +442,7 @@
 
         // Measure tab creation duration for different launch types to understand tab creation
         // performance using an existing WebContents.
-        try (TraceEvent te = TraceEvent.scoped("ChromeTabCreator.createTabWithWebContents");
-                TimingMetric unused =
-                        TimingMetric.mediumUptime(
-                                "Android.Tab.CreateNewTabDuration."
-                                        + tabLaunchTypeToHistogramKey(type)
-                                        + ".WithExistingWebContents")) {
+        try (TraceEvent te = TraceEvent.scoped("ChromeTabCreator.createTabWithWebContents")) {
             // If parent is in the same tab model, place the new tab next to it.
             int position = TabModel.INVALID_TAB_INDEX;
             int index = TabModelUtils.getTabIndexById(mTabModel, parentId);
@@ -674,6 +673,7 @@
                 break;
             case TabLaunchType.FROM_LONGPRESS_FOREGROUND:
             case TabLaunchType.FROM_LONGPRESS_INCOGNITO:
+            case TabLaunchType.FROM_HISTORY_NAVIGATION_FOREGROUND:
                 transition = PageTransition.LINK;
                 break;
             case TabLaunchType.FROM_LONGPRESS_BACKGROUND:
@@ -682,6 +682,7 @@
             case TabLaunchType.FROM_RECENT_TABS:
             case TabLaunchType.FROM_RECENT_TABS_FOREGROUND:
             case TabLaunchType.FROM_BOOKMARK_BAR_BACKGROUND:
+            case TabLaunchType.FROM_HISTORY_NAVIGATION_BACKGROUND:
                 // On low end devices tabs are backgrounded in a frozen state, so we set the
                 // transition type to RELOAD to avoid handling intents when the tab is foregrounded.
                 // (https://crbug.com/758027)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
index 67c5375..f7ae9a2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
@@ -66,10 +66,7 @@
         assert mNativeTabModelObserverJniBridge != 0;
         TabModelObserverJniBridgeJni.get()
                 .onFinishingTabClosure(
-                        mNativeTabModelObserverJniBridge,
-                        TabModelObserverJniBridge.this,
-                        tab.getId(),
-                        tab.isIncognito());
+                        mNativeTabModelObserverJniBridge, TabModelObserverJniBridge.this, tab);
     }
 
     @Override
@@ -238,10 +235,7 @@
                 long nativeTabModelObserverJniBridge, TabModelObserverJniBridge caller, Tab tab);
 
         void onFinishingTabClosure(
-                long nativeTabModelObserverJniBridge,
-                TabModelObserverJniBridge caller,
-                int tabId,
-                boolean incognito);
+                long nativeTabModelObserverJniBridge, TabModelObserverJniBridge caller, Tab tab);
 
         void onFinishingMultipleTabClosure(
                 long nativeTabModelObserverJniBridge,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ChromeAsyncTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ChromeAsyncTabLauncher.java
index 72eb275a..30b2ae98 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ChromeAsyncTabLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ChromeAsyncTabLauncher.java
@@ -66,8 +66,8 @@
      */
     public void launchTabInOtherWindow(
             LoadUrlParams loadUrlParams, Activity activity, int parentId, Activity otherActivity) {
-        Intent intent =
-                createNewTabIntent(new AsyncTabCreationParams(loadUrlParams), parentId, false);
+        Intent intent = createNewTabIntent(new AsyncTabCreationParams(loadUrlParams), parentId,
+                TabLaunchType.UNSET);
 
         Class<? extends Activity> targetActivity =
                 MultiWindowUtils.getInstance().getOpenInOtherWindowActivity(activity);
@@ -125,19 +125,20 @@
                 && asyncParams.getWebContents() != null);
 
         Intent intent =
-                createNewTabIntent(asyncParams, parentId, type == TabLaunchType.FROM_CHROME_UI);
+                createNewTabIntent(asyncParams, parentId, type);
         IntentHandler.startActivityForTrustedIntent(intent);
     }
 
     private Intent createNewTabIntent(
-            AsyncTabCreationParams asyncParams, int parentId, boolean isChromeUi) {
+            AsyncTabCreationParams asyncParams, int parentId,
+            @TabLaunchType int launchType) {
         int assignedTabId = TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID);
         AsyncTabParamsManagerSingleton.getInstance().add(assignedTabId, asyncParams);
 
         Intent intent =
                 new Intent(Intent.ACTION_VIEW, Uri.parse(asyncParams.getLoadUrlParams().getUrl()));
 
-        addAsyncTabExtras(asyncParams, parentId, isChromeUi, assignedTabId, intent);
+        addAsyncTabExtras(asyncParams, parentId, launchType, assignedTabId, intent);
 
         return intent;
     }
@@ -145,7 +146,7 @@
     private void addAsyncTabExtras(
             AsyncTabCreationParams asyncParams,
             int parentId,
-            boolean isChromeUi,
+            @TabLaunchType int launchType,
             int assignedTabId,
             Intent intent) {
         ComponentName componentName = asyncParams.getComponentName();
@@ -160,7 +161,9 @@
         IntentHandler.setTabId(intent, assignedTabId);
         intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, mIsIncognito);
         intent.putExtra(IntentHandler.EXTRA_PARENT_TAB_ID, parentId);
+        IntentHandler.setTabLaunchType(intent, launchType);
 
+        boolean isChromeUi = (launchType == TabLaunchType.FROM_CHROME_UI);
         if (mIsIncognito || isChromeUi) {
             intent.putExtra(
                     Browser.EXTRA_APPLICATION_ID,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupPTTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupPTTest.java
index 02317ba..f09f226 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupPTTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupPTTest.java
@@ -22,12 +22,14 @@
 
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.transit.AutoResetCtaTransitTestRule;
 import org.chromium.chrome.test.transit.ChromeTransitTestRules;
 import org.chromium.chrome.test.transit.page.PopupBlockedMessageFacility;
 import org.chromium.chrome.test.transit.page.WebPageStation;
+import org.chromium.chrome.test.transit.testhtmls.BlankPopupOnLoadPageStation;
 import org.chromium.chrome.test.transit.testhtmls.PopupOnClickPageStation;
 import org.chromium.chrome.test.transit.testhtmls.PopupOnLoadPageStation;
 import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
@@ -145,4 +147,22 @@
         assertEquals(1, mCtaTestRule.tabsCount(/* incognito= */ false));
         assertFinalDestination(page, popupBlockedMessage);
     }
+
+    // Regression test for crbug.com/413341816.
+    @Test
+    @MediumTest
+    @RequiresRestart
+    public void testBlankPopupLaunchedFromBlockedChip() {
+        PopupBlockedMessageFacility popupBlockedMessage =
+                BlankPopupOnLoadPageStation.loadInCurrentTabExpectBlocked(
+                                mCtaTestRule.getActivityTestRule(), mEntryPage)
+                        .second;
+        assertEquals(1, mCtaTestRule.tabsCount(/* incognito= */ false));
+
+        // Click the "Always allow" button.
+        WebPageStation poppedUpPage = popupBlockedMessage.clickAlwaysAllow();
+        assertEquals(2, mCtaTestRule.tabsCount(/* incognito= */ false));
+
+        assertFinalDestination(poppedUpPage);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
index f3bfff74..61358ca 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -734,7 +734,7 @@
         assertSetTabStripScrollOffset(
                 (int)
                         TabStripUtils.getActiveStripLayoutHelper(mActivityTestRule.getActivity())
-                                .getMinimumScrollOffsetForTesting());
+                                .getScrollOffsetLimitForTesting());
 
         // Tab should now be hidden.
         helper.waitForCallback(0);
@@ -780,7 +780,7 @@
         // Open enough regular tabs to cause the strip to scroll.
         StripLayoutHelper tabStrip =
                 TabStripUtils.getStripLayoutHelper(mActivityTestRule.getActivity(), false);
-        while (tabStrip.getMinimumScrollOffsetForTesting() >= 0) {
+        while (tabStrip.getScrollOffsetLimitForTesting() >= 0) {
             ChromeTabUtils.newTabFromMenu(
                     InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
         }
@@ -792,12 +792,12 @@
         assertTabStripFadeFullyHidden(!isLeft);
         assertTabStripFadeFullyVisible(isLeft);
 
-        // Scroll a little below the minimum scroll offset causing the right fade (in LTR) to be
+        // Scroll a little below the scroll offset limit causing the right fade (in LTR) to be
         // at partial opacity.
         assertSetTabStripScrollOffset(
                 (int)
                         (TabStripUtils.getActiveStripLayoutHelper(mActivityTestRule.getActivity())
-                                        .getMinimumScrollOffsetForTesting()
+                                        .getScrollOffsetLimitForTesting()
                                 + StripLayoutHelper.FADE_FULL_OPACITY_THRESHOLD_DP / 2));
         assertTabStripFadePartiallyVisible(!isLeft);
         assertTabStripFadeFullyVisible(isLeft);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
index f391146e5..30b04ac 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -562,6 +562,27 @@
 
     @Test
     @LargeTest
+    @Restriction(DeviceFormFactor.DESKTOP)
+    @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_EMPTY_SPACE})
+    public void testSavePage() throws TimeoutException {
+        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        int callCount = sDownloadTestRule.getChromeDownloadCallCount();
+        ContextMenuUtils.selectContextMenuItemFromRightClick(
+                InstrumentationRegistry.getInstrumentation(),
+                sDownloadTestRule.getActivity(),
+                tab,
+                "testEmptySpace",
+                R.id.contextmenu_save_page);
+
+        // Wait for the download to complete and see if we got the right file
+        Assert.assertTrue(sDownloadTestRule.waitForChromeDownloadToFinish(callCount));
+        Assert.assertTrue(
+                sDownloadTestRule.hasDownloadedRegex(
+                        ".*chrome_test_data_android_contextmenu_context_menu_test.html.mht"));
+    }
+
+    @Test
+    @LargeTest
     public void testSaveDataUrl() throws TimeoutException, SecurityException, IOException {
         saveMediaFromContextMenu("dataUrlIcon", R.id.contextmenu_save_image, FILENAME_GIF);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java
index 69c5355..b784ebe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java
@@ -82,6 +82,22 @@
     }
 
     /**
+     * Checks if a file matching the regex has downloaded. Is agnostic to the mechanism by which the
+     * file has downloaded.
+     *
+     * @param fileNameRegex Expected regex the file name should match. Files are non-recursively
+     *     searched in the system downloads path.
+     */
+    public boolean hasDownloadedRegex(String fileNameRegex) {
+        for (File file : DOWNLOAD_DIRECTORY.listFiles()) {
+            if (!file.isDirectory() && file.getName().matches(fileNameRegex)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Check the download exists in DownloadManager by matching the local file path.
      *
      * @param fileName Expected file name. Path is built by appending filename to the system
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoViewTest.java
index bf248c7..10610f30 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoViewTest.java
@@ -6,7 +6,6 @@
 
 import androidx.test.filters.MediumTest;
 
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -15,39 +14,35 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.app.ChromeActivity;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
+import org.chromium.chrome.test.transit.AutoResetCtaTransitTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.page.WebPageStation;
 import org.chromium.components.page_info.ConnectionInfoView;
 import org.chromium.content_public.browser.WebContents;
 
 /** Tests for ConnectionInfoView. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Batch(ConnectionInfoViewTest.PAGE_INFO_BATCH_NAME)
+@Batch(Batch.PER_CLASS)
 public class ConnectionInfoViewTest {
-    public static final String PAGE_INFO_BATCH_NAME = "page_info";
-
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
     @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
+    public final AutoResetCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.fastAutoResetCtaActivityRule();
 
     /** Tests that ConnectionInfoView can be instantiated and shown. */
     @Test
     @MediumTest
     @Feature({"ConnectionInfoView"})
     public void testShow() throws InterruptedException {
+        WebPageStation page = mActivityTestRule.startOnBlankPage();
+        WebContents webContents = page.webContentsElement.get();
+        ChromeTabbedActivity activity = page.getActivity();
         ThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    ChromeActivity context = sActivityTestRule.getActivity();
-                    WebContents webContents = context.getActivityTab().getWebContents();
-                    ConnectionInfoView.show(context, webContents, context.getModalDialogManager());
-                });
+                () ->
+                        ConnectionInfoView.show(
+                                activity, webContents, activity.getModalDialogManager()));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java
index 48d01d23..bb304b3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteTest.java
@@ -30,7 +30,6 @@
 import androidx.test.filters.MediumTest;
 
 import org.junit.Before;
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -51,9 +50,10 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabbed_mode.TabbedRootUiCoordinator;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.R;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
+import org.chromium.chrome.test.transit.AutoResetCtaTransitTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.page.WebPageStation;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport;
 import org.chromium.components.page_info.PageInfoController;
@@ -85,15 +85,11 @@
     private static final String sSimpleHtml = "/chrome/test/data/android/simple.html";
     private static final String sAboutHtml = "/chrome/test/data/android/about.html";
 
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
+    public final AutoResetCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.fastAutoResetCtaActivityRule();
 
     @Rule public EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
 
@@ -103,6 +99,7 @@
                     .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_BUBBLES_PAGE_INFO)
                     .build();
 
+    private WebPageStation mStartingPage;
     private EphemeralTabCoordinator mEphemeralTabCoordinator;
 
     private BottomSheetTestSupport mSheetTestSupport;
@@ -117,13 +114,17 @@
                 .getJavaDrawableIconId();
         PageInfoAboutThisSiteControllerJni.setInstanceForTesting(mMockAboutThisSiteJni);
         mTestServerRule.setServerUsesHttps(true);
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSimpleHtml));
+        mStartingPage =
+                mActivityTestRule
+                        .startOnBlankPage()
+                        .loadWebPageProgrammatically(
+                                mTestServerRule.getServer().getURL(sSimpleHtml));
 
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     TabbedRootUiCoordinator tabbedRootUiCoordinator =
                             ((TabbedRootUiCoordinator)
-                                    sActivityTestRule
+                                    mActivityTestRule
                                             .getActivity()
                                             .getRootUiCoordinatorForTesting());
                     mEphemeralTabCoordinator =
@@ -132,14 +133,14 @@
 
         mSheetTestSupport =
                 new BottomSheetTestSupport(
-                        sActivityTestRule
+                        mActivityTestRule
                                 .getActivity()
                                 .getRootUiCoordinatorForTesting()
                                 .getBottomSheetController());
     }
 
     private void openPageInfo() {
-        ChromeTabbedActivity activity = sActivityTestRule.getActivity();
+        ChromeTabbedActivity activity = mActivityTestRule.getActivity();
         Tab tab = activity.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
@@ -223,7 +224,7 @@
     @Test
     @MediumTest
     public void testAboutThisSiteRowWithDataOnInsecureSite() {
-        sActivityTestRule.loadUrl(
+        mActivityTestRule.loadUrl(
                 mTestServerRule.getServer().getURLWithHostName("invalidcert.com", sSimpleHtml));
         mockResponse(createDescription());
         openPageInfo();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java
index e7ab496..1e3e60f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewDarkModeTest.java
@@ -35,6 +35,9 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.R;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.FreshCtaTransitTestRule;
+import org.chromium.chrome.test.transit.page.WebPageStation;
 import org.chromium.components.page_info.PageInfoController;
 import org.chromium.components.page_info.PageInfoController.OpenedFromSource;
 import org.chromium.content_public.common.ContentSwitches;
@@ -61,8 +64,8 @@
     private static final String sSimpleHtml = "/chrome/test/data/android/simple.html";
 
     @Rule
-    public final ChromeTabbedActivityTestRule mActivityTestRule =
-            new ChromeTabbedActivityTestRule();
+    public final FreshCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.freshChromeTabbedActivityRule();
 
     @Rule public EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
 
@@ -73,6 +76,8 @@
                     .setBugComponent(RenderTestRule.Component.UI_BROWSER_BUBBLES_PAGE_INFO)
                     .build();
 
+    private WebPageStation mStartingPage;
+
     private void loadUrlAndOpenPageInfo(String url) {
         mActivityTestRule.loadUrl(url);
         openPageInfo();
@@ -117,7 +122,7 @@
                     ChromeNightModeTestUtils.setUpNightModeForChromeActivity(
                             /* nightModeEnabled= */ true);
                 });
-        mActivityTestRule.startMainActivityOnBlankPage();
+        mStartingPage = mActivityTestRule.startOnBlankPage();
     }
 
     @After
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
index 0b1a5266..79c6edd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -57,7 +57,6 @@
 import org.hamcrest.TypeSafeMatcher;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -104,9 +103,9 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.R;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
+import org.chromium.chrome.test.transit.AutoResetCtaTransitTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
 import org.chromium.components.browser_ui.settings.SettingsNavigation;
 import org.chromium.components.browser_ui.site_settings.ContentSettingException;
 import org.chromium.components.browser_ui.site_settings.RwsCookieInfo;
@@ -234,15 +233,11 @@
 
     private FakePrivacySandboxBridge mFakePrivacySandboxBridge;
 
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
+    public final AutoResetCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.fastAutoResetCtaActivityRule();
 
     @Rule public EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
 
@@ -269,12 +264,12 @@
 
     private void loadUrlAndOpenPageInfoWithPermission(
             String url, @ContentSettingsType.EnumType int highlightedPermission) {
-        sActivityTestRule.loadUrl(url);
+        mActivityTestRule.loadUrl(url);
         openPageInfo(highlightedPermission);
     }
 
     private void openPageInfo(@ContentSettingsType.EnumType int highlightedPermission) {
-        ChromeActivity activity = sActivityTestRule.getActivity();
+        ChromeActivity activity = mActivityTestRule.getActivity();
         Tab tab = activity.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
@@ -395,7 +390,7 @@
 
     private String runJavascriptAsync(String type) throws TimeoutException {
         return JavaScriptUtils.runJavascriptWithAsyncResult(
-                sActivityTestRule.getWebContents(), type);
+                mActivityTestRule.getWebContents(), type);
     }
 
     private void expectHasCookies(boolean hasData) throws TimeoutException {
@@ -1352,7 +1347,7 @@
     @Test
     @MediumTest
     public void clearCookiesOnSubpage() throws Exception {
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
+        mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
         // Create cookies.
         expectHasCookies(false);
         createCookies();
@@ -1375,7 +1370,7 @@
     @MediumTest
     public void clearCookiesOnSubpageUserBypass() throws Exception {
         setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY);
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
+        mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
         // Create cookies.
         expectHasCookies(false);
         createCookies();
@@ -1406,7 +1401,7 @@
     public void clearCookiesOnSubpageTrackingProtection() throws Exception {
         enableTrackingProtection();
         setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY);
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
+        mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
         // Create cookies.
         expectHasCookies(false);
         createCookies();
@@ -1450,7 +1445,7 @@
     @MediumTest
     public void a11yLiveRegionInUserBypass() throws Exception {
         setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY);
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
+        mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
         // Create cookies.
         expectHasCookies(false);
         createCookies();
@@ -1488,7 +1483,7 @@
     @Test
     @MediumTest
     public void testResetPermissionsOnSubpage() throws Exception {
-        sActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
+        mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml));
         String url = mTestServerRule.getServer().getURL("/");
         // Create permissions.
         expectHasPermissions(url, false);
@@ -1516,7 +1511,7 @@
     @MediumTest
     public void testClearFederatedIdentityEmbargoOnSubpage() throws Exception {
         String rpUrl = mTestServerRule.getServer().getURL(sSimpleHtml);
-        sActivityTestRule.loadUrl(rpUrl);
+        mActivityTestRule.loadUrl(rpUrl);
 
         assertTrue(
                 getNonWildcardContentSettingExceptions(ContentSettingsType.FEDERATED_IDENTITY_API)
@@ -1555,7 +1550,7 @@
     public void testPaintPreview() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    final ChromeActivity activity = sActivityTestRule.getActivity();
+                    final ChromeActivity activity = mActivityTestRule.getActivity();
                     final Tab tab = activity.getActivityTab();
                     ChromePageInfoControllerDelegate pageInfoControllerDelegate =
                             new ChromePageInfoControllerDelegate(
@@ -1573,7 +1568,7 @@
                                 }
                             };
                     PageInfoController.show(
-                            sActivityTestRule.getActivity(),
+                            mActivityTestRule.getActivity(),
                             tab.getWebContents(),
                             null,
                             PageInfoController.OpenedFromSource.MENU,
@@ -1591,7 +1586,7 @@
     public void testTransientPdfPage() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    final ChromeActivity activity = sActivityTestRule.getActivity();
+                    final ChromeActivity activity = mActivityTestRule.getActivity();
                     final Tab tab = activity.getActivityTab();
                     ChromePageInfoControllerDelegate pageInfoControllerDelegate =
                             new ChromePageInfoControllerDelegate(
@@ -1609,7 +1604,7 @@
                                 }
                             };
                     PageInfoController.show(
-                            sActivityTestRule.getActivity(),
+                            mActivityTestRule.getActivity(),
                             tab.getWebContents(),
                             null,
                             PageInfoController.OpenedFromSource.MENU,
@@ -1627,7 +1622,7 @@
     public void testInsecureTransientPdfPage() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    final ChromeActivity activity = sActivityTestRule.getActivity();
+                    final ChromeActivity activity = mActivityTestRule.getActivity();
                     final Tab tab = activity.getActivityTab();
                     ChromePageInfoControllerDelegate pageInfoControllerDelegate =
                             new ChromePageInfoControllerDelegate(
@@ -1645,7 +1640,7 @@
                                 }
                             };
                     PageInfoController.show(
-                            sActivityTestRule.getActivity(),
+                            mActivityTestRule.getActivity(),
                             tab.getWebContents(),
                             null,
                             PageInfoController.OpenedFromSource.MENU,
@@ -1666,7 +1661,7 @@
     public void testLocalPdfPage() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    final ChromeActivity activity = sActivityTestRule.getActivity();
+                    final ChromeActivity activity = mActivityTestRule.getActivity();
                     final Tab tab = activity.getActivityTab();
                     ChromePageInfoControllerDelegate pageInfoControllerDelegate =
                             new ChromePageInfoControllerDelegate(
@@ -1684,7 +1679,7 @@
                                 }
                             };
                     PageInfoController.show(
-                            sActivityTestRule.getActivity(),
+                            mActivityTestRule.getActivity(),
                             tab.getWebContents(),
                             null,
                             PageInfoController.OpenedFromSource.MENU,
@@ -1801,7 +1796,7 @@
         final CallbackHelper onDidStartNavigationHelper = new CallbackHelper();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    return new WebContentsObserver(sActivityTestRule.getWebContents()) {
+                    return new WebContentsObserver(mActivityTestRule.getWebContents()) {
                         @Override
                         public void didStartNavigationInPrimaryMainFrame(
                                 NavigationHandle navigationHandle) {
@@ -1873,7 +1868,7 @@
         float cornerRadius =
                 ThreadUtils.runOnUiThreadBlocking(
                         () -> {
-                            ChromeActivity activity = sActivityTestRule.getActivity();
+                            ChromeActivity activity = mActivityTestRule.getActivity();
                             BrowserControlsManager browserControlsManager =
                                     BrowserControlsManagerSupplier.getValueOrNullFrom(
                                             activity.getWindowAndroid());
@@ -1964,7 +1959,7 @@
         ObservableSupplier<ModalDialogManager> modalDialogManagerSupplier =
                 ThreadUtils.runOnUiThreadBlocking(
                         () -> {
-                            ChromeActivity activity = sActivityTestRule.getActivity();
+                            ChromeActivity activity = mActivityTestRule.getActivity();
                             BrowserControlsManager browserControlsManager =
                                     BrowserControlsManagerSupplier.getValueOrNullFrom(
                                             activity.getWindowAndroid());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
index fc21467..cac4e90e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 
@@ -31,6 +32,7 @@
 
 import androidx.preference.Preference;
 import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.filters.LargeTest;
 
@@ -46,6 +48,7 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.shared_preferences.SharedPreferencesManager;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisabledTest;
@@ -60,6 +63,8 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager;
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthSettingUtils;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.privacy_guide.PrivacyGuideInteractions;
 import org.chromium.chrome.browser.privacy_sandbox.FakePrivacySandboxBridge;
@@ -71,9 +76,11 @@
 import org.chromium.chrome.browser.sync.settings.GoogleServicesSettings;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.R;
+import org.chromium.chrome.test.util.AdvancedProtectionTestRule;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.chrome.test.util.browser.signin.SigninTestRule;
 import org.chromium.components.browser_ui.settings.SettingsNavigation;
+import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.policy.test.annotations.Policies;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
@@ -82,6 +89,7 @@
 
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 
 /** Tests for {@link PrivacySettings}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
@@ -111,6 +119,10 @@
     public final SigninTestRule mSigninTestRule = new SigninTestRule();
 
     @Rule
+    public final AdvancedProtectionTestRule mAdvancedProtectionRule =
+            new AdvancedProtectionTestRule();
+
+    @Rule
     public final RuleChain mRuleChain =
             RuleChain.outerRule(mSigninTestRule).around(mSettingsActivityTestRule);
 
@@ -554,4 +566,109 @@
             SettingsNavigationFactory.setInstanceForTesting(mSettingsNavigation);
         }
     }
+
+    /**
+     * Test that advanced-protection-info is shown when (1) Advanced-Protection is on AND (2) Chrome
+     * doesn't have any stored preferences.
+     */
+    @Test
+    @LargeTest
+    public void testInfoShown_AdvancedProtectionOn_FirstRun() {
+        mAdvancedProtectionRule.setIsAdvancedProtectionRequestedByOs(true);
+
+        SharedPreferencesManager preferences = ChromeSharedPreferences.getInstance();
+        preferences
+                .getEditor()
+                .remove(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING)
+                .remove(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME)
+                .apply();
+
+        mSettingsActivityTestRule.startSettingsActivity();
+        scrollToSetting(withText(R.string.prefs_safe_browsing_title));
+        onView(withText(R.string.settings_privacy_and_security_advanced_protection_section_title))
+                .check(matches(isDisplayed()));
+    }
+
+    /**
+     * Test that advanced-protection-info is shown when (1) Advanced-Protection is on AND (2) the
+     * user turned on Advanced-Protection 1 day ago.
+     */
+    @Test
+    @LargeTest
+    public void testInfoShown_AdvancedProtectionOn_1DayAfterFirstRun() {
+        mAdvancedProtectionRule.setIsAdvancedProtectionRequestedByOs(true);
+        SharedPreferencesManager preferences = ChromeSharedPreferences.getInstance();
+        preferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
+        preferences.writeLong(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1));
+
+        mSettingsActivityTestRule.startSettingsActivity();
+        scrollToSetting(withText(R.string.prefs_safe_browsing_title));
+        onView(withText(R.string.settings_privacy_and_security_advanced_protection_section_title))
+                .check(matches(isDisplayed()));
+    }
+
+    /**
+     * Test that advanced-protection-info is not shown when (1) Advanced-Protection is on AND (2)
+     * the user turned on Advanced-Protection a long time ago.
+     */
+    @Test
+    @LargeTest
+    public void testInfoNotShown_AdvancedProtectionOn_91DaysAfterFirstRun() {
+        mAdvancedProtectionRule.setIsAdvancedProtectionRequestedByOs(true);
+        SharedPreferencesManager preferences = ChromeSharedPreferences.getInstance();
+        preferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
+        preferences.writeLong(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                System.currentTimeMillis() - TimeUnit.DAYS.toMillis(91));
+
+        mSettingsActivityTestRule.startSettingsActivity();
+        scrollToSetting(withText(R.string.prefs_safe_browsing_title));
+        onView(withText(R.string.settings_privacy_and_security_advanced_protection_section_title))
+                .check(doesNotExist());
+    }
+
+    /** Test that advanced-protection-info is not shown when Advanced-Protection is off. */
+    @Test
+    @LargeTest
+    public void testInfoNotShown_AdvancedProtectionOff_FirstRun() {
+        mAdvancedProtectionRule.setIsAdvancedProtectionRequestedByOs(false);
+
+        SharedPreferencesManager preferences = ChromeSharedPreferences.getInstance();
+        preferences
+                .getEditor()
+                .remove(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING)
+                .remove(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME)
+                .apply();
+
+        mSettingsActivityTestRule.startSettingsActivity();
+        scrollToSetting(withText(R.string.prefs_safe_browsing_title));
+        onView(withText(R.string.settings_privacy_and_security_advanced_protection_section_title))
+                .check(doesNotExist());
+    }
+
+    /**
+     * Test that Javascript-optimizer settings are shown when the user clicks the
+     * javascript-optimizer link in the advanced-protection section.
+     */
+    @Test
+    @LargeTest
+    public void testOnJavascriptOptimizerLinkClicked() {
+        SettingsNavigationFactory.setInstanceForTesting(mSettingsNavigation);
+        PrivacySettings.onJavascriptOptimizerLinkClicked(
+                ApplicationProvider.getApplicationContext());
+
+        verify(mSettingsNavigation)
+                .startSettings(
+                        any(),
+                        eq(SingleCategorySettings.class),
+                        argThat(
+                                fragmentArgs -> {
+                                    String category =
+                                            fragmentArgs.getString(
+                                                    SingleCategorySettings.EXTRA_CATEGORY);
+                                    return "javascript_optimizer".equals(category);
+                                }));
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/OtrProfileIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/OtrProfileIdTest.java
index 812d1e3e..c29f829e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/OtrProfileIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/OtrProfileIdTest.java
@@ -4,20 +4,25 @@
 
 package org.chromium.chrome.browser.profiles;
 
+import static org.junit.Assert.assertSame;
+
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.ReusedCtaTransitTestRule;
+import org.chromium.chrome.test.transit.page.WebPageStation;
 
 /**
  * This test class checks if OtrProfileId works correctly for regular profile, primary
@@ -26,17 +31,20 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@Batch(Batch.PER_CLASS)
 public class OtrProfileIdTest {
     private static final String TEST_OTR_PROFILE_ID_ONE = "Test::SerializationOne";
     private static final String TEST_OTR_PROFILE_ID_TWO = "Test::SerializationTwo";
 
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
+    @Rule
+    public ReusedCtaTransitTestRule<WebPageStation> mActivityTestRule =
+            ChromeTransitTestRules.blankPageStartReusedActivityRule();
+
+    private WebPageStation mPage;
 
     @Before
     public void setUp() {
-        sActivityTestRule.startMainActivityOnBlankPage();
+        mPage = mActivityTestRule.start();
     }
 
     @Test
@@ -46,6 +54,8 @@
                 () -> {
                     Profile profile = ProfileManager.getLastUsedRegularProfile();
 
+                    assertSame(profile, mPage.loadedTabElement.get().getProfile());
+
                     // OtrProfileId should be null for regular profile.
                     assert profile.getOtrProfileId() == null;
                 });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileResolverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileResolverTest.java
index 443dd8e..934670aa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileResolverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileResolverTest.java
@@ -18,11 +18,13 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.PayloadCallbackHelper;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.ReducedModeNativeTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.FreshCtaTransitTestRule;
 import org.chromium.components.embedder_support.simple_factory_key.SimpleFactoryKeyHandle;
 import org.chromium.content_public.browser.BrowserContextHandle;
 
@@ -38,10 +40,11 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@DoNotBatch(reason = "Tests initialization")
 public class ProfileResolverTest {
     @Rule
-    public final ChromeTabbedActivityTestRule mActivityTestRule =
-            new ChromeTabbedActivityTestRule();
+    public final FreshCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.freshChromeTabbedActivityRule();
 
     @Rule
     public ReducedModeNativeTestRule mReducedModeNativeTestRule =
@@ -55,8 +58,7 @@
     }
 
     private void initToFullMode() {
-        mActivityTestRule.startMainActivityOnBlankPage();
-        mActivityTestRule.waitForActivityNativeInitializationComplete();
+        mActivityTestRule.startOnBlankPage();
     }
 
     private void initToReducedMode() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
index 75ec2f0..af0213c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
@@ -8,7 +8,6 @@
 
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -19,8 +18,9 @@
 import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
+import org.chromium.chrome.test.transit.AutoResetCtaTransitTestRule;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.page.WebPageStation;
 import org.chromium.components.profile_metrics.BrowserProfileType;
 
 /** This test class checks if incognito and non-incognito OTR profiles can be distinctly created. */
@@ -28,40 +28,32 @@
 @Batch(Batch.PER_CLASS)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ProfileTest {
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
     @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
+    public final AutoResetCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.fastAutoResetCtaActivityRule();
 
     public Profile mRegularProfile;
+    private WebPageStation mStartingPage;
 
     @Before
     public void setUp() {
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mRegularProfile =
-                            sActivityTestRule
-                                    .getActivity()
-                                    .getTabModelSelector()
-                                    .getModel(false)
-                                    .getProfile();
-                });
+        mStartingPage = mActivityTestRule.startOnBlankPage();
+        mRegularProfile = mStartingPage.loadedTabElement.get().getProfile();
     }
 
     /** Test if two calls for incognito profile return the same object. */
     @Test
     @LargeTest
-    public void testIncognitoProfileConsistency() throws Exception {
+    public void testIncognitoProfileConsistency() {
         Assert.assertNull(mRegularProfile.getOtrProfileId());
         // Open an new Incognito Tab page to create a new primary OTR profile.
-        sActivityTestRule.loadUrlInNewTab("about:blank", true);
+        WebPageStation incognitoPage =
+                mStartingPage.openRegularTabAppMenu().openNewIncognitoTab().loadAboutBlank();
 
-        Profile incognitoProfile1 =
-                ThreadUtils.runOnUiThreadBlocking(
-                        () -> mRegularProfile.getPrimaryOtrProfile(/* createIfNeeded= */ true));
+        Profile incognitoProfile1 = incognitoPage.loadedTabElement.get().getProfile();
+        Assert.assertSame(
+                incognitoProfile1,
+                mRegularProfile.getPrimaryOtrProfile(/* createIfNeeded= */ true));
         Assert.assertTrue(
                 "isOffTheRecord should be true for Incognito profiles",
                 incognitoProfile1.isOffTheRecord());
@@ -90,7 +82,7 @@
     /** Test if two calls to get non-primary profile with the same id return the same object. */
     @Test
     @LargeTest
-    public void testNonPrimaryProfileConsistency() throws Exception {
+    public void testNonPrimaryProfileConsistency() {
         OtrProfileId profileId = new OtrProfileId("test::OtrProfile");
         Profile nonPrimaryOtrProfile1 =
                 ThreadUtils.runOnUiThreadBlocking(
@@ -139,7 +131,7 @@
     /** Test if creating two non-primary profiles result in different objects. */
     @Test
     @LargeTest
-    public void testCreatingTwoNonPrimaryProfiles() throws Exception {
+    public void testCreatingTwoNonPrimaryProfiles() {
         OtrProfileId profileId1 = new OtrProfileId("test::OtrProfile-1");
         Profile nonPrimaryOtrProfile1 =
                 ThreadUtils.runOnUiThreadBlocking(
@@ -196,7 +188,7 @@
     /** Test if creating unique otr profile ids works as expected. */
     @Test
     @LargeTest
-    public void testCreatingUniqueOtrProfileIds() throws Exception {
+    public void testCreatingUniqueOtrProfileIds() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     OtrProfileId profileId1 = OtrProfileId.createUnique("test::OtrProfile");
@@ -213,7 +205,7 @@
     /** Test if creating unique iCCT profile ids works as expected. */
     @Test
     @LargeTest
-    public void testCreatingUniqueIncognitoCCTOtrProfileIds() throws Exception {
+    public void testCreatingUniqueIncognitoCCTOtrProfileIds() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     OtrProfileId incognitoCctId1 = OtrProfileId.createUniqueIncognitoCctId();
@@ -232,7 +224,7 @@
     /** Tests creating iCCT profile. */
     @Test
     @LargeTest
-    public void testIncognitoCctProfileCreation() throws Exception {
+    public void testIncognitoCctProfileCreation() {
         OtrProfileId incognitoCctId = OtrProfileId.createUniqueIncognitoCctId();
         Profile incognitoCctProfile =
                 ThreadUtils.runOnUiThreadBlocking(
@@ -260,7 +252,7 @@
 
     @Test
     @LargeTest
-    public void testBrowserProfileTypeFromRegularProfile() throws Exception {
+    public void testBrowserProfileTypeFromRegularProfile() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     Assert.assertEquals(
@@ -271,9 +263,9 @@
 
     @Test
     @LargeTest
-    public void testBrowserProfileTypeFromPrimaryOtrProfile() throws Exception {
+    public void testBrowserProfileTypeFromPrimaryOtrProfile() {
         // Open an new Incognito Tab page to create a new primary OTR profile.
-        sActivityTestRule.loadUrlInNewTab("about:blank", true);
+        mStartingPage.openRegularTabAppMenu().openNewIncognitoTab().loadAboutBlank();
 
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
@@ -287,7 +279,7 @@
 
     @Test
     @LargeTest
-    public void testBrowserProfileTypeFromNonPrimaryOtrProfile() throws Exception {
+    public void testBrowserProfileTypeFromNonPrimaryOtrProfile() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     OtrProfileId otrProfileId = new OtrProfileId("test::OtrProfile");
@@ -305,7 +297,7 @@
     @LargeTest
     @RequiresRestart(
             "crbug/1161449 - Other tests create profiles which invalidate the first assertion.")
-    public void testGetOffTheRecordProfile() throws Exception {
+    public void testGetOffTheRecordProfile() {
         OtrProfileId profileId = new OtrProfileId("test::OtrProfile");
 
         // Ask for a non-existing profile with createIfNeeded set to false, and expect null.
@@ -350,7 +342,7 @@
     /** Tests createIfNeeded parameter of getPrimaryOtrProfile. */
     @Test
     @LargeTest
-    public void testGetPrimaryOtrProfile() throws Exception {
+    public void testGetPrimaryOtrProfile() {
         // Ask for a non-existing profile with createIfNeeded set to false, and expect null.
         Profile profile1 =
                 ThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettingsTest.java
index 7b1a2ad..959f592 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettingsTest.java
@@ -6,9 +6,11 @@
 
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.pressKey;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.matcher.RootMatchers.isDialog;
 import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static androidx.test.espresso.matcher.ViewMatchers.hasFocus;
 import static androidx.test.espresso.matcher.ViewMatchers.hasSibling;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
@@ -29,6 +31,7 @@
 
 import android.app.Dialog;
 import android.os.Bundle;
+import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
@@ -1187,6 +1190,20 @@
                 .check(matches(isDisplayed()));
     }
 
+    @Test
+    @LargeTest
+    public void testKeyboardNavigationToSignOutButton() {
+        mSyncTestRule.setUpAccountAndSignInForTesting();
+        final ManageSyncSettings fragment = startManageSyncPreferences();
+        RecyclerView recyclerView = fragment.getView().findViewById(R.id.recycler_view);
+        // There are 3 non-selectable preferences in the preference screen: account_section_header,
+        // account_section_footer, and account_advanced_header.
+        for (int i = 0; i < recyclerView.getAdapter().getItemCount() - 3; ++i) {
+            onView(withId(R.id.recycler_view)).perform(pressKey(KeyEvent.KEYCODE_DPAD_DOWN));
+        }
+        onView(withId(R.id.sign_out_button)).check(matches(hasFocus()));
+    }
+
     // TODO(crbug.com/330438265): Extend this test for the identity error card.
     @Test
     @SmallTest
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegateUnitTest.java
index b74b77f..af12fa9 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegateUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollDelegateUnitTest.java
@@ -36,7 +36,12 @@
     private static final float REORDER_START_MARGIN = 10.f;
     private static final float TRAILING_MARGIN_WIDTH = 10.f;
 
-    private static final float TEST_MIN_SCROLL_OFFSET = -200.f;
+    /**
+     * The scroll offset limit of the tab strip, which is a 1-D vector along the X axis under the
+     * dynamic coordinate system used by {@link ScrollDelegate}.
+     */
+    private static final float TEST_SCROLL_OFFSET_LIMIT = -200.f;
+
     private static final long TIMESTAMP = 0;
 
     private final Context mContext = RuntimeEnvironment.systemContext;
@@ -52,7 +57,7 @@
     @Before
     public void setup() {
         mScrollDelegate = new ScrollDelegate(mContext);
-        mScrollDelegate.setMinScrollOffsetForTesting(TEST_MIN_SCROLL_OFFSET);
+        mScrollDelegate.setScrollOffsetLimitForTesting(TEST_SCROLL_OFFSET_LIMIT);
     }
 
     @Test
@@ -62,7 +67,7 @@
         mScrollDelegate.setScrollOffset(newScrollOffset);
         assertEquals(
                 /* message= */ "Offset should be clamped.",
-                TEST_MIN_SCROLL_OFFSET,
+                TEST_SCROLL_OFFSET_LIMIT,
                 mScrollDelegate.getScrollOffset(),
                 /* delta= */ 0);
     }
@@ -140,7 +145,7 @@
         // stripWidth = width(150) - leftMargin(5) - rightMargin(5) = 140
         // viewsWidth = 3*(viewWidth(110) - overlapWidth(10)) + overlapWidth(10) = 310
         // marginsWidth = trailingMarginWidth(10) + reorderStartMargin(10) = 20
-        // expectedMinScrollOffset = viewsWidth(310) + marginsWidth(20) - stripWidth(140) = -190
+        // expectedScrollOffsetLimit = viewsWidth(310) + marginsWidth(20) - stripWidth(140) = -190
         mScrollDelegate.setReorderStartMargin(REORDER_START_MARGIN);
         mScrollDelegate.updateScrollOffsetLimits(
                 mViews,
@@ -150,11 +155,11 @@
                 VIEW_WIDTH,
                 VIEW_OVERLAP_WIDTH,
                 VIEW_OVERLAP_WIDTH);
-        float expectedMinScrollOffset = -190.f;
+        float expectedScrollOffsetLimit = -190.f;
         assertEquals(
-                /* message= */ "minScrollOffset was not as calculated.",
-                expectedMinScrollOffset,
-                mScrollDelegate.getMinScrollOffsetForTesting(),
+                /* message= */ "scrollOffsetLimit was not as calculated.",
+                expectedScrollOffsetLimit,
+                mScrollDelegate.getScrollOffsetLimitForTesting(),
                 /* delta= */ 0);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java
index 5d43109..f377f4b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java
@@ -190,6 +190,10 @@
                         ((TintedCompositorButton) mModelSelectorButton).getTint(),
                         ((TintedCompositorButton) mModelSelectorButton).getBackgroundTint(),
                         mModelSelectorButton.getOpacity(),
+                        false,
+                        R.drawable.circular_button_keyfocus,
+                        MaterialColors.getColor(
+                                mContext, R.attr.colorPrimary, /* defaultValue= */ 0),
                         mResourceManager);
         verify(mTabStripSceneMock)
                 .updateNewTabButton(
@@ -205,6 +209,11 @@
                         /* tint= */ anyInt(),
                         /* backgroundTint= */ anyInt(),
                         /* buttonAlpha= */ anyFloat(),
+                        /* isKeyboardFocused= */ eq(false),
+                        /* keyboardFocusRingResourceId= */ eq(R.drawable.circular_button_keyfocus),
+                        /* keyboardFocusRingColor= */ eq(
+                                MaterialColors.getColor(
+                                        mContext, R.attr.colorPrimary, /* defaultValue= */ 0)),
                         /* resourceManager= */ eq(mResourceManager));
         verify(mTabStripSceneMock)
                 .updateTabStripLeftFade(
@@ -245,7 +254,7 @@
                         anyInt(),
                         anyInt(),
                         eq(false),
-                        eq(R.drawable.close_button_keyfocus),
+                        eq(R.drawable.circular_button_keyfocus),
                         anyInt(),
                         anyInt(),
                         anyInt(),
@@ -310,7 +319,7 @@
                         anyInt(),
                         anyInt(),
                         eq(false),
-                        eq(R.drawable.close_button_keyfocus),
+                        eq(R.drawable.circular_button_keyfocus),
                         anyInt(),
                         anyInt(),
                         anyInt(),
@@ -373,7 +382,7 @@
                         anyInt(),
                         anyInt(),
                         eq(false),
-                        eq(R.drawable.close_button_keyfocus),
+                        eq(R.drawable.circular_button_keyfocus),
                         anyInt(),
                         anyInt(),
                         anyInt(),
@@ -437,7 +446,7 @@
                         anyInt(),
                         anyInt(),
                         eq(true),
-                        eq(R.drawable.close_button_keyfocus),
+                        eq(R.drawable.circular_button_keyfocus),
                         anyInt(),
                         anyInt(),
                         anyInt(),
@@ -525,4 +534,57 @@
                         eq(mLayerTitleCache),
                         eq(mResourceManager));
     }
+
+    @Test
+    public void testUpdateNewTabButton() {
+        mNewTabButton.setKeyboardFocused(true);
+        mTabStripSceneLayer.pushButtonsAndBackground(
+                mStripLayoutHelperManager, mResourceManager, 0, 0, 0.0f, 0.0f, 0.0f, 0.0f);
+        verify(mTabStripSceneMock, times(1))
+                .updateNewTabButton(
+                        eq(1L),
+                        eq(mTabStripSceneLayer),
+                        anyInt(),
+                        anyInt(),
+                        anyFloat(),
+                        anyFloat(),
+                        anyFloat(),
+                        anyBoolean(),
+                        anyBoolean(),
+                        anyInt(),
+                        anyInt(),
+                        anyFloat(),
+                        eq(true),
+                        eq(R.drawable.circular_button_keyfocus),
+                        eq(
+                                MaterialColors.getColor(
+                                        mContext, R.attr.colorPrimary, /* defaultValue= */ 0)),
+                        eq(mResourceManager));
+    }
+
+    @Test
+    public void testUpdateModelSelectorButton() {
+        mModelSelectorButton.setKeyboardFocused(true);
+        mTabStripSceneLayer.pushButtonsAndBackground(
+                mStripLayoutHelperManager, mResourceManager, 0, 0, 0.0f, 0.0f, 0.0f, 0.0f);
+        verify(mTabStripSceneMock, times(1))
+                .updateModelSelectorButton(
+                        eq(1L),
+                        eq(mTabStripSceneLayer),
+                        anyInt(),
+                        anyInt(),
+                        anyFloat(),
+                        anyFloat(),
+                        anyBoolean(),
+                        anyBoolean(),
+                        anyInt(),
+                        anyInt(),
+                        anyFloat(),
+                        eq(true),
+                        eq(R.drawable.circular_button_keyfocus),
+                        eq(
+                                MaterialColors.getColor(
+                                        mContext, R.attr.colorPrimary, /* defaultValue= */ 0)),
+                        eq(mResourceManager));
+    }
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 7dd367f..58c92ce8 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10726,6 +10726,12 @@
         <message name="IDS_PASSWORDS_SAVE_PRIMING_PROMO_SCREENREADER" is_accessibility_with_no_ui="true" desc="Screenreader text for IPH prompting users to consider saving passwords">
           You can save passwords with Google Password Manager when you are signed in to Chrome
         </message>
+        <message name="IDS_PASSWORDS_SAVE_RECOVERY_PROMO_BODY" desc="Body of IPH prompting users to reconsider saving passwords">
+          To save your password to Google Password Manager, click the key
+        </message>
+        <message name="IDS_PASSWORDS_SAVE_RECOVERY_PROMO_SCREENREADER" is_accessibility_with_no_ui="true" desc="Screenreader text for IPH prompting users to reconsider saving passwords">
+          To save your password to Google Password Manager, the Password Manager icon in the Location Bar
+        </message>
         <message name="IDS_PASSWORD_MANAGER_IPH_MANAGEMENT_BUBBLE_AFTER_SAVE" desc="Body of the in Product Help shown after saving a password informing the user about the password management bubble">
           To view your password or add a note about it, click the key icon
         </message>
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORDS_SAVE_RECOVERY_PROMO_BODY.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORDS_SAVE_RECOVERY_PROMO_BODY.png.sha1
new file mode 100644
index 0000000..a70e5942
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORDS_SAVE_RECOVERY_PROMO_BODY.png.sha1
@@ -0,0 +1 @@
+9d95b71f6b9939c34bc7428d11b234827bb95222
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 0093824..9bbe440 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1992,9 +1992,6 @@
   <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED" desc="Label for safe browsing enhanced protection mode">
     Enhanced protection
   </message>
-  <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC" desc="Description of safe browsing enhanced protection mode">
-    Real-time, proactive protection against dangerous sites, downloads, and extensions that's based on your browsing data getting sent to Google
-  </message>
   <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC_UPDATED" desc="Description of safe browsing enhanced protection mode">
     Real-time, AI-powered protection against dangerous sites, downloads, and extensions that's based on your browsing data getting sent to Google
   </message>
@@ -2022,9 +2019,6 @@
   <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FOUR" desc="Bullet point under the Safe Browsing enhanced protection mode section titled 'When on'">
     Improves security for you and everyone on the web.
   </message>
-  <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FIVE" desc="Bullet point under the Safe Browsing enhanced protection mode section titled 'When on'">
-    Warns you if you use a password that has been compromised in a data breach.
-  </message>
   <message name="IDS_SETTINGS_SAFEBROWSING_ENHANCED_THINGS_TO_CONSIDER_BULLET_ONE" desc="Bullet point under the Safe Browsing enhanced protection mode section titled 'Things to consider'">
     Sends the URLs of sites you visit and a small sample of page content, downloads, extension activity, and system information to Google Safe Browsing to check if they're harmful.
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC.png.sha1
deleted file mode 100644
index 948d0b6..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a15f5920c17e9e26685c8700c6fb6e147090df90
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FIVE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FIVE.png.sha1
deleted file mode 100644
index f644b477e1..0000000
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FIVE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3d01ff69262cab8715f4e1ddea813d01b0b4cc75
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d0b47f6..9422b081 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -538,7 +538,6 @@
     "first_party_sets/first_party_sets_navigation_throttle.cc",
     "first_party_sets/first_party_sets_navigation_throttle.h",
     "first_party_sets/first_party_sets_policy_service.cc",
-    "first_party_sets/first_party_sets_policy_service.h",
     "first_party_sets/first_party_sets_policy_service_factory.cc",
     "first_party_sets/first_party_sets_policy_service_factory.h",
     "flag_descriptions.cc",
@@ -1003,6 +1002,8 @@
     "password_manager/field_info_manager_factory.h",
     "password_manager/password_change/change_form_submission_verifier.cc",
     "password_manager/password_change/change_form_submission_verifier.h",
+    "password_manager/password_change/change_password_form_finder.cc",
+    "password_manager/password_change/change_password_form_finder.h",
     "password_manager/password_change/change_password_form_waiter.cc",
     "password_manager/password_change/change_password_form_waiter.h",
     "password_manager/password_change_delegate.h",
@@ -1257,7 +1258,6 @@
     "privacy_sandbox/notice/notice_service_factory.h",
     "privacy_sandbox/privacy_sandbox_countries.h",
     "privacy_sandbox/privacy_sandbox_countries_impl.cc",
-    "privacy_sandbox/privacy_sandbox_countries_impl.h",
     "privacy_sandbox/privacy_sandbox_notice_confirmation.cc",
     "privacy_sandbox/privacy_sandbox_notice_confirmation.h",
     "privacy_sandbox/privacy_sandbox_policy_handler.cc",
@@ -2084,6 +2084,7 @@
     "//components/collaboration/internal",
     "//components/collaboration/internal:collaboration_finder",
     "//components/collaboration/public",
+    "//components/collaboration/public:prefs",
     "//components/color",
     "//components/commerce/content/browser:browser",
     "//components/commerce/core:commerce_heuristics_data",
@@ -7676,8 +7677,6 @@
       # They should be removed.
       "extensions/desktop_android/desktop_android_extension_host_delegate.cc",
       "extensions/desktop_android/desktop_android_extension_host_delegate.h",
-      "extensions/desktop_android/desktop_android_extension_system.cc",
-      "extensions/desktop_android/desktop_android_extension_system.h",
       "extensions/desktop_android/desktop_android_extensions_browser_client.cc",
       "extensions/desktop_android/desktop_android_extensions_browser_client.h",
       "extensions/desktop_android/desktop_android_runtime_api_delegate.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 84ed82d5..db1e23db 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2465,6 +2465,16 @@
 #endif  // BUILDFLAG(IS_ANDROID)
 
 const FeatureEntry::FeatureParam
+    kReportNotificationContentDetectionDataRate100[] = {
+        {"ReportNotificationContentDetectionDataRate", "100"}};
+const FeatureEntry::FeatureVariation
+    kReportNotificationContentDetectionDataVariations[] = {
+        {"with reporting rate 100",
+         kReportNotificationContentDetectionDataRate100,
+         std::size(kReportNotificationContentDetectionDataRate100), nullptr},
+};
+
+const FeatureEntry::FeatureParam
     kResamplingScrollEventsPredictionTimeBasedEnabled[] = {
         {"mode", features::kPredictionTypeTimeBased},
         {"latency", features::kPredictionTypeDefaultTime}};
@@ -7567,6 +7577,15 @@
 
 #endif  // BUILDFLAG(IS_ANDROID)
 
+    {"report-notification-content-detection-data",
+     flag_descriptions::kReportNotificationContentDetectionDataName,
+     flag_descriptions::kReportNotificationContentDetectionDataDescription,
+     kOsAndroid,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         safe_browsing::kReportNotificationContentDetectionData,
+         kReportNotificationContentDetectionDataVariations,
+         "ReportNotificationContentDetectionData")},
+
     {"show-warnings-for-suspicious-notifications",
      flag_descriptions::kShowWarningsForSuspiciousNotificationsName,
      flag_descriptions::kShowWarningsForSuspiciousNotificationsDescription,
@@ -11483,11 +11502,6 @@
      flag_descriptions::kAutofillEnableCardBenefitsIphDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardBenefitsIph)},
 
-    {"privacy-sandbox-privacy-policy",
-     flag_descriptions::kPrivacySandboxPrivacyPolicyName,
-     flag_descriptions::kPrivacySandboxPrivacyPolicyDescription, kOsAll,
-     FEATURE_VALUE_TYPE(privacy_sandbox::kPrivacySandboxPrivacyPolicy)},
-
 #if BUILDFLAG(IS_ANDROID)
     {"support-multiple-server-requests-for-pix-payments",
      flag_descriptions::kSupportMultipleServerRequestsForPixPaymentsName,
@@ -12317,6 +12331,13 @@
      FEATURE_VALUE_TYPE(
          blink::features::kMediaPlaybackWhileNotVisiblePermissionPolicy)},
 
+#if BUILDFLAG(IS_ANDROID)
+    {"android-adaptive-frame-rate",
+     flag_descriptions::kAndroidAdaptiveFrameRateName,
+     flag_descriptions::kAndroidAdaptiveFrameRateDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kUseFrameIntervalDeciderAdaptiveFrameRate)},
+#endif  // BUILDFLAG(IS_ANDROID)
+
     // Add new entries above this line.
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
index a2ab9f42..e9120f5a 100644
--- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -37,12 +37,15 @@
       foreground_group_titles_(cc::slim::Layer::Create()),
       new_tab_button_(cc::slim::UIResourceLayer::Create()),
       new_tab_button_background_(cc::slim::UIResourceLayer::Create()),
+      new_tab_button_keyboard_focus_ring_(cc::slim::UIResourceLayer::Create()),
       left_fade_(cc::slim::UIResourceLayer::Create()),
       right_fade_(cc::slim::UIResourceLayer::Create()),
       left_padding_layer_(cc::slim::SolidColorLayer::Create()),
       right_padding_layer_(cc::slim::SolidColorLayer::Create()),
       model_selector_button_(cc::slim::UIResourceLayer::Create()),
       model_selector_button_background_(cc::slim::UIResourceLayer::Create()),
+      model_selector_button_keyboard_focus_ring_(
+          cc::slim::UIResourceLayer::Create()),
       scrim_layer_(cc::slim::SolidColorLayer::Create()),
       content_tree_(nullptr) {
   new_tab_button_->SetIsDrawable(true);
@@ -85,6 +88,8 @@
   tab_strip_layer_->AddChild(new_tab_button_background_);
   tab_strip_layer_->AddChild(model_selector_button_);
   tab_strip_layer_->AddChild(new_tab_button_);
+  tab_strip_layer_->AddChild(model_selector_button_keyboard_focus_ring_);
+  tab_strip_layer_->AddChild(new_tab_button_keyboard_focus_ring_);
 
   layer()->AddChild(background_layer_);
 }
@@ -233,6 +238,9 @@
     jint tint,
     jint background_tint,
     jfloat button_alpha,
+    jboolean is_keyboard_focused,
+    jint keyboard_focus_ring_resource_id,
+    jint keyboard_focus_ring_color,
     const JavaParamRef<jobject>& jresource_manager) {
   ui::ResourceManager* resource_manager =
       ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
@@ -241,12 +249,17 @@
   ui::Resource* background_resource =
       resource_manager->GetStaticResourceWithTint(bg_resource_id,
                                                   background_tint, true);
+  ui::Resource* keyboard_focus_ring_drawable =
+      resource_manager->GetStaticResourceWithTint(
+          keyboard_focus_ring_resource_id, keyboard_focus_ring_color, true);
 
   x += touch_target_offset;
 
   UpdateCompositorButton(new_tab_button_, new_tab_button_background_,
                          button_resource, background_resource, x, y, visible,
-                         should_apply_hover_highlight, button_alpha);
+                         should_apply_hover_highlight, button_alpha,
+                         new_tab_button_keyboard_focus_ring_,
+                         is_keyboard_focused, keyboard_focus_ring_drawable);
 }
 
 void TabStripSceneLayer::UpdateModelSelectorButton(
@@ -261,6 +274,9 @@
     jint tint,
     jint background_tint,
     jfloat button_alpha,
+    jboolean is_keyboard_focused,
+    jint keyboard_focus_ring_resource_id,
+    jint keyboard_focus_ring_color,
     const JavaParamRef<jobject>& jresource_manager) {
   ui::ResourceManager* resource_manager =
       ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
@@ -269,11 +285,16 @@
   ui::Resource* background_resource =
       resource_manager->GetStaticResourceWithTint(bg_resource_id,
                                                   background_tint, true);
+  ui::Resource* keyboard_focus_ring_drawable =
+      resource_manager->GetStaticResourceWithTint(
+          keyboard_focus_ring_resource_id, keyboard_focus_ring_color, true);
 
   UpdateCompositorButton(model_selector_button_,
                          model_selector_button_background_, button_resource,
                          background_resource, x, y, visible,
-                         should_apply_hover_highlight, button_alpha);
+                         should_apply_hover_highlight, button_alpha,
+                         model_selector_button_keyboard_focus_ring_,
+                         is_keyboard_focused, keyboard_focus_ring_drawable);
 }
 
 void TabStripSceneLayer::UpdateCompositorButton(
@@ -285,7 +306,10 @@
     float y,
     bool visible,
     bool should_apply_hover_highlight,
-    float button_alpha) {
+    float button_alpha,
+    scoped_refptr<cc::slim::UIResourceLayer> keyboard_focus_ring_layer,
+    bool is_keyboard_focused,
+    ui::Resource* keyboard_focus_ring_drawable) {
   button->SetUIResourceId(button_resource->ui_resource()->id());
   button->SetBounds(button_resource->size());
   button->SetHideLayerAndSubtree(!visible);
@@ -306,6 +330,23 @@
     background->SetHideLayerAndSubtree(!visible);
     background->SetOpacity(button_alpha);
   }
+
+  if (is_keyboard_focused) {
+    keyboard_focus_ring_layer->SetIsDrawable(true);
+    keyboard_focus_ring_layer->SetUIResourceId(
+        keyboard_focus_ring_drawable->ui_resource()->id());
+    gfx::Size ring_size = keyboard_focus_ring_drawable->size();
+
+    float ring_x_offset = (background_size.width() - ring_size.width()) / 2;
+    float ring_y_offset = (background_size.height() - ring_size.height()) / 2;
+    keyboard_focus_ring_layer->SetPosition(
+        gfx::PointF(x + ring_x_offset, y + ring_y_offset));
+    keyboard_focus_ring_layer->SetBounds(ring_size);
+  } else {
+    // If the keyboard focus ring is already showing, make sure it stops
+    // showing.
+    keyboard_focus_ring_layer->SetIsDrawable(false);
+  }
 }
 
 void TabStripSceneLayer::UpdateTabStripLeftFade(
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
index 1078f5a..55a7fe49 100644
--- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
@@ -87,6 +87,9 @@
       jint tint,
       jint background_tint,
       jfloat button_alpha,
+      jboolean is_keyboard_focused,
+      jint keyboard_focus_ring_resource_id,
+      jint keyboard_focus_ring_color,
       const base::android::JavaParamRef<jobject>& jresource_manager);
 
   void UpdateModelSelectorButton(
@@ -101,6 +104,9 @@
       jint tint,
       jint background_tint,
       jfloat button_alpha,
+      jboolean is_keyboard_focused,
+      jint keyboard_focus_ring_resource_id,
+      jint keyboard_focus_ring_color,
       const base::android::JavaParamRef<jobject>& jresource_manager);
 
   void UpdateTabStripLeftFade(
@@ -214,7 +220,10 @@
       float y,
       bool visible,
       bool should_apply_hover_highlight,
-      float button_alpha);
+      float button_alpha,
+      scoped_refptr<cc::slim::UIResourceLayer> keyboard_focus_ring_layer,
+      bool is_keyboard_focused,
+      ui::Resource* keyboard_focus_ring_drawable);
 
   typedef std::vector<scoped_refptr<TabHandleLayer>> TabHandleLayerList;
 
@@ -227,6 +236,7 @@
   scoped_refptr<cc::slim::Layer> foreground_group_titles_;
   scoped_refptr<cc::slim::UIResourceLayer> new_tab_button_;
   scoped_refptr<cc::slim::UIResourceLayer> new_tab_button_background_;
+  scoped_refptr<cc::slim::UIResourceLayer> new_tab_button_keyboard_focus_ring_;
   scoped_refptr<cc::slim::UIResourceLayer> left_fade_;
   scoped_refptr<cc::slim::UIResourceLayer> right_fade_;
 
@@ -237,6 +247,8 @@
 
   scoped_refptr<cc::slim::UIResourceLayer> model_selector_button_;
   scoped_refptr<cc::slim::UIResourceLayer> model_selector_button_background_;
+  scoped_refptr<cc::slim::UIResourceLayer>
+      model_selector_button_keyboard_focus_ring_;
   scoped_refptr<cc::slim::SolidColorLayer> scrim_layer_;
 
   unsigned write_index_ = 0;
diff --git a/chrome/browser/ash/app_list/BUILD.gn b/chrome/browser/ash/app_list/BUILD.gn
index 39d134a..a2201e3 100644
--- a/chrome/browser/ash/app_list/BUILD.gn
+++ b/chrome/browser/ash/app_list/BUILD.gn
@@ -301,25 +301,6 @@
     "//ui/views:test_support",
     "//ui/wm",
   ]
-
-  if (enable_assistant_integration_tests) {
-    sources += [ "launcher_search_iph_browsertest.cc" ]
-
-    deps += [
-      "//ash/app_list:test_support",
-      "//ash/assistant/ui",
-      "//ash/assistant/ui:constants",
-      "//chrome/browser/ui/ash/assistant:browser_test_support",
-      "//chromeos/ash/components/assistant/test_support",
-      "//chromeos/ash/services/assistant/public/cpp",
-      "//chromeos/assistant/internal:libassistant",
-      "//components/feature_engagement/test:test_support",
-    ]
-
-    data = [ "//chromeos/assistant/internal/test_data/" ]
-
-    data_deps = [ "//chromeos/assistant/internal:build_fake_s3_server_main" ]
-  }
 }
 
 if (!is_chromeos_device) {
diff --git a/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc b/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc
deleted file mode 100644
index 15191c56..0000000
--- a/chrome/browser/ash/app_list/launcher_search_iph_browsertest.cc
+++ /dev/null
@@ -1,803 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/app_list/app_list_controller_impl.h"
-#include "ash/app_list/app_list_presenter_impl.h"
-#include "ash/app_list/app_list_public_test_util.h"
-#include "ash/app_list/views/app_list_bubble_view.h"
-#include "ash/app_list/views/app_list_main_view.h"
-#include "ash/app_list/views/app_list_view.h"
-#include "ash/app_list/views/assistant/assistant_test_api_impl.h"
-#include "ash/app_list/views/contents_view.h"
-#include "ash/app_list/views/pagination_model_transition_waiter.h"
-#include "ash/app_list/views/search_box_view.h"
-#include "ash/assistant/assistant_controller_impl.h"
-#include "ash/assistant/test/test_assistant_service.h"
-#include "ash/assistant/ui/assistant_view_ids.h"
-#include "ash/assistant/ui/main_stage/assistant_zero_state_view.h"
-#include "ash/assistant/ui/main_stage/chip_view.h"
-#include "ash/assistant/ui/main_stage/launcher_search_iph_view.h"
-#include "ash/public/cpp/accelerators.h"
-#include "ash/public/cpp/app_list/app_list_types.h"
-#include "ash/public/cpp/test/app_list_test_api.h"
-#include "ash/shell.h"
-#include "ash/test/ash_test_base.h"
-#include "ash/test/view_drawn_waiter.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/run_loop.h"
-#include "base/scoped_observation.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/gtest_tags.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/ash/app_list/app_list_client_impl.h"
-#include "chrome/browser/ash/app_list/search/search_controller.h"
-#include "chrome/browser/feature_engagement/tracker_factory.h"
-#include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "chromeos/ash/services/assistant/public/cpp/assistant_enums.h"
-#include "chromeos/ash/services/assistant/public/cpp/features.h"
-#include "components/feature_engagement/public/feature_constants.h"
-#include "components/feature_engagement/test/scoped_iph_feature_list.h"
-#include "content/public/test/browser_test.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/events/keycodes/keyboard_codes_posix.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/views/controls/button/image_button.h"
-#include "ui/views/controls/styled_label.h"
-#include "ui/views/view.h"
-#include "ui/views/view_observer.h"
-
-namespace {
-
-constexpr char kScreenPlayTagName[] = "feature_id";
-constexpr char kScreenPlayTagValue[] =
-    "screenplay-3adcce6b-a470-48b0-9246-f6570c5cef34";
-
-constexpr char kNotifyUsedEventUserActionName[] =
-    "InProductHelp.NotifyUsedEvent.IPH_LauncherSearchHelpUi";
-constexpr char kNotifyEventUserActionName[] =
-    "InProductHelp.NotifyEvent.IPH_LauncherSearchHelpUi";
-
-class ViewWaiter : public views::ViewObserver {
- public:
-  ViewWaiter(views::View* observed_view, int view_id)
-      : observed_view_(observed_view), view_id_(view_id) {}
-
-  void Run() {
-    if (observed_view_->GetViewByID(view_id_)) {
-      return;
-    }
-
-    scoped_observation_.Observe(observed_view_);
-    run_loop.Run();
-  }
-
-  void OnViewHierarchyChanged(
-      views::View* observed_view,
-      const views::ViewHierarchyChangedDetails& details) override {
-    if (observed_view_->GetViewByID(view_id_)) {
-      run_loop.Quit();
-    }
-  }
-
- private:
-  raw_ptr<views::View> observed_view_;
-  int view_id_;
-  base::ScopedObservation<views::View, ViewWaiter> scoped_observation_{this};
-  base::RunLoop run_loop;
-};
-
-class IphWaiter {
- public:
-  IphWaiter() = default;
-  ~IphWaiter() = default;
-
-  void Run(feature_engagement::Tracker* tracker) {
-    base::RunLoop run_loop;
-    tracker->AddOnInitializedCallback(base::BindOnce(
-        [](base::OnceClosure callback, bool success) {
-          ASSERT_TRUE(success);
-          std::move(callback).Run();
-        },
-        run_loop.QuitClosure()));
-    run_loop.Run();
-  }
-};
-
-bool IsLauncherSearchIphViewVisible() {
-  ash::SearchBoxView* search_box_view = ash::GetSearchBoxView();
-  if (!search_box_view) {
-    return false;
-  }
-
-  views::View* launcher_search_iph_view =
-      search_box_view->GetViewByID(ash::LauncherSearchIphView::ViewId::kSelf);
-  if (!launcher_search_iph_view) {
-    return false;
-  }
-
-  return launcher_search_iph_view->GetVisible();
-}
-
-std::string GenerateTestSuffix(const testing::TestParamInfo<bool>& info) {
-  return info.param ? "tablet" : "clamshell";
-}
-
-ash::assistant::LauncherSearchIphQueryType GetQueryType(
-    const std::u16string& query) {
-  if (query == u"Weather") {
-    return ash::assistant::LauncherSearchIphQueryType::kWeather;
-  }
-  if (query == u"5 ft in m") {
-    return ash::assistant::LauncherSearchIphQueryType::kUnitConversion1;
-  }
-  if (query == u"90°F in C") {
-    return ash::assistant::LauncherSearchIphQueryType::kUnitConversion2;
-  }
-  if (query == u"Hi in French") {
-    return ash::assistant::LauncherSearchIphQueryType::kTranslation;
-  }
-  if (query == u"Define zenith") {
-    return ash::assistant::LauncherSearchIphQueryType::kDefinition;
-  }
-  if (query == u"50+94/5") {
-    return ash::assistant::LauncherSearchIphQueryType::kCalculation;
-  }
-  NOTREACHED();
-}
-
-}  // namespace
-
-class AppListIphBrowserTest : public MixinBasedInProcessBrowserTest,
-                              public testing::WithParamInterface<bool> {
- public:
-  void SetUpOnMainThread() override {
-    ash::Shell::Get()->tablet_mode_controller()->SetEnabledForTest(GetParam());
-    ash::Shell::Get()->assistant_controller()->SetAssistant(&test_service_);
-    test_api_impl_.EnableAssistantAndWait();
-    event_generator_ = std::make_unique<ui::test::EventGenerator>(
-        ash::Shell::GetPrimaryRootWindow());
-
-    app_list_client_impl_ = AppListClientImpl::GetInstance();
-    app_list_client_impl_->UpdateProfile();
-    base::AddTagToTestResult(kScreenPlayTagName, kScreenPlayTagValue);
-
-    tracker_ = feature_engagement::TrackerFactory::GetForBrowserContext(
-        browser()->profile());
-
-    scoped_iph_feature_list_.InitWithExistingFeatures(
-        {feature_engagement::kIPHLauncherSearchHelpUiFeature});
-
-    MixinBasedInProcessBrowserTest::SetUpOnMainThread();
-  }
-
-  void TearDownOnMainThread() override { DisableAssistant(); }
-
- protected:
-  void DisableAssistant() { test_api_impl_.SetAssistantEnabled(false); }
-
-  // Provides both `IsClamshellModeTest` and `IsTabletModeTest` to be able to
-  // write `if(IsClamshellModeTest)` instead of `if(!IsTabletModeTest)` for
-  // readbility.
-  bool IsClamshellModeTest() const { return !GetParam(); }
-  bool IsTabletModeTest() const { return GetParam(); }
-
-  bool IsAppListVisible() const {
-    return ash::AppListControllerImpl::Get()->IsVisible();
-  }
-
-  void OpenAppList() {
-    ASSERT_FALSE(IsAppListVisible());
-
-    if (IsClamshellModeTest()) {
-      app_list_client_impl_->ShowAppList(ash::AppListShowSource::kSearchKey);
-
-      // We dispatch mouse events to interact with UI. Wait animation completion
-      // to reliably dispatch those events.
-      ash::AppListTestApi().WaitForBubbleWindow(
-          /*wait_for_opening_animation=*/true);
-    } else {
-      ash::AcceleratorController::Get()->PerformActionIfEnabled(
-          ash::AcceleratorAction::kToggleAppList, {});
-
-      // We dispatch mouse events to interact with UI. Wait animation completion
-      // to reliably dispatch those events.
-      ash::AppListTestApi().WaitForAppListShowAnimation(
-          /*is_bubble_window=*/false);
-    }
-
-    ASSERT_TRUE(IsAppListVisible());
-  }
-
-  // Opens app list and activates the search box if necessary. The search box is
-  // active by default in clamshell mode.
-  void OpenAppListForSearch() {
-    OpenAppList();
-
-    if (IsTabletModeTest()) {
-      ash::PaginationModelTransitionWaiter pagination_model_transition_waiter(
-          GetFullscreenAppListContentsView()->pagination_model_for_testing());
-      Click(search_box_view());
-      pagination_model_transition_waiter.Wait();
-    }
-
-    ASSERT_TRUE(search_box_view());
-    ASSERT_TRUE(search_box_view()->is_search_box_active());
-  }
-
-  void DismissAppList() {
-    ASSERT_TRUE(IsAppListVisible());
-
-    if (IsClamshellModeTest()) {
-      app_list_client_impl()->DismissView();
-    } else {
-      // In tablet mode, dismiss the app list view by activating a Chrome
-      // browser window for a better prod behavior simulation.
-      // `AppListClientImpl::DismissView` can also dismiss the app list view.
-      // But it puts a UI in a weird state.
-      browser()->window()->Activate();
-    }
-
-    ASSERT_FALSE(IsAppListVisible());
-  }
-
-  void ClickAssistantButton() {
-    if (IsTabletModeTest()) {
-      ash::PaginationModelTransitionWaiter pagination_model_transition_waiter(
-          GetFullscreenAppListContentsView()->pagination_model_for_testing());
-
-      views::ImageButton* assistant_button =
-          search_box_view()->assistant_button();
-      ASSERT_TRUE(assistant_button);
-      Click(assistant_button);
-
-      pagination_model_transition_waiter.Wait();
-      return;
-    }
-
-    views::ImageButton* assistant_button =
-        search_box_view()->assistant_button();
-    ASSERT_TRUE(assistant_button);
-    Click(assistant_button);
-  }
-
-  void ClickAssistantIconAndWaitForIphView() {
-    OpenAppList();
-
-    // IPH should not show when open the Launcher.
-    ASSERT_FALSE(IsLauncherSearchIphViewVisible());
-
-    // Clicks Assistant button to open Assistant UI. IPH will show.
-    ClickAssistantButton();
-
-    // There is an async call for checking IPH trigger condition.
-    ViewWaiter(search_box_view(), ash::LauncherSearchIphView::ViewId::kSelf)
-        .Run();
-    auto* launcher_search_iph_view = search_box_view()->GetViewByID(
-        ash::LauncherSearchIphView::ViewId::kSelf);
-    ash::ViewDrawnWaiter().Wait(launcher_search_iph_view);
-
-    ASSERT_TRUE(IsLauncherSearchIphViewVisible());
-  }
-
-  ash::ContentsView* GetFullscreenAppListContentsView() {
-    return ash::GetAppListView()->app_list_main_view()->contents_view();
-  }
-
-  ash::AssistantZeroStateView* GetAssistantZeroStateView() {
-    if (IsClamshellModeTest()) {
-      return static_cast<ash::AssistantZeroStateView*>(
-          ash::GetAppListBubbleView()->GetViewByID(
-              ash::AssistantViewID::kZeroStateView));
-    }
-
-    return static_cast<ash::AssistantZeroStateView*>(
-        ash::GetAppListView()->GetViewByID(
-            ash::AssistantViewID::kZeroStateView));
-  }
-
-  ash::LauncherSearchIphView* GetAssistantLauncherSearchIph() {
-    if (IsClamshellModeTest()) {
-      return static_cast<ash::LauncherSearchIphView*>(
-          ash::GetAppListBubbleView()->GetViewByID(
-              ash::AssistantViewID::kLauncherSearchIph));
-    }
-
-    return static_cast<ash::LauncherSearchIphView*>(
-        ash::GetAppListView()->GetViewByID(
-            ash::AssistantViewID::kLauncherSearchIph));
-  }
-
-  bool IsSearchPageActive() {
-    if (IsClamshellModeTest()) {
-      return ash::GetAppListBubbleView()->current_page_for_test() ==
-             ash::AppListBubblePage::kSearch;
-    } else {
-      return GetFullscreenAppListContentsView()->IsShowingSearchResults();
-    }
-  }
-
-  bool IsAssistantPageActive() {
-    if (IsClamshellModeTest()) {
-      return ash::GetAppListBubbleView()->current_page_for_test() ==
-             ash::AppListBubblePage::kAssistant;
-    } else {
-      return GetFullscreenAppListContentsView()->IsShowingEmbeddedAssistantUI();
-    }
-  }
-
-  AppListClientImpl* app_list_client_impl() { return app_list_client_impl_; }
-
-  ash::SearchBoxView* search_box_view() { return ash::GetSearchBoxView(); }
-
-  views::View* GetAssistantPageView() { return test_api_impl_.page_view(); }
-
-  void Click(views::View* view) {
-    ASSERT_TRUE(view);
-
-    event_generator_->MoveMouseToInHost(
-        view->GetBoundsInScreen().CenterPoint());
-    event_generator_->ClickLeftButton();
-  }
-
-  void PressAndReleaseKey(ui::KeyboardCode key_code, int flags = ui::EF_NONE) {
-    event_generator_->PressAndReleaseKey(key_code, flags);
-  }
-
-  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
-
-  raw_ptr<feature_engagement::Tracker> tracker_ = nullptr;
-
-  feature_engagement::test::ScopedIphFeatureList scoped_iph_feature_list_;
-
- private:
-  ash::TestAssistantService test_service_;
-  ash::AssistantTestApiImpl test_api_impl_;
-  std::unique_ptr<ui::test::EventGenerator> event_generator_;
-  base::HistogramTester histogram_tester_;
-
-  raw_ptr<AppListClientImpl> app_list_client_impl_ = nullptr;
-};
-
-using AppListIphBrowserTestWithTestConfig = AppListIphBrowserTest;
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTest, LauncherSearchIphShownByDefault) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       NotShowIphWhenOpenForSearch) {
-  IphWaiter().Run(tracker_);
-  OpenAppListForSearch();
-
-  // IPH should not show when open the Launcher.
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       NotShowIphWhenQueryChanges) {
-  IphWaiter().Run(tracker_);
-  OpenAppListForSearch();
-
-  // IPH should not show when open the Launcher.
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-
-  // Do search and confirm that the IPH is not shown.
-  ash::AppListTestApi().SimulateSearch(u"Test");
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       ShowIphWhenClickAssistantButtonInSearchBox) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       DismissIphWhenQueryChanges) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  // Do search and confirm that the IPH gets dismissed.
-  ash::AppListTestApi().SimulateSearch(u"Test");
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       DismissIphWhenQueryIsEmpty) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  // Do search and confirm that the IPH gets dismissed.
-  ash::AppListTestApi().SimulateSearch(u"Test");
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-
-  // Clear the search box query, the IPH is still not visible.
-  ash::AppListTestApi().SimulateSearch(u"");
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-using AppListIphBrowserTestWithTestConfigClamshell =
-    AppListIphBrowserTestWithTestConfig;
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfigClamshell,
-                       ShowAssistantPageWhenClickAssistantButtonInSearchBox) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  // Clicks Assistant button when the IPH is visible will open Assistant UI and
-  // confirm that IPH gets dismissed.
-  ClickAssistantButton();
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfigClamshell,
-                       RecordActionWhenClickAssistantButtonInSearchBox) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  // Confirm that a background is installed as we check that this gets removed
-  // if IPH is not shown below.
-  EXPECT_TRUE(search_box_view()->assistant_button()->GetBackground());
-
-  // Confirm that assistant event is recorded. Make sure that the initial count
-  // is 0 to distinguish this from other events.
-  base::UserActionTester user_action_tester;
-  ASSERT_EQ(0, user_action_tester.GetActionCount(kNotifyEventUserActionName));
-  ClickAssistantButton();
-  EXPECT_EQ(1, user_action_tester.GetActionCount(kNotifyEventUserActionName));
-
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfigClamshell,
-                       NotShowIphAfterClickTwiceAssistantButtonInSearchBox) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  ClickAssistantButton();
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-
-  // Back() to dismiss Launcher.
-  // Open Launcher and click Assistant button again. IPH won't be shown this
-  // time. Note that this behavior is coming from the IPH config.
-  PressAndReleaseKey(ui::VKEY_ESCAPE);
-  OpenAppList();
-  ClickAssistantButton();
-  ash::ViewDrawnWaiter().Wait(GetAssistantPageView());
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig, ClickChip) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  // Chip click is specified as EventUsed in the config.
-  base::UserActionTester user_action_tester;
-  auto* chip = static_cast<ash::ChipView*>(search_box_view()->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kChipStart));
-  ASSERT_TRUE(chip);
-  std::u16string text(chip->GetText());
-  Click(chip);
-  EXPECT_EQ(1,
-            user_action_tester.GetActionCount(kNotifyUsedEventUserActionName));
-  histogram_tester()->ExpectTotalCount(
-      "Assistant.LauncherSearchIphQueryType.SearchBox", 1);
-  histogram_tester()->ExpectBucketCount(
-      "Assistant.LauncherSearchIphQueryType.SearchBox",
-      static_cast<int>(GetQueryType(text)), 1);
-
-  EXPECT_EQ(text, app_list_client_impl()->search_controller()->get_query());
-  EXPECT_TRUE(IsSearchPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-
-  // IPH should be kept being shown as long as the trigger condition in the IPH
-  // config matches.
-  DismissAppList();
-  // Open Launcher again, will still show IPH.
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       ClickAssistantChipInIph) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-  if (IsClamshellModeTest()) {
-    // Confirm that a background is installed as we check that this gets removed
-    // if IPH is not shown below.
-    EXPECT_TRUE(search_box_view()->assistant_button()->GetBackground());
-  }
-
-  // Confirm that assistant event is recorded. Make sure that the initial count
-  // is 0 to distinguish this from other events.
-  base::UserActionTester user_action_tester;
-  ASSERT_EQ(0, user_action_tester.GetActionCount(kNotifyEventUserActionName));
-  views::View* assistant_button = search_box_view()->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kAssistant);
-  ASSERT_TRUE(assistant_button);
-  Click(assistant_button);
-  EXPECT_EQ(1, user_action_tester.GetActionCount(kNotifyEventUserActionName));
-
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       NotShowIphAfterClickAssistantChipInIph) {
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-  if (IsClamshellModeTest()) {
-    // Confirm that a background is installed as we check that this gets removed
-    // if IPH is not shown below.
-    EXPECT_TRUE(search_box_view()->assistant_button()->GetBackground());
-  }
-
-  views::View* assistant_button = search_box_view()->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kAssistant);
-  ASSERT_TRUE(assistant_button);
-  Click(assistant_button);
-
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-
-  // Back() to dismiss Launcher.
-  // Open Launcher and click Assistant button again. IPH won't be shown this
-  // time. Note that this behavior is coming from the IPH config.
-  if (IsTabletModeTest()) {
-    ash::PaginationModelTransitionWaiter pagination_model_transition_waiter(
-        GetFullscreenAppListContentsView()->pagination_model_for_testing());
-
-    PressAndReleaseKey(ui::VKEY_ESCAPE);
-
-    pagination_model_transition_waiter.Wait();
-  } else {
-    PressAndReleaseKey(ui::VKEY_ESCAPE);
-    OpenAppList();
-  }
-
-  ClickAssistantButton();
-  ash::ViewDrawnWaiter().Wait(GetAssistantPageView());
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       RecordEntryExitPointsWhenClickAssistantChip) {
-  auto duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
-      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
-
-  IphWaiter().Run(tracker_);
-  ClickAssistantIconAndWaitForIphView();
-  EXPECT_TRUE(IsLauncherSearchIphViewVisible());
-
-  views::View* assistant_button = search_box_view()->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kAssistant);
-  ASSERT_TRUE(assistant_button);
-  Click(assistant_button);
-
-  EXPECT_TRUE(IsAssistantPageActive());
-  histogram_tester()->ExpectTotalCount("Assistant.EntryPoint", 1);
-  histogram_tester()->ExpectBucketCount("Assistant.EntryPoint",
-                                        /*kLauncherSearchIphChip=*/13, 1);
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestWithTestConfig,
-                       NotShowIphWithoutAssistant) {
-  // `AssistantTestApiImpl::SetAssistantEnabled` asserts that the value has
-  // taken effect, i.e. we are sure that Assistant gets disabled after this
-  // call.
-  DisableAssistant();
-  IphWaiter().Run(tracker_);
-
-  OpenAppListForSearch();
-
-  // There is an async call for IPH to be shown. This test expects that IPH does
-  // NOT get shown. But run `RunUntilIdle` as this test can get failed if we
-  // starts showing an IPH for this case.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_FALSE(IsLauncherSearchIphViewVisible());
-  EXPECT_FALSE(search_box_view()->assistant_button()->GetBackground());
-}
-
-class AppListIphBrowserTestAssistantZeroState
-    : public AppListIphBrowserTestWithTestConfig {
- public:
-  void SetUpOnMainThread() override {
-    AppListIphBrowserTestWithTestConfig::SetUpOnMainThread();
-
-    // Record the click event so that this test suite only tests the
-    // AssistantPageView behaviors.
-    tracker_->NotifyEvent("IPH_LauncherSearchHelpUi_assistant_click");
-  }
-};
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTest,
-                       HasAssistantZeroStateIphByDefault) {
-  ASSERT_TRUE(base::FeatureList::IsEnabled(
-      feature_engagement::kIPHLauncherSearchHelpUiFeature));
-
-  tracker_->NotifyEvent("IPH_LauncherSearchHelpUi_assistant_click");
-  OpenAppList();
-
-  ClickAssistantButton();
-
-  // The LauncherSearchIphView will show in the zero state view.
-  ASSERT_TRUE(IsAssistantPageActive());
-  ASSERT_TRUE(GetAssistantZeroStateView()->GetVisible());
-
-  ash::LauncherSearchIphView* launcher_search_iph =
-      GetAssistantLauncherSearchIph();
-  EXPECT_TRUE(launcher_search_iph->GetVisible());
-  EXPECT_TRUE(launcher_search_iph->IsDrawn());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestAssistantZeroState,
-                       ShowAssistantZeroStateIph) {
-  OpenAppList();
-
-  ClickAssistantButton();
-
-  // The LauncherSearchIphView is shown in the zero state view.
-  ASSERT_TRUE(IsAssistantPageActive());
-  ASSERT_TRUE(GetAssistantZeroStateView()->GetVisible());
-
-  ash::LauncherSearchIphView* launcher_search_iph =
-      GetAssistantLauncherSearchIph();
-  EXPECT_TRUE(launcher_search_iph->GetVisible());
-  EXPECT_TRUE(launcher_search_iph->IsDrawn());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestAssistantZeroState,
-                       DismissAssistantPageAfterClickChip) {
-  auto duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
-      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
-
-  OpenAppList();
-
-  ClickAssistantButton();
-
-  // The LauncherSearchIphView is shown in the zero state view.
-  ASSERT_TRUE(IsAssistantPageActive());
-  ASSERT_TRUE(GetAssistantZeroStateView()->GetVisible());
-
-  ash::LauncherSearchIphView* launcher_search_iph =
-      GetAssistantLauncherSearchIph();
-  EXPECT_TRUE(launcher_search_iph->GetVisible());
-  EXPECT_TRUE(launcher_search_iph->IsDrawn());
-
-  // Chip click will redirect to the search page with query of the chip's text.
-  auto* chip = static_cast<ash::ChipView*>(launcher_search_iph->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kChipStart));
-  ASSERT_TRUE(chip);
-  std::u16string text(chip->GetText());
-  Click(chip);
-
-  histogram_tester()->ExpectTotalCount(
-      "Assistant.LauncherSearchIphQueryType.AssistantPage", 1);
-  histogram_tester()->ExpectBucketCount(
-      "Assistant.LauncherSearchIphQueryType.AssistantPage",
-      static_cast<int>(GetQueryType(text)), 1);
-
-  EXPECT_EQ(text, app_list_client_impl()->search_controller()->get_query());
-  EXPECT_TRUE(IsSearchPageActive());
-  EXPECT_FALSE(IsAssistantPageActive());
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestAssistantZeroState,
-                       RecordExitPointsWhenClickAssistantChip) {
-  auto duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
-      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
-
-  OpenAppList();
-
-  ClickAssistantButton();
-  histogram_tester()->ExpectTotalCount("Assistant.EntryPoint", 1);
-  histogram_tester()->ExpectBucketCount("Assistant.EntryPoint",
-                                        /*kLauncherSearchBoxIcon=*/9, 1);
-
-  ash::LauncherSearchIphView* launcher_search_iph =
-      GetAssistantLauncherSearchIph();
-  EXPECT_TRUE(launcher_search_iph->GetVisible());
-  EXPECT_TRUE(launcher_search_iph->IsDrawn());
-
-  // Chip click will redirect to the search page with query of the chip's text.
-  auto* chip = static_cast<ash::ChipView*>(launcher_search_iph->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kChipStart));
-  ASSERT_TRUE(chip);
-  Click(chip);
-  histogram_tester()->ExpectTotalCount("Assistant.ExitPoint", 1);
-  histogram_tester()->ExpectBucketCount("Assistant.ExitPoint",
-                                        /*kLauncherSearchIphChip=*/13, 1);
-}
-
-IN_PROC_BROWSER_TEST_P(AppListIphBrowserTestAssistantZeroState,
-                       CanOpenAssistantPageAfterClickChip) {
-  auto duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
-      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
-
-  OpenAppList();
-
-  ClickAssistantButton();
-
-  // The LauncherSearchIphView is shown in the zero state view.
-  ASSERT_TRUE(IsAssistantPageActive());
-  ASSERT_TRUE(GetAssistantZeroStateView()->GetVisible());
-
-  ash::LauncherSearchIphView* launcher_search_iph =
-      GetAssistantLauncherSearchIph();
-  EXPECT_TRUE(launcher_search_iph->GetVisible());
-  EXPECT_TRUE(launcher_search_iph->IsDrawn());
-
-  // Chip click will redirect to the search page with query of the chip's text.
-  auto* chip = static_cast<ash::ChipView*>(launcher_search_iph->GetViewByID(
-      ash::LauncherSearchIphView::ViewId::kChipStart));
-  ASSERT_TRUE(chip);
-  auto text = chip->GetText();
-  Click(chip);
-
-  EXPECT_EQ(text, app_list_client_impl()->search_controller()->get_query());
-  EXPECT_TRUE(IsSearchPageActive());
-  EXPECT_FALSE(IsAssistantPageActive());
-
-  // Press ESC key to trigger back action of Launcher.
-  PressAndReleaseKey(ui::VKEY_ESCAPE);
-  EXPECT_EQ(u"", app_list_client_impl()->search_controller()->get_query());
-  EXPECT_FALSE(IsSearchPageActive());
-  EXPECT_FALSE(IsAssistantPageActive());
-
-  // Allow the `test_assistant_service` to finish StopActiveInteraction() call.
-  base::RunLoop().RunUntilIdle();
-
-  // Test after the back action, click the Assistant button will show the
-  // `assistant_page`. (b/309551206)
-  ClickAssistantButton();
-
-  EXPECT_TRUE(IsAssistantPageActive());
-  EXPECT_FALSE(IsSearchPageActive());
-}
-
-INSTANTIATE_TEST_SUITE_P(LauncherSearchIph,
-                         AppListIphBrowserTest,
-                         /*is_tablet_mode=*/testing::Bool(),
-                         &GenerateTestSuffix);
-
-INSTANTIATE_TEST_SUITE_P(LauncherSearchIph,
-                         AppListIphBrowserTestWithTestConfig,
-                         /*is_tablet=*/testing::Bool(),
-                         &GenerateTestSuffix);
-
-INSTANTIATE_TEST_SUITE_P(LauncherSearchIph,
-                         AppListIphBrowserTestWithTestConfigClamshell,
-                         /*is_tablet=*/testing::Values(false),
-                         &GenerateTestSuffix);
-
-INSTANTIATE_TEST_SUITE_P(LauncherSearchIph,
-                         AppListIphBrowserTestAssistantZeroState,
-                         /*is_tablet_mode=*/testing::Bool(),
-                         &GenerateTestSuffix);
diff --git a/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.cc b/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.cc
index b0a3d36..b75a7ad 100644
--- a/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.cc
+++ b/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.cc
@@ -18,15 +18,6 @@
 
 namespace ash::babelorca {
 
-namespace {
-void UnwrapSodaInstallationStatus(
-    base::OnceCallback<void(bool)> availabililty_callback,
-    SodaInstaller::InstallationStatus status) {
-  std::move(availabililty_callback)
-      .Run(status == SodaInstaller::InstallationStatus::kReady);
-}
-}  // namespace
-
 BabelOrcaSpeechRecognizerImpl::BabelOrcaSpeechRecognizerImpl(
     Profile* profile,
     SodaInstaller* soda_installer,
@@ -53,14 +44,14 @@
 
 void BabelOrcaSpeechRecognizerImpl::Start() {
   // If already installed, will immediately begin recognizing.
+  started_ = true;
   soda_installer_->InstallSoda(base::BindOnce(
-      &UnwrapSodaInstallationStatus,
-      base::BindOnce(
-          &SystemLiveCaptionService::SpeechRecognitionAvailabilityChanged,
-          service_ptr_factory_.GetWeakPtr())));
+      &BabelOrcaSpeechRecognizerImpl::OnSpeechRecognitionAvailabilityChanged,
+      weak_ptr_factory_.GetWeakPtr()));
 }
 
 void BabelOrcaSpeechRecognizerImpl::Stop() {
+  started_ = false;
   SpeechRecognitionAvailabilityChanged(false);
 }
 
@@ -85,4 +76,13 @@
              : SystemLiveCaptionService::GetRecognizerClientType();
 }
 
+void BabelOrcaSpeechRecognizerImpl::OnSpeechRecognitionAvailabilityChanged(
+    SodaInstaller::InstallationStatus status) {
+  if (!started_) {
+    return;
+  }
+  SpeechRecognitionAvailabilityChanged(
+      status == SodaInstaller::InstallationStatus::kReady);
+}
+
 }  // namespace ash::babelorca
diff --git a/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.h b/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.h
index 058e3997..616dd5f 100644
--- a/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.h
+++ b/chrome/browser/ash/boca/babelorca/babel_orca_speech_recognizer_impl.h
@@ -26,6 +26,11 @@
   explicit BabelOrcaSpeechRecognizerImpl(Profile* profile,
                                          SodaInstaller* soda_installer,
                                          const std::string& application_locale);
+
+  BabelOrcaSpeechRecognizerImpl(const BabelOrcaSpeechRecognizerImpl&) = delete;
+  BabelOrcaSpeechRecognizerImpl& operator=(
+      const BabelOrcaSpeechRecognizerImpl&) = delete;
+
   ~BabelOrcaSpeechRecognizerImpl() override;
 
   // SystemLiveCaptionService
@@ -50,11 +55,15 @@
   media::mojom::RecognizerClientType GetRecognizerClientType() override;
 
  private:
+  void OnSpeechRecognitionAvailabilityChanged(
+      SodaInstaller::InstallationStatus status);
+
+  bool started_ = false;
   // installer is owned by manager, which owns this class.
   raw_ptr<SodaInstaller> soda_installer_;
   SpeechRecognitionEventHandler speech_recognition_event_handler_;
   raw_ptr<Profile> primary_profile_;
-  base::WeakPtrFactory<SystemLiveCaptionService> service_ptr_factory_{this};
+  base::WeakPtrFactory<BabelOrcaSpeechRecognizerImpl> weak_ptr_factory_{this};
 };
 
 }  // namespace ash::babelorca
diff --git a/chrome/browser/ash/extensions/users_private/users_private_apitest.cc b/chrome/browser/ash/extensions/users_private/users_private_apitest.cc
index a02ceea..0919a40 100644
--- a/chrome/browser/ash/extensions/users_private/users_private_apitest.cc
+++ b/chrome/browser/ash/extensions/users_private/users_private_apitest.cc
@@ -10,6 +10,7 @@
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/test/test_future.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/ash/extensions/users_private/users_private_delegate.h"
@@ -17,6 +18,7 @@
 #include "chrome/browser/ash/login/lock/screen_locker.h"
 #include "chrome/browser/ash/login/lock/screen_locker_tester.h"
 #include "chrome/browser/ash/login/test/oobe_base_test.h"
+#include "chrome/browser/ash/ownership/owner_settings_service_ash.h"
 #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h"
 #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
@@ -154,6 +156,12 @@
         profile(),
         base::BindRepeating(&UsersPrivateApiTest::GetUsersPrivateDelegate));
     content::RunAllPendingInMessageLoop();
+
+    auto* owner_settings_service =
+        ash::OwnerSettingsServiceAshFactory::GetForBrowserContext(profile());
+    base::test::TestFuture<bool> future;
+    owner_settings_service->IsOwnerAsync(future.GetCallback());
+    ASSERT_TRUE(future.Get());
   }
 
  protected:
diff --git a/chrome/browser/autofill/BUILD.gn b/chrome/browser/autofill/BUILD.gn
index 0cc9b95..d03f3137 100644
--- a/chrome/browser/autofill/BUILD.gn
+++ b/chrome/browser/autofill/BUILD.gn
@@ -4,7 +4,6 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/ui.gni")
-import("//chrome/version.gni")
 import("//components/optimization_guide/features.gni")
 import("//extensions/buildflags/buildflags.gni")
 
@@ -186,12 +185,10 @@
       "form_structure_browsertest.cc",
     ]
 
-    defines = [
-      "HAS_OUT_OF_PROC_TEST_RUNNER",
-      "CHROME_VERSION_MAJOR=" + chrome_version_major,
-    ]
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
     deps = [
+      "//base/version_info",
       "//chrome/browser/autofill",
       "//chrome/browser/ui:browser_navigator_params_headers",
       "//chrome/browser/ui/tabs:tab_strip",
diff --git a/chrome/browser/autofill/autocomplete_browsertest.cc b/chrome/browser/autofill/autocomplete_browsertest.cc
index 4511fe32..90096ff 100644
--- a/chrome/browser/autofill/autocomplete_browsertest.cc
+++ b/chrome/browser/autofill/autocomplete_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_callback.h"
 #include "base/time/time.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "chrome/browser/autofill/autocomplete_history_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -172,7 +173,7 @@
   // `autocomplete_history_manager()` and waiting for the cleanup to complete.
   void TriggerRetentionPolicyCleanup() {
     pref_service()->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                               CHROME_VERSION_MAJOR - 1);
+                               version_info::GetMajorVersionNumberAsInt() - 1);
     autocomplete_history_manager()->Init(
         WebDataServiceFactory::GetAutofillWebDataForProfile(
             current_profile(), ServiceAccessType::EXPLICIT_ACCESS),
@@ -278,11 +279,11 @@
   // finished, yet.
   WaitForPrefValue(pref_service(),
                    prefs::kAutocompleteLastVersionRetentionPolicy,
-                   base::Value(CHROME_VERSION_MAJOR));
+                   base::Value(version_info::GetMajorVersionNumberAsInt()));
 
   int saved_version = pref_service()->GetInteger(
       prefs::kAutocompleteLastVersionRetentionPolicy);
-  EXPECT_EQ(CHROME_VERSION_MAJOR, saved_version);
+  EXPECT_EQ(version_info::GetMajorVersionNumberAsInt(), saved_version);
 }
 
 // Tests that the retention policy cleanup removes an expired entry.
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index f1f6057..86d57f56 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -1770,9 +1770,6 @@
       public testing::WithParamInterface<bool> {
  public:
   void SetUp() override {
-    profile_.GetPrefs()->SetInteger(
-        prefs::kCookieControlsMode,
-        static_cast<int>(content_settings::CookieControlsMode::kLimited));
     profile_.GetPrefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled,
                                     true);
 
diff --git a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
index cb30a51..ddd526b 100644
--- a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
+++ b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
@@ -289,8 +289,6 @@
                           CookieControlsMode::kIncognitoOnly),
         CookieSettingPair(ThirdPartyCookieBlockingSetting::INCOGNITO_ONLY,
                           CookieControlsMode::kOff),
-        CookieSettingPair(ThirdPartyCookieBlockingSetting::INCOGNITO_ONLY,
-                          CookieControlsMode::kLimited),
         CookieSettingPair(ThirdPartyCookieBlockingSetting::BLOCK_THIRD_PARTY,
                           CookieControlsMode::kBlockThirdParty)));
 
diff --git a/chrome/browser/contextual_cueing/contextual_cueing_helper.cc b/chrome/browser/contextual_cueing/contextual_cueing_helper.cc
index 280c190..0f950269 100644
--- a/chrome/browser/contextual_cueing/contextual_cueing_helper.cc
+++ b/chrome/browser/contextual_cueing/contextual_cueing_helper.cc
@@ -102,18 +102,27 @@
   return browser->browser_window_features()->glic_nudge_controller();
 }
 
-void ContextualCueingHelper::DidStartNavigation(
+void ContextualCueingHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  // Ignore subframe navigations and reloads.
-  if (!navigation_handle->IsInMainFrame()) {
+  // Ignore sub-frame and uncommitted navigations.
+  if (!navigation_handle->IsInPrimaryMainFrame()) {
     return;
   }
+  if (!navigation_handle->HasCommitted()) {
+    return;
+  }
+
+  // Ignore reloads.
   if (PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
                                ui::PAGE_TRANSITION_RELOAD)) {
     return;
   }
 
-  // TODO: b/412468816 - See what we should do about fragments.
+  // Ignore fragment changes.
+  if (navigation_handle->GetPreviousPrimaryMainFrameURL().GetWithoutRef() ==
+      navigation_handle->GetURL().GetWithoutRef()) {
+    return;
+  }
 
   // Clear zero state suggestions if needed.
   if (base::FeatureList::IsEnabled(kGlicZeroStateSuggestions) &&
@@ -123,6 +132,10 @@
         web_contents()->GetPrimaryPage());
   }
 
+  if (!base::FeatureList::IsEnabled(kContextualCueing)) {
+    return;
+  }
+
   // Make sure we always clear the nudge label anyway despite operating on
   // pages.
   auto* glic_nudge_controller = GetGlicNudgeController();
@@ -131,28 +144,12 @@
         web_contents(), std::string(),
         tabs::GlicNudgeActivity::kNudgeIgnoredNavigation, base::DoNothing());
   }
-}
-
-void ContextualCueingHelper::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (!base::FeatureList::IsEnabled(kContextualCueing)) {
-    return;
-  }
-
-  // Ignore sub-frame navigations.
-  if (!navigation_handle->IsInMainFrame()) {
-    return;
-  }
 
   // Do not report page loads for these types of navigations.
-  if (navigation_handle->IsErrorPage() || !navigation_handle->HasCommitted() ||
+  if (navigation_handle->IsErrorPage() ||
       !navigation_handle->ShouldUpdateHistory()) {
     return;
   }
-  if (PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
-                               ui::PAGE_TRANSITION_RELOAD)) {
-    return;
-  }
 
   // We have already initiated nudging sequence for the page. Do not report page
   // load.
diff --git a/chrome/browser/contextual_cueing/contextual_cueing_helper.h b/chrome/browser/contextual_cueing/contextual_cueing_helper.h
index 99e144a..274feb3 100644
--- a/chrome/browser/contextual_cueing/contextual_cueing_helper.h
+++ b/chrome/browser/contextual_cueing/contextual_cueing_helper.h
@@ -37,8 +37,6 @@
   ~ContextualCueingHelper() override;
 
   // content::WebContentsObserver:
-  void DidStartNavigation(
-      content::NavigationHandle* navigation_handle) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
   void PrimaryMainDocumentElementAvailable() override;
diff --git a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.cc b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.cc
index 684de00..9ef6e911 100644
--- a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.cc
+++ b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.cc
@@ -14,12 +14,45 @@
 #include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
 #include "components/optimization_guide/core/optimization_guide_common.mojom.h"
 #include "components/optimization_guide/core/optimization_guide_logger.h"
+#include "components/optimization_guide/core/optimization_guide_permissions_util.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/proto/contextual_cueing_metadata.pb.h"
 #include "components/optimization_guide/proto/features/zero_state_suggestions.pb.h"
 #include "components/optimization_guide/proto/hints.pb.h"
 #include "content/public/browser/web_contents.h"
 
+namespace {
+
+// Parse the given metadata and return a std::pair containing:
+// 1. bool: true if eligible for contextual suggestions.
+// 2. std::vector<std::string>: suggestions in the metadata, if present.
+std::pair<bool, std::vector<std::string>> ParseOptimizationMetadata(
+    optimization_guide::OptimizationGuideDecision decision,
+    optimization_guide::OptimizationMetadata& metadata) {
+  if (decision != optimization_guide::OptimizationGuideDecision::kTrue) {
+    return std::make_pair(true, std::vector<std::string>());
+  }
+
+  auto suggestions_metadata = metadata.ParsedMetadata<
+      optimization_guide::proto::GlicZeroStateSuggestionsMetadata>();
+  if (!suggestions_metadata.has_value()) {
+    return std::make_pair(true, std::vector<std::string>());
+  }
+  if (!suggestions_metadata->contextual_suggestions_eligible()) {
+    return std::make_pair(false, std::vector<std::string>());
+  }
+  if (!suggestions_metadata->contextual_suggestions().empty()) {
+    return std::make_pair(
+        true, std::vector<std::string>(
+                  suggestions_metadata->contextual_suggestions().begin(),
+                  suggestions_metadata->contextual_suggestions().end()));
+  }
+
+  return std::make_pair(true, std::vector<std::string>());
+}
+
+}  // namespace
+
 namespace contextual_cueing {
 
 ZeroStateSuggestionsPageData::ZeroStateSuggestionsPageData(content::Page& page)
@@ -105,6 +138,47 @@
   RequestSuggestionsIfComplete();
 }
 
+void ZeroStateSuggestionsPageData::OnReceivedOptimizationMetadata(
+    const GURL& url,
+    const base::flat_map<
+        optimization_guide::proto::OptimizationType,
+        optimization_guide::OptimizationGuideDecisionWithMetadata>& decisions) {
+  optimization_metadata_done_ = true;
+  auto it =
+      decisions.find(optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS);
+  if (it == decisions.end()) {
+    // If not found, treat it as no metadata.
+    optimization_decision_ =
+        optimization_guide::OptimizationGuideDecision::kFalse;
+  } else {
+    optimization_metadata_ = it->second.metadata;
+    optimization_decision_ = it->second.decision;
+  }
+
+  ProcessSuggestionsIfComplete();
+}
+
+bool ZeroStateSuggestionsPageData::
+    ReturnSuggestionsFromOptimizationMetadataIfPossible() {
+  if (!optimization_metadata_done_) {
+    return false;
+  }
+
+  std::pair<bool, std::vector<std::string>> pair =
+      ParseOptimizationMetadata(optimization_decision_, optimization_metadata_);
+  if (!pair.first) {
+    suggestions_callbacks_.Notify(std::nullopt);
+    cached_suggestions_ = std::make_optional(std::vector<std::string>({}));
+    return true;
+  }
+  if (!pair.second.empty()) {
+    suggestions_callbacks_.Notify(pair.second);
+    cached_suggestions_ = pair.second;
+    return true;
+  }
+  return false;
+}
+
 void ZeroStateSuggestionsPageData::RequestSuggestionsIfComplete() {
   bool work_done = inner_text_done_ && annotated_page_content_done_;
   bool has_page_context = inner_text_result_ || annotated_page_content_;
@@ -121,27 +195,21 @@
 
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(&(page().GetMainDocument()));
-  optimization_guide::OptimizationMetadata metadata;
-  auto decision = optimization_guide_keyed_service_->CanApplyOptimization(
-      web_contents->GetLastCommittedURL(),
-      optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS, &metadata);
-  auto suggestions_metadata = metadata.ParsedMetadata<
-      optimization_guide::proto::GlicZeroStateSuggestionsMetadata>();
-  if (decision == optimization_guide::OptimizationGuideDecision::kTrue &&
-      suggestions_metadata &&
-      !suggestions_metadata->contextual_suggestions_eligible()) {
-    suggestions_callbacks_.Notify(std::nullopt);
-    cached_suggestions_ = std::make_optional(std::vector<std::string>({}));
-    return;
-  }
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  bool can_request_metadata =
+      optimization_guide::IsUserPermittedToFetchFromRemoteOptimizationGuide(
+          profile->IsOffTheRecord(), profile->GetPrefs());
 
-  if (suggestions_metadata &&
-      !suggestions_metadata->contextual_suggestions().empty()) {
-    std::vector<std::string> suggestions(
-        suggestions_metadata->contextual_suggestions().begin(),
-        suggestions_metadata->contextual_suggestions().end());
-    suggestions_callbacks_.Notify(suggestions);
-    cached_suggestions_ = suggestions;
+  if (!optimization_metadata_done_ && can_request_metadata) {
+    optimization_decision_ =
+        optimization_guide_keyed_service_->CanApplyOptimization(
+            web_contents->GetLastCommittedURL(),
+            optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS,
+            &optimization_metadata_);
+    optimization_metadata_done_ = true;
+  }
+  if (ReturnSuggestionsFromOptimizationMetadataIfPossible()) {
     return;
   }
 
@@ -151,6 +219,18 @@
     return;
   }
 
+  if (!optimization_metadata_done_ && !can_request_metadata) {
+    optimization_guide_keyed_service_->CanApplyOptimizationOnDemand(
+        {content::WebContents::FromRenderFrameHost(&(page().GetMainDocument()))
+             ->GetLastCommittedURL()},
+        {optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS},
+        optimization_guide::proto::RequestContext::
+            CONTEXT_GLIC_ZERO_STATE_SUGGESTIONS,
+        base::BindRepeating(
+            &ZeroStateSuggestionsPageData::OnReceivedOptimizationMetadata,
+            weak_ptr_factory_.GetWeakPtr()));
+  }
+
   optimization_guide::proto::PageContext* page_context =
       suggestions_request_->mutable_page_context();
   const GURL& page_url = web_contents->GetLastCommittedURL();
@@ -172,29 +252,33 @@
       *suggestions_request_,
       /*execution_timeout=*/std::nullopt,
       base::BindOnce(&ZeroStateSuggestionsPageData::OnModelExecutionResponse,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     suggestions_request_->is_fre()));
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ZeroStateSuggestionsPageData::OnModelExecutionResponse(
-    bool is_fre,
     optimization_guide::OptimizationGuideModelExecutionResult result,
     std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry) {
   // Clear out suggestions request as it's been fulfilled.
   suggestions_request_ = std::nullopt;
+  mes_suggestions_result_ = std::make_unique<
+      optimization_guide::OptimizationGuideModelExecutionResult>(
+      std::move(result));
+  mes_suggestions_done_ = true;
 
   base::TimeDelta suggestions_duration = base::TimeTicks::Now() - begin_time_;
-  if (!result.response.has_value()) {
+  if (!mes_suggestions_result_->response.has_value()) {
     OPTIMIZATION_GUIDE_LOG(
         optimization_guide_common::mojom::LogSource::MODEL_EXECUTION,
         optimization_guide_keyed_service_->GetOptimizationGuideLogger(),
-        base::StringPrintf("ZeroStateSuggestionsPageData: Failed to get "
-                           "suggestions after %ld ms. Error: %d",
-                           suggestions_duration.InMilliseconds(),
-                           static_cast<int>(result.response.error().error())));
+        base::StringPrintf(
+            "ZeroStateSuggestionsPageData: Failed to get "
+            "suggestions after %ld ms. Error: %d",
+            suggestions_duration.InMilliseconds(),
+            static_cast<int>(
+                mes_suggestions_result_->response.error().error())));
     suggestions_callbacks_.Notify(std::nullopt);
 
-    if (!result.response.error().transient()) {
+    if (!mes_suggestions_result_->response.error().transient()) {
       // Cache empty suggestions if error is not transient.
       cached_suggestions_ = std::make_optional(std::vector<std::string>({}));
     }
@@ -209,10 +293,24 @@
                          "suggestions after %ld ms.",
                          suggestions_duration.InMilliseconds()));
 
+  ProcessSuggestionsIfComplete();
+}
+
+void ZeroStateSuggestionsPageData::ProcessSuggestionsIfComplete() {
+  // Do not wait for model execution service if optimization metadata has
+  // enough information.
+  if (ReturnSuggestionsFromOptimizationMetadataIfPossible()) {
+    return;
+  }
+
+  if (!optimization_metadata_done_ || !mes_suggestions_done_) {
+    return;
+  }
+
   std::optional<optimization_guide::proto::ZeroStateSuggestionsResponse>
       response = optimization_guide::ParsedAnyMetadata<
           optimization_guide::proto::ZeroStateSuggestionsResponse>(
-          result.response.value());
+          mes_suggestions_result_->response.value());
   if (!response) {
     suggestions_callbacks_.Notify(std::nullopt);
     // Treat this as a transient error that server returned bad data
diff --git a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.h b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.h
index 37ceade..e021f01 100644
--- a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.h
+++ b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data.h
@@ -12,7 +12,9 @@
 #include "base/callback_list.h"
 #include "base/time/time.h"
 #include "components/optimization_guide/content/browser/page_content_proto_provider.h"
+#include "components/optimization_guide/core/optimization_guide_decision.h"
 #include "components/optimization_guide/core/optimization_guide_model_executor.h"
+#include "components/optimization_guide/core/optimization_metadata.h"
 #include "content/public/browser/page_user_data.h"
 
 class OptimizationGuideKeyedService;
@@ -62,22 +64,50 @@
   void OnReceivedAnnotatedPageContent(
       std::optional<optimization_guide::AIPageContentResult> content);
 
+  // Called when on-demand metadata is received.
+  void OnReceivedOptimizationMetadata(
+      const GURL& url,
+      const base::flat_map<
+          optimization_guide::proto::OptimizationType,
+          optimization_guide::OptimizationGuideDecisionWithMetadata>&
+          decisions);
+
   // Send out suggestions request, if all necessary fetches are complete.
   void RequestSuggestionsIfComplete();
 
+  // Return suggestions result by invoking `suggestions_callbacks_`, if all
+  // necessary fetches are complete.
+  void ProcessSuggestionsIfComplete();
+
+  // If `optimization_metadata_` contains everything necessary to determine a
+  // suggestions result, run `suggestions_callbacks_` to return those
+  // suggestions. This method itself also returns true if suggestions are sent
+  // via the callbacks as a result of execution.
+  bool ReturnSuggestionsFromOptimizationMetadataIfPossible();
+
   // Called when a zero state suggestions server response is received.
   void OnModelExecutionResponse(
-      bool is_fre,
       optimization_guide::OptimizationGuideModelExecutionResult result,
       std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry);
 
-  // Tracks the status of inner text and annotated page content fetches.
+  // Tracks the status of inner text and annotated page content fetches, which
+  // are needed in `RequestSuggestionsIfComplete()`.
   bool inner_text_done_ = false;
   std::unique_ptr<content_extraction::InnerTextResult> inner_text_result_;
   bool annotated_page_content_done_ = false;
   std::optional<optimization_guide::AIPageContentResult>
       annotated_page_content_;
 
+  // Tracks the status of fetches for on-demand optimization metadata, and
+  // suggestions from model execution service, which are needed for
+  // `ProcessSuggestionsIfComplete()`.
+  bool optimization_metadata_done_ = false;
+  optimization_guide::OptimizationGuideDecision optimization_decision_;
+  optimization_guide::OptimizationMetadata optimization_metadata_;
+  bool mes_suggestions_done_ = false;
+  std::unique_ptr<optimization_guide::OptimizationGuideModelExecutionResult>
+      mes_suggestions_result_;
+
   // Tracks the state for a request.
   base::TimeTicks begin_time_;
   std::optional<optimization_guide::proto::ZeroStateSuggestionsRequest>
diff --git a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data_browsertest.cc b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data_browsertest.cc
index 53b6732..1f6ade4 100644
--- a/chrome/browser/contextual_cueing/zero_state_suggestions_page_data_browsertest.cc
+++ b/chrome/browser/contextual_cueing/zero_state_suggestions_page_data_browsertest.cc
@@ -14,7 +14,9 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_model_executor.h"
+#include "components/optimization_guide/core/optimization_guide_switches.h"
 #include "components/optimization_guide/proto/contextual_cueing_metadata.pb.h"
 #include "components/optimization_guide/proto/features/zero_state_suggestions.pb.h"
 #include "content/public/test/browser_test.h"
@@ -24,6 +26,7 @@
 
 using ::testing::_;
 using ::testing::An;
+using ::testing::ElementsAre;
 using ::testing::Eq;
 using ::testing::Invoke;
 using ::testing::Return;
@@ -100,10 +103,17 @@
     }
     scoped_feature_list_.InitWithFeaturesAndParameters(
         {{contextual_cueing::kContextualCueing, {}},
-         {contextual_cueing::kGlicZeroStateSuggestions, zss_params}},
+         {contextual_cueing::kGlicZeroStateSuggestions, zss_params},
+         {optimization_guide::features::kRemoteOptimizationGuideFetching, {}}},
         /*disabled_features=*/{});
   }
 
+  void DisableOptimizationPermissionCheck() {
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        optimization_guide::switches::
+            kDisableCheckingUserPermissionsForTesting);
+  }
+
   void SetUpBrowserContextKeyedServices(
       content::BrowserContext* browser_context) override {
     mock_optimization_guide_keyed_service_ =
@@ -128,6 +138,41 @@
     return *mock_optimization_guide_keyed_service_;
   }
 
+  void SetUpOnDemandHints(bool allow_contextual,
+                          const std::vector<std::string>& suggestions) {
+    EXPECT_CALL(
+        mock_optimization_guide_keyed_service(),
+        CanApplyOptimizationOnDemand(
+            _,
+            ElementsAre(optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS),
+            optimization_guide::proto::RequestContext::
+                CONTEXT_GLIC_ZERO_STATE_SUGGESTIONS,
+            _, _))
+        .WillOnce(WithArgs<3>(
+            [=](optimization_guide::
+                    OnDemandOptimizationGuideDecisionRepeatingCallback
+                        callback) {
+              optimization_guide::proto::GlicZeroStateSuggestionsMetadata
+                  metadata;
+              metadata.set_contextual_suggestions_eligible(allow_contextual);
+              *metadata.mutable_contextual_suggestions() = {suggestions.begin(),
+                                                            suggestions.end()};
+
+              optimization_guide::OptimizationMetadata og_metadata;
+              og_metadata.SetAnyMetadataForTesting(metadata);
+
+              optimization_guide::OptimizationGuideDecisionWithMetadata
+                  decision_with_metadata;
+              decision_with_metadata.decision =
+                  optimization_guide::OptimizationGuideDecision::kTrue;
+              decision_with_metadata.metadata = og_metadata;
+              callback.Run(
+                  GURL(),
+                  {{optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS,
+                    decision_with_metadata}});
+            }));
+  }
+
   void SetUpHints(bool allow_contextual,
                   const std::vector<std::string>& suggestions) {
     EXPECT_CALL(mock_optimization_guide_keyed_service(),
@@ -217,6 +262,19 @@
             }));
   }
 
+  void SetUpEmptyModelExecutionResult() {
+    ON_CALL(mock_optimization_guide_keyed_service(), ExecuteModel(_, _, _, _))
+        .WillByDefault(WithArgs<3>(
+            [&](optimization_guide::
+                    OptimizationGuideModelExecutionResultCallback callback) {
+              optimization_guide::proto::Any any_result;
+              std::move(callback).Run(
+                  optimization_guide::OptimizationGuideModelExecutionResult(
+                      any_result, nullptr),
+                  nullptr);
+            }));
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   raw_ptr<testing::NiceMock<MockOGKS>> mock_optimization_guide_keyed_service_;
@@ -233,8 +291,12 @@
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest, BasicFlow) {
   base::HistogramTester histogram_tester;
 
+  DisableOptimizationPermissionCheck();
   SetUpSuccessfulModelExecution();
   SetUpHints(/*allow_contextual=*/true, /*suggestions=*/{});
+  EXPECT_CALL(mock_optimization_guide_keyed_service(),
+              CanApplyOptimizationOnDemand)
+      .Times(0);
 
   ASSERT_TRUE(embedded_test_server()->Start());
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
@@ -260,6 +322,7 @@
                        HoldsOntoSuccessiveRequests) {
   base::HistogramTester histogram_tester;
 
+  DisableOptimizationPermissionCheck();
   EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel(_, _, _, _))
       .WillOnce(Invoke(&mock_optimization_guide_keyed_service(),
                        &MockOGKS::CaptureExecutionCallback));
@@ -314,6 +377,7 @@
                        CreateDataDoesNotFetchWithoutExplicitCall) {
   base::HistogramTester histogram_tester;
 
+  DisableOptimizationPermissionCheck();
   EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel).Times(0);
 
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -334,8 +398,12 @@
 
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
                        UseHintsSuggestions) {
+  DisableOptimizationPermissionCheck();
   SetUpHints(/*allow_contextual=*/true,
              /*suggestions=*/{"hints 1", "hints 2", "hints 3"});
+  EXPECT_CALL(mock_optimization_guide_keyed_service(),
+              CanApplyOptimizationOnDemand)
+      .Times(0);
   // MES not to be called if hints has the suggestions.
   EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel).Times(0);
 
@@ -359,7 +427,11 @@
 
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
                        ContextualSuggestionsNotAllowed) {
+  DisableOptimizationPermissionCheck();
   SetUpHints(/*allow_contextual=*/false, /*suggestions=*/{});
+  EXPECT_CALL(mock_optimization_guide_keyed_service(),
+              CanApplyOptimizationOnDemand)
+      .Times(0);
   // MES not to be called if not eligible for contextual suggestions.
   EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel).Times(0);
 
@@ -380,6 +452,7 @@
 
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
                        NoResultFromHints) {
+  DisableOptimizationPermissionCheck();
   // Assumes page is eligible for contextual suggestions without hints result.
   EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel).Times(0);
   SetUpHintsNoResult();
@@ -404,6 +477,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest, CacheBehavior) {
+  DisableOptimizationPermissionCheck();
   ASSERT_TRUE(embedded_test_server()->Start());
 
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
@@ -503,6 +577,7 @@
 
 IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
                        CacheBehaviorTransientError) {
+  DisableOptimizationPermissionCheck();
   ASSERT_TRUE(embedded_test_server()->Start());
 
   auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
@@ -558,4 +633,85 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest, NonMSBBFlow) {
+  base::HistogramTester histogram_tester;
+
+  SetUpEmptyModelExecutionResult();
+  SetUpOnDemandHints(/*allow_contextual=*/true, /*suggestions=*/{
+                         "on demand 1", "on demand 2", "on demand 3"});
+
+  ASSERT_TRUE(embedded_test_server()->Start());
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL("/optimization_guide/zss_page.html")));
+
+  base::test::TestFuture<std::optional<std::vector<std::string>>> future;
+
+  auto* page_data = ZeroStateSuggestionsPageData::GetOrCreateForPage(
+      web_contents->GetPrimaryPage());
+  page_data->FetchSuggestions(/*is_fre=*/false, future.GetCallback());
+  ASSERT_TRUE(future.Wait());
+  EXPECT_EQ(3u, future.Get().value().size());
+  EXPECT_EQ("on demand 1", future.Get().value()[0]);
+  EXPECT_EQ("on demand 2", future.Get().value()[1]);
+  EXPECT_EQ("on demand 3", future.Get().value()[2]);
+  histogram_tester.ExpectUniqueSample(
+      "ContextualCueing.ZeroStateSuggestions.ContextExtractionDone", true, 1);
+}
+
+IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
+                       NonMSBBFlowContextualNotAllowed) {
+  base::HistogramTester histogram_tester;
+
+  SetUpEmptyModelExecutionResult();
+  SetUpOnDemandHints(/*allow_contextual=*/false, /*suggestions=*/{});
+
+  ASSERT_TRUE(embedded_test_server()->Start());
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL("/optimization_guide/zss_page.html")));
+
+  base::test::TestFuture<std::optional<std::vector<std::string>>> future;
+
+  auto* page_data = ZeroStateSuggestionsPageData::GetOrCreateForPage(
+      web_contents->GetPrimaryPage());
+  page_data->FetchSuggestions(/*is_fre=*/false, future.GetCallback());
+  ASSERT_TRUE(future.Wait());
+  EXPECT_EQ(std::nullopt, future.Get());
+}
+
+IN_PROC_BROWSER_TEST_P(ZeroStateSuggestionsPageDataBrowserTest,
+                       OnlyRequestsHintsOnDemandAfterFetchCall) {
+  base::HistogramTester histogram_tester;
+
+  ASSERT_TRUE(embedded_test_server()->Start());
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL("/optimization_guide/zss_page.html")));
+
+  // Make sure on demand fetch does not start when creating page data.
+  EXPECT_CALL(mock_optimization_guide_keyed_service(),
+              CanApplyOptimizationOnDemand)
+      .Times(0);
+  auto* page_data = ZeroStateSuggestionsPageData::GetOrCreateForPage(
+      web_contents->GetPrimaryPage());
+  optimization_guide::RetryForHistogramUntilCountReached(
+      &histogram_tester,
+      "ContextualCueing.ZeroStateSuggestions.ContextExtractionDone", 1);
+
+  testing::Mock::VerifyAndClearExpectations(
+      &mock_optimization_guide_keyed_service());
+
+  // Make sure on demand fetch starts after FetchSuggestions is invoked.
+  SetUpEmptyModelExecutionResult();
+  base::test::TestFuture<std::optional<std::vector<std::string>>> future;
+  SetUpOnDemandHints(/*allow_contextual=*/false, /*suggestions=*/{});
+  page_data->FetchSuggestions(/*is_fre=*/false, future.GetCallback());
+  ASSERT_TRUE(future.Wait());
+  EXPECT_EQ(std::nullopt, future.Get());
+}
+
 }  // namespace contextual_cueing
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateFactory.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateFactory.java
index addf411..6d3b7a7c 100644
--- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateFactory.java
+++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateFactory.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.browser.data_sharing;
 
-import androidx.annotation.Nullable;
+import static org.chromium.build.NullUtil.assumeNonNull;
 
 import org.chromium.base.ResettersForTesting;
 import org.chromium.base.ThreadUtils;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.collaboration.messaging.MessagingBackendServiceFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileKeyedMap;
@@ -17,8 +19,9 @@
 import org.chromium.components.tab_group_sync.TabGroupSyncService;
 
 /** Creates/provides {@link InstantMessageDelegateImpl} by {@link Profile}. */
+@NullMarked
 public final class InstantMessageDelegateFactory {
-    private static ProfileKeyedMap<InstantMessageDelegateImpl> sProfileMap;
+    private static @Nullable ProfileKeyedMap<InstantMessageDelegateImpl> sProfileMap;
     private static @Nullable InstantMessageDelegateImpl sInstantMessageDelegateImplForTesting;
 
     // No instantiation.
@@ -49,6 +52,7 @@
                 MessagingBackendServiceFactory.getForProfile(profile);
         DataSharingService dataSharingService = DataSharingServiceFactory.getForProfile(profile);
         TabGroupSyncService tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(profile);
+        assumeNonNull(tabGroupSyncService);
         return new InstantMessageDelegateImpl(
                 messagingBackendService, dataSharingService, tabGroupSyncService);
     }
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn
index 5406d49..7eae2de7 100644
--- a/chrome/browser/devtools/BUILD.gn
+++ b/chrome/browser/devtools/BUILD.gn
@@ -320,6 +320,7 @@
   if (!is_android) {
     deps += [
       "//chrome/app:command_ids",
+      "//chrome/browser/first_party_sets",
       "//chrome/browser/ui/media_router",
       "//components/custom_handlers",
       "//components/media_router/browser",
diff --git a/chrome/browser/download/insecure_download_blocking.cc b/chrome/browser/download/insecure_download_blocking.cc
index 6d8b743..ee21f83 100644
--- a/chrome/browser/download/insecure_download_blocking.cc
+++ b/chrome/browser/download/insecure_download_blocking.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/download/public/common/download_stats.h"
@@ -405,6 +406,12 @@
     return;
   }
 
+  // TODO(crbug.com/399076164): debug only. Used to investigate why insecure
+  // downloads can be initiated from the NTP.
+  if (rfh->GetLastCommittedOrigin().host() == chrome::kChromeUINewTabPageHost) {
+    base::debug::DumpWithoutCrashing();
+  }
+
   rfh->AddMessageToConsole(
       blink::mojom::ConsoleMessageLevel::kError,
       base::StringPrintf(
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index a77db72..55b14fc 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -788,7 +788,11 @@
       }
 #endif
 
-      actions->push_back(DownloadCommands::SHOW_IN_FOLDER);
+      // Do not include the Show in folder action for downloads we can't show in
+      // the folder.
+      if (item_->GetDownloadItem() != nullptr) {
+        actions->push_back(DownloadCommands::SHOW_IN_FOLDER);
+      }
       // We disable this functionality for now as the usage is very low, the
       // feature gets re-written at this time and there is currently no secure
       // way to determine the caller on the Ash side as the dialog is still
diff --git a/chrome/browser/educational_tip/BUILD.gn b/chrome/browser/educational_tip/BUILD.gn
index ece47d1..4e027786 100644
--- a/chrome/browser/educational_tip/BUILD.gn
+++ b/chrome/browser/educational_tip/BUILD.gn
@@ -34,6 +34,7 @@
     "//chrome/browser/magic_stack/android:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/segmentation_platform:factory_java",
+    "//chrome/browser/signin/services/android:java",
     "//chrome/browser/tab_group_sync:factory_java",
     "//chrome/browser/tab_group_sync:features_java",
     "//chrome/browser/tab_ui/android:java",
@@ -89,6 +90,7 @@
     "junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleMediatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewBinderUnitTest.java",
     "junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewUnitTest.java",
+    "junit/src/org/chromium/chrome/browser/educational_tip/HistorySyncPromoCoordinatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/educational_tip/QuickDeletePromoCoordinatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/educational_tip/TabGroupPromoCoordinatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/educational_tip/TabGroupSyncPromoCoordinatorUnitTest.java",
@@ -100,11 +102,13 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//chrome/android/javatests:common_unit_test_deps_java",
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/hub:java",
     "//chrome/browser/magic_stack/android:java",
     "//chrome/browser/profiles/android:java",
+    "//chrome/browser/signin/services/android:java",
     "//chrome/browser/tab_group_sync:factory_java",
     "//chrome/browser/tab_group_sync:features_java",
     "//chrome/browser/tab_ui/android:java",
diff --git a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/cards/HistorySyncPromoCoordinator.java b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/cards/HistorySyncPromoCoordinator.java
index f1c4313..a24460bcb 100644
--- a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/cards/HistorySyncPromoCoordinator.java
+++ b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/cards/HistorySyncPromoCoordinator.java
@@ -7,23 +7,33 @@
 import androidx.annotation.DrawableRes;
 
 import org.chromium.base.CallbackController;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.educational_tip.EducationTipModuleActionDelegate;
 import org.chromium.chrome.browser.educational_tip.EducationalTipCardProvider;
 import org.chromium.chrome.browser.educational_tip.R;
+import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.components.signin.SigninFeatureMap;
 import org.chromium.components.signin.SigninFeatures;
+import org.chromium.components.signin.identitymanager.ConsentLevel;
+import org.chromium.components.signin.identitymanager.IdentityManager;
+import org.chromium.components.signin.identitymanager.PrimaryAccountChangeEvent;
 
 /**
  * A coordinator that is responsible for displaying the history sync education tip that is show on
  * the NTP in the magic stack if the user is eligible.
  */
-public class HistorySyncPromoCoordinator implements EducationalTipCardProvider {
+@NullMarked
+public class HistorySyncPromoCoordinator
+        implements EducationalTipCardProvider, IdentityManager.Observer {
 
     private static final String HISTORY_OPT_IN_EDUCATIONAL_TIP_PARAM =
             "history_opt_in_educational_tip_param";
 
     private final EducationTipModuleActionDelegate mActionDelegate;
     private final Runnable mOnClickedRunnable;
+    private final Runnable mRemoveModuleRunnable;
+    private final @Nullable IdentityManager mIdentityManager;
 
     public HistorySyncPromoCoordinator(
             Runnable onModuleClickedCallback,
@@ -32,12 +42,29 @@
             Runnable removeModuleCallback) {
         mActionDelegate = actionDelegate;
 
+        mRemoveModuleRunnable =
+                callbackController.makeCancelable(
+                        () -> {
+                            removeModuleCallback.run();
+                        });
+
         mOnClickedRunnable =
                 callbackController.makeCancelable(
                         () -> {
+                            // removeModuleCallback is passed as a callable to ChromeTabbedActivity
+                            // so that the promo is dismssed only after the history sync activity is
+                            // complete. Otherwise the promo will be dismissed too early.
                             mActionDelegate.showHistorySyncOptIn(removeModuleCallback);
                             onModuleClickedCallback.run();
                         });
+
+        assert mActionDelegate.getProfileSupplier().hasValue();
+        mIdentityManager =
+                IdentityServicesProvider.get()
+                        .getIdentityManager(mActionDelegate.getProfileSupplier().get());
+
+        assert mIdentityManager != null;
+        mIdentityManager.addObserver(this);
     }
 
     @Override
@@ -89,4 +116,19 @@
     public void onCardClicked() {
         mOnClickedRunnable.run();
     }
+
+    /** Implements {@link IdentityManager.Observer}. */
+    @Override
+    public void onPrimaryAccountChanged(PrimaryAccountChangeEvent eventDetails) {
+        if (eventDetails.getEventTypeFor(ConsentLevel.SIGNIN)
+                == PrimaryAccountChangeEvent.Type.CLEARED) {
+            mRemoveModuleRunnable.run();
+        }
+    }
+
+    @Override
+    public void destroy() {
+        assert mIdentityManager != null;
+        mIdentityManager.removeObserver(this);
+    }
 }
diff --git a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleMediatorUnitTest.java b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleMediatorUnitTest.java
index 4cfe0d3..9d7d69b 100644
--- a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleMediatorUnitTest.java
+++ b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleMediatorUnitTest.java
@@ -25,6 +25,7 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Features.EnableFeatures;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
@@ -32,10 +33,12 @@
 import org.chromium.chrome.browser.magic_stack.ModuleDelegate;
 import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.ui.default_browser_promo.DefaultBrowserPromoUtils;
 import org.chromium.chrome.browser.ui.default_browser_promo.DefaultBrowserPromoUtils.DefaultBrowserPromoTriggerStateListener;
 import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.feature_engagement.Tracker;
+import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.shadows.ShadowAppCompatResources;
 
@@ -53,11 +56,15 @@
     @Mock private Profile mProfile;
     @Mock private Tracker mTracker;
     @Mock private DefaultBrowserPromoUtils mMockDefaultBrowserPromoUtils;
+    @Mock private IdentityServicesProvider mIdentityServicesProvider;
+    @Mock private IdentityManager mIdentityManager;
 
     @Captor
     private ArgumentCaptor<DefaultBrowserPromoTriggerStateListener>
             mDefaultBrowserPromoTriggerStateListener;
 
+    ObservableSupplierImpl<Profile> mProfileSupplier;
+
     private Context mContext;
     private @ModuleType int mDefaultModuleTypeForTesting;
     private EducationalTipModuleMediator mEducationalTipModuleMediator;
@@ -66,11 +73,17 @@
     public void setUp() {
         mContext = ApplicationProvider.getApplicationContext();
         when(mActionDelegate.getContext()).thenReturn(mContext);
-        when(mProfile.getOriginalProfile()).thenReturn(mProfile);
         mDefaultModuleTypeForTesting = ModuleType.DEFAULT_BROWSER_PROMO;
         TrackerFactory.setTrackerForTests(mTracker);
         DefaultBrowserPromoUtils.setInstanceForTesting(mMockDefaultBrowserPromoUtils);
 
+        // Setup for History sync promo
+        mProfileSupplier = new ObservableSupplierImpl<>();
+        mProfileSupplier.set(mProfile);
+        when(mActionDelegate.getProfileSupplier()).thenReturn(mProfileSupplier);
+        IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
+        when(mIdentityServicesProvider.getIdentityManager(mProfile)).thenReturn(mIdentityManager);
+
         mEducationalTipModuleMediator =
                 new EducationalTipModuleMediator(
                         mDefaultModuleTypeForTesting,
diff --git a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/HistorySyncPromoCoordinatorUnitTest.java b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/HistorySyncPromoCoordinatorUnitTest.java
new file mode 100644
index 0000000..b23851d
--- /dev/null
+++ b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/HistorySyncPromoCoordinatorUnitTest.java
@@ -0,0 +1,67 @@
+// Copyright 2025 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.educational_tip;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import org.chromium.base.CallbackController;
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.educational_tip.cards.HistorySyncPromoCoordinator;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
+import org.chromium.components.signin.identitymanager.ConsentLevel;
+import org.chromium.components.signin.identitymanager.IdentityManager;
+import org.chromium.components.signin.identitymanager.PrimaryAccountChangeEvent;
+
+/** Test relating to {@link HistorySyncPromoCoordinator} */
+@RunWith(BaseRobolectricTestRunner.class)
+public class HistorySyncPromoCoordinatorUnitTest {
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock private Runnable mOnModuleClickedCallback;
+    @Mock private Runnable mRemoveModuleCallback;
+    @Mock private EducationTipModuleActionDelegate mActionDelegate;
+    @Mock private IdentityManager mIdentityManager;
+    @Mock private Profile mProfile;
+    @Mock private IdentityServicesProvider mIdentityServicesProvider;
+    ObservableSupplierImpl<Profile> mProfileSupplier;
+    private HistorySyncPromoCoordinator mHistorySyncPromoCoordinator;
+
+    @Before
+    public void setUp() {
+        mProfileSupplier = new ObservableSupplierImpl<>();
+        mProfileSupplier.set(mProfile);
+        IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
+        when(mActionDelegate.getProfileSupplier()).thenReturn(mProfileSupplier);
+        IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
+        when(mIdentityServicesProvider.getIdentityManager(mProfile)).thenReturn(mIdentityManager);
+        mHistorySyncPromoCoordinator =
+                new HistorySyncPromoCoordinator(
+                        mOnModuleClickedCallback,
+                        new CallbackController(),
+                        mActionDelegate,
+                        mRemoveModuleCallback);
+    }
+
+    @Test
+    @SmallTest
+    public void testCardRemovedOnSignout() {
+        mHistorySyncPromoCoordinator.onPrimaryAccountChanged(
+                new PrimaryAccountChangeEvent(
+                        PrimaryAccountChangeEvent.Type.CLEARED, ConsentLevel.SIGNIN));
+
+        verify(mRemoveModuleCallback).run();
+    }
+}
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 8609816..65860b7 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -175,6 +175,10 @@
     "chrome_extension_frame_host.h",
     "chrome_extension_registrar_delegate.cc",
     "chrome_extension_registrar_delegate.h",
+    "chrome_extension_system.cc",
+    "chrome_extension_system.h",
+    "chrome_extension_system_factory.cc",
+    "chrome_extension_system_factory.h",
     "chrome_extension_web_contents_observer.cc",
     "chrome_extension_web_contents_observer.h",
     "chrome_extensions_browser_api_provider.cc",
@@ -659,10 +663,6 @@
       "chrome_extension_function_details.h",
       "chrome_extension_host_delegate.cc",
       "chrome_extension_host_delegate.h",
-      "chrome_extension_system.cc",
-      "chrome_extension_system.h",
-      "chrome_extension_system_factory.cc",
-      "chrome_extension_system_factory.h",
       "chrome_extensions_browser_interface_binders.cc",
       "chrome_extensions_browser_interface_binders.h",
       "chrome_kiosk_delegate.h",
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index 3bcb13e..23df0b2 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -3274,24 +3274,9 @@
 }
 
 class DeveloperPrivateApiSupervisedUserUnitTest
-    : public DeveloperPrivateApiUnitTest,
-      public testing::WithParamInterface<bool> {
+    : public DeveloperPrivateApiUnitTest {
  public:
-  DeveloperPrivateApiSupervisedUserUnitTest() {
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-    if (extensions_permissions_for_supervised_users_on_desktop()) {
-      feature_list_.InitAndEnableFeature(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-
-    } else {
-      feature_list_.InitAndDisableFeature(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-    }
-#endif
-  }
-
+  DeveloperPrivateApiSupervisedUserUnitTest() = default;
   DeveloperPrivateApiSupervisedUserUnitTest(
       const DeveloperPrivateApiSupervisedUserUnitTest&) = delete;
   DeveloperPrivateApiSupervisedUserUnitTest& operator=(
@@ -3300,23 +3285,15 @@
   ~DeveloperPrivateApiSupervisedUserUnitTest() override = default;
 
   bool ProfileIsSupervised() const override { return true; }
-
-  bool extensions_permissions_for_supervised_users_on_desktop() const {
-    return GetParam();
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
 };
 
 // Tests trying to call loadUnpacked when the profile shouldn't be allowed to.
-TEST_P(DeveloperPrivateApiSupervisedUserUnitTest,
+TEST_F(DeveloperPrivateApiSupervisedUserUnitTest,
        LoadUnpackedFailsForSupervisedUsers) {
   std::unique_ptr<content::WebContents> web_contents(
       content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
   base::FilePath path = data_dir().AppendASCII("simple_with_popup");
 
-  if (extensions_permissions_for_supervised_users_on_desktop()) {
     EXPECT_TRUE(supervised_user::AreExtensionsPermissionsEnabled(profile()));
     auto function =
         base::MakeRefCounted<api::DeveloperPrivateLoadUnpackedFunction>();
@@ -3324,26 +3301,8 @@
     std::string error = api_test_utils::RunFunctionAndReturnError(
         function.get(), "[]", profile());
     EXPECT_THAT(error, testing::HasSubstr("Child account"));
-  } else {
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
-    EXPECT_TRUE(supervised_user::AreExtensionsPermissionsEnabled(profile()));
-    auto function =
-        base::MakeRefCounted<api::DeveloperPrivateLoadUnpackedFunction>();
-    function->SetRenderFrameHost(web_contents->GetPrimaryMainFrame());
-    std::string error = api_test_utils::RunFunctionAndReturnError(
-        function.get(), "[]", profile());
-    EXPECT_THAT(error, testing::HasSubstr("Child account"));
-#else
-    EXPECT_FALSE(supervised_user::AreExtensionsPermissionsEnabled(profile()));
-#endif
-  }
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    ExtensionsPermissionsForSupervisedUsersOnDesktopFeature,
-    DeveloperPrivateApiSupervisedUserUnitTest,
-    testing::Bool());
-
 // Test suite for cases where the user is in the  MV2 deprecation "warning"
 // experiment phase.
 class DeveloperPrivateApiWithMV2DeprecationWarningUnitTest
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_desktop.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_desktop.cc
index 252d216..72e902ff 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_desktop.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_desktop.cc
@@ -87,20 +87,9 @@
       info.dependent_extensions.push_back(std::move(dependent_extension));
     }
   }
-
-  DisableReasonSet disable_reasons =
-      extension_prefs_->GetDisableReasons(extension.id());
-  bool custodian_approval_required = disable_reasons.contains(
-      disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
-  bool permissions_increase =
-      disable_reasons.contains(disable_reason::DISABLE_PERMISSIONS_INCREASE);
-  info.disable_reasons.parent_disabled_permissions =
-      supervised_user::AreExtensionsPermissionsEnabled(profile) &&
-      !supervised_user::
-          IsSupervisedUserSkipParentApprovalToInstallExtensionsEnabled() &&
-      !profile->GetPrefs()->GetBoolean(
-          prefs::kSupervisedUserExtensionsMayRequestPermissions) &&
-      (custodian_approval_required || permissions_increase);
+  // TODO(crbug.com/413650880): Investigate if `parent_disabled_permissions`
+  // can be removed.
+  info.disable_reasons.parent_disabled_permissions = false;
 
   // Location.
   bool updates_from_web_store =
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index 828a45d..18f60bc 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -1433,27 +1433,10 @@
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
 
-// Whether parental controls apply to extensions.
-enum class ExtensionsParentalControlState : int { kEnabled = 0, kDisabled = 1 };
-
-// Whether the parental controls on Extensions are managed by the preference
-// `SkipParentApprovalToInstallExtensions`, which corresponds to the
-// "Allow to add extensions without asking permission" Family Link switch
-// or by the preference `kSupervisedUserExtensionsMayRequestPermissions`
-// which corresponds to the "Permissions for Sites, Apps and Extensions"
-// Family Link switch.
-enum class ExtensionManagementFamilyLinkSwitch : int {
-  kManagedByExtensionsSwitch = 0,
-  kManagedByPermissionsSwitch = 1
-};
-
 // Tests for supervised users (child accounts). Supervised users are not allowed
 // to install apps or extensions unless their parent approves.
 class ExtensionInfoGeneratorUnitTestSupervised
-    : public ExtensionInfoGeneratorUnitTest,
-      public testing::WithParamInterface<
-          std::tuple<ExtensionsParentalControlState,
-                     ExtensionManagementFamilyLinkSwitch>> {
+    : public ExtensionInfoGeneratorUnitTest {
  public:
   ExtensionInfoGeneratorUnitTestSupervised() = default;
   ~ExtensionInfoGeneratorUnitTestSupervised() override = default;
@@ -1471,70 +1454,17 @@
 
     // Set up custodians (parents) for the child.
     supervised_user_test_util::AddCustodians(profile());
-
-    // Set the pref to allow the child to request extension install.
-    supervised_user_test_util::
-        SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
-
   }
 
   void TearDown() override {
     ExtensionInfoGeneratorUnitTest::TearDown();
   }
-
-  bool ApplyParentalControlsOnExtensions() {
-    return std::get<0>(GetParam()) == ExtensionsParentalControlState::kEnabled;
-  }
-
-  ExtensionManagementFamilyLinkSwitch GetExtensionManagementFamilyLinkSwitch() {
-    return std::get<1>(GetParam());
-  }
 };
 
-// Tests that when an extension:
-// 1) is disabled pending permission updates and
-// 2) the parent has turned off the "Permissions for sites, apps and extensions"
-// toggle on Family Link and
-// 3) the extension parental controls are managed by the Family link
-// "Permissions for sites, apps and extensions" (legacy flow), instead of the
-// "Allow to add extensions without asking permission" Family Link switch (new
-// flow)" then supervised users will see a kite error icon with a tooltip.
-TEST_P(ExtensionInfoGeneratorUnitTestSupervised,
-       ParentDisabledPermissionsForSupervisedUsers) {
-  // Extension permissions for supervised users is already enabled on ChromeOS.
-  base::test::ScopedFeatureList feature_list;
-  std::vector<base::test::FeatureRef> enabled_features;
-  std::vector<base::test::FeatureRef> disabled_features;
-
-  if (ApplyParentalControlsOnExtensions()) {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    if (GetExtensionManagementFamilyLinkSwitch() ==
-        ExtensionManagementFamilyLinkSwitch::kManagedByExtensionsSwitch) {
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-  } else {
-    disabled_features.push_back(
-        supervised_user::
-            kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    disabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-  }
-  feature_list.InitWithFeatures(enabled_features, disabled_features);
-
+// Tests that when a supervised user is never blocked from
+// updating the permissions of an extension after a permissions' increase.
+TEST_F(ExtensionInfoGeneratorUnitTestSupervised,
+       AlwaysAllowPermissionUpdatesForSupervisedUsers) {
   ASSERT_TRUE(profile()->IsChild());
 
   std::unique_ptr<SupervisedUserExtensionsDelegate>
@@ -1544,33 +1474,22 @@
   base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
   base::FilePath path = base_path.AppendASCII("v1");
 
-  // When extension parental controls apply, on the default behaviour
-  // the extensions will be installed but disabled until custodian approvals are
-  // performed. When extension parental controls do not apply, the extensions
-  // will be installed and enabled.
-  InstallState install_state =
-      ApplyParentalControlsOnExtensions() ? INSTALL_WITHOUT_LOAD : INSTALL_NEW;
+  // The extensions will be installed but disabled until custodian approvals are
+  // performed.
+  InstallState install_state = INSTALL_WITHOUT_LOAD;
   const Extension* extension = PackAndInstallCRX(path, pem_path, install_state);
   ASSERT_TRUE(extension);
-  if (ApplyParentalControlsOnExtensions()) {
     EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
-  } else {
-    EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
-  }
 
   // Save the id, as |extension| will be destroyed during updating.
   ExtensionId extension_id = extension->id();
 
   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
-  if (ApplyParentalControlsOnExtensions()) {
     EXPECT_TRUE(prefs->HasDisableReason(
         extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
 
     // Simulate parent approval for the extension installation.
     supervised_user_extensions_delegate->AddExtensionApproval(*extension);
-  } else {
-    EXPECT_FALSE(prefs->IsExtensionDisabled(extension_id));
-  }
 
   // The extension should be enabled.
   EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
@@ -1585,52 +1504,20 @@
   // Due to a permission increase, prefs will contain escalation information.
   EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
 
-  // Simulate the parent disallowing the child from approving permission
-  // updates. If extensions parental controls don't apply, or the extensions
-  // are managed by the `SkipParentApprovalToInstallExtensions` preference
-  // then this has no effect.
+  // Disable the supervised user preferences relating to permissions and
+  // extensions.
   supervised_user_test_util::
       SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
+  supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
+      profile(), false); /* Default value. */
 
-  // The extension should be disabled only if the extension parental controls
-  // are enabled and the extensions are governed by the
-  // `kSupervisedUserExtensionsMayRequestPermissions` preference.
+  // The supervised user is never blocked from updating the permissions of an
+  // extension.
   std::unique_ptr<api::developer_private::ExtensionInfo> info =
       GenerateExtensionInfo(extension_id);
-  bool is_extension_disabled =
-      ApplyParentalControlsOnExtensions() &&
-      GetExtensionManagementFamilyLinkSwitch() ==
-          ExtensionManagementFamilyLinkSwitch::kManagedByPermissionsSwitch;
-  EXPECT_EQ(info->disable_reasons.parent_disabled_permissions,
-            is_extension_disabled);
+  EXPECT_FALSE(info->disable_reasons.parent_disabled_permissions);
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    ExtensionsForSupervisedUsers,
-    ExtensionInfoGeneratorUnitTestSupervised,
-    testing::Combine(
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-        testing::Values(ExtensionsParentalControlState::kEnabled,
-                        ExtensionsParentalControlState::kDisabled),
-#else
-        // For ChromeOS the extension parental controls are on by default.
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-#endif
-        testing::Values(
-            ExtensionManagementFamilyLinkSwitch::kManagedByPermissionsSwitch,
-            ExtensionManagementFamilyLinkSwitch::kManagedByExtensionsSwitch)),
-    [](const auto& info) {
-      return std::string(std::get<0>(info.param) ==
-                                 ExtensionsParentalControlState::kEnabled
-                             ? "WithExtensionParentalControls"
-                             : "WithoutExtensionParentalControls") +
-             std::string(std::get<1>(info.param) ==
-                                 ExtensionManagementFamilyLinkSwitch::
-                                     kManagedByExtensionsSwitch
-                             ? "ManagedByExtensionsFamilyLinkSwitch"
-                             : "ManagedByPermissionsFamilyLinkSwitch");
-    });
-
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
 
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/extensions/api/management/management_api_unittest.cc b/chrome/browser/extensions/api/management/management_api_unittest.cc
index 9ecffab..d9bbbda 100644
--- a/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -1213,42 +1213,11 @@
   int show_block_dialog_count_ = 0;
 };
 
-// Whether the extension parental controls are managed by the Family Link
-// "Extensions" switch ("Allow child to add extensions without asking for
-// permission") or the "Permissions" switch ("Permissions for sites").
-enum class ExtensionManagementSwitch : int {
-  kManagedByExtensions = 0,
-  kManagedByPermissions = 1
-};
-
 // Tests for supervised users (child accounts). Supervised users are not allowed
 // to install apps or extensions unless their parent approves.
-class ManagementApiSupervisedUserTest
-    : public ManagementApiUnitTest,
-      public ::testing::WithParamInterface<ExtensionManagementSwitch> {
+class ManagementApiSupervisedUserTest : public ManagementApiUnitTest {
  public:
-  ManagementApiSupervisedUserTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    if (IsManagedBySwitch(
-           ExtensionManagementSwitch::kManagedByExtensions)) {
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
+  ManagementApiSupervisedUserTest() = default;
   ~ManagementApiSupervisedUserTest() override = default;
 
   // ManagementApiUnitTest:
@@ -1290,10 +1259,6 @@
         base::WrapUnique(supervised_user_delegate_.get()));
   }
 
-  bool IsManagedBySwitch(ExtensionManagementSwitch management_switch) {
-    return GetParam() == management_switch;
-  }
-
   std::unique_ptr<content::WebContents> web_contents_;
   raw_ptr<ManagementAPI> management_api_ = nullptr;
   raw_ptr<TestSupervisedUserExtensionsDelegate> supervised_user_delegate_ =
@@ -1301,11 +1266,11 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-// Tests that locally approved extensions (on the feature release of
-// `kEnableSupervisedUserSkipParentApprovalToInstallExtensions`) can be
-// enabled by the supervised user. The enabling action does not grant parental
-// approval. Prevents regressions to b/336759592.
-TEST_P(ManagementApiSupervisedUserTest,
+// Tests that locally approved extensions (when parental extensions control
+// apply for the first time) can be enabled by the supervised user.
+// The enabling action does not grant parental approval.
+// Prevents regressions to crbug.com/336759592.
+TEST_F(ManagementApiSupervisedUserTest,
        SetEnabled_SetEnabledForLocallyApprovedExtension) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
@@ -1322,7 +1287,6 @@
 
   bool is_locally_parent_approved = false;
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-  if (IsManagedBySwitch(ExtensionManagementSwitch::kManagedByExtensions)) {
     // Simulate a local approval grant for this extension.
     base::Value::Dict locally_approved;
     locally_approved.Set(extension_id, true);
@@ -1330,7 +1294,7 @@
         prefs::kSupervisedUserLocallyParentApprovedExtensions,
         std::move(locally_approved));
     is_locally_parent_approved = true;
-  }
+
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 
   // Start with an initially disabled extension.
@@ -1338,9 +1302,9 @@
   ASSERT_EQ(supervised_user_delegate_->IsExtensionAllowedByParent(*extension),
             is_locally_parent_approved);
 
-  // Try to enable it. If the extension is locally approved (Win/Linux/Mac when
-  // managed by "Extensions" switch), the enabling should succeed. Otherwise it
-  // should fail due to missing parent approval.
+  // Try to enable it. If the extension is locally approved (Win/Linux/Mac),
+  // the enabling should succeed. Otherwise it should fail due to missing parent
+  // approval.
   std::string error;
   bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
                                        /*use_user_gesture=*/true,
@@ -1371,62 +1335,10 @@
                    .contains(extension_id));
 }
 
-TEST_P(ManagementApiSupervisedUserTest, SetEnabled_BlockedByParent) {
-  // Preconditions.
-  ASSERT_TRUE(profile()->IsChild());
-
-  base::HistogramTester histogram_tester;
-  base::UserActionTester user_action_tester;
-
-  base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
-  base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
-
-  base::FilePath path = base_path.AppendASCII("v1");
-  const Extension* extension =
-      PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
-  ASSERT_TRUE(extension);
-  // The extension should be installed but disabled.
-  EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
-  const ExtensionId& extension_id = extension->id();
-  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
-  EXPECT_TRUE(prefs->HasDisableReason(
-      extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
-
-  // Simulate disabling Permissions for sites, apps and extensions in the
-  // testing supervised user service delegate used by the Management API.
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
-
-  // The supervised user trying to enable the extensions
-  // should fail because the extension is missing parent approval.
-  {
-    std::string error;
-    bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
-                                         /*use_user_gesture=*/true,
-                                         /*accept_dialog=*/true, &error);
-    EXPECT_FALSE(success);
-    EXPECT_FALSE(error.empty());
-    EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
-
-    // The block dialog should have been shown if extension parental controls
-    // are governed by the "Permissions" switch. It is never shown if they are
-    // managed by the "Extensions" switch.
-    bool should_be_blocked = IsManagedBySwitch(
-         ExtensionManagementSwitch::kManagedByPermissions);
-    EXPECT_EQ(supervised_user_delegate_->show_block_dialog_count(),
-              should_be_blocked ? 1 : 0);
-  }
-
-  // Metrics reporting cannot be tested here, because the current implementation
-  // of `TestSupervisedUserExtensionsDelegate` overrides the
-  // `ShowInstallBlockedByParentDialogForExtension` method that records the
-  // metric in the production code.
-}
-
 // Tests enabling an extension via management API after it was disabled due to
 // permission increase for supervised users.
 // Prevents a regression to crbug/1068660.
-TEST_P(ManagementApiSupervisedUserTest, SetEnabled_AfterIncreasedPermissions) {
+TEST_F(ManagementApiSupervisedUserTest, SetEnabled_AfterIncreasedPermissions) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
 
@@ -1508,115 +1420,11 @@
       SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName, 2);
 }
 
-// Tests that supervised users can't approve permission updates by themselves
-// when the "Permissions for sites, apps and extensions" toggle is off and the
-// Extension parental controls are managed by the "Permissions" Family Link
-// switch.
-TEST_P(ManagementApiSupervisedUserTest,
-       SetEnabled_CantApprovePermissionUpdatesToggleOff) {
-  // Preconditions.
-  ASSERT_TRUE(profile()->IsChild());
-
-  base::HistogramTester histogram_tester;
-
-  base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
-  base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
-
-  base::FilePath path = base_path.AppendASCII("v1");
-  const Extension* extension =
-      PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
-  ASSERT_TRUE(extension);
-  // The extension should be installed but disabled pending custodian approval.
-  EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
-  // Save the id, as |extension| will be destroyed during updating.
-  const ExtensionId extension_id = extension->id();
-
-  // Simulate parent approval for the extension installation.
-  GetSupervisedUserExtensionsDelegate()->AddExtensionApproval(*extension);
-  // The extension should be enabled now.
-  EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
-
-  // There should be 1 kApprovalGranted UMA metric.
-  histogram_tester.ExpectUniqueSample(
-      SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
-      SupervisedUserExtensionsMetricsRecorder::UmaExtensionState::
-          kApprovalGranted,
-      1);
-  histogram_tester.ExpectTotalCount(
-      SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName, 1);
-
-  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
-  std::unique_ptr<const PermissionSet> known_perms =
-      prefs->GetGrantedPermissions(extension_id);
-  ASSERT_TRUE(known_perms);
-  // v1 extension doesn't have any permissions.
-  EXPECT_TRUE(known_perms->IsEmpty());
-
-  // Update to a new version with increased permissions.
-  path = base_path.AppendASCII("v2");
-  PackCRXAndUpdateExtension(extension_id, path, pem_path, DISABLED);
-  // The extension should be disabled.
-  EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
-  // Due to a permission increase, prefs will contain escalation information.
-  EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
-
-  // If the "Permissions for sites, apps and extensions" toggle is off, then the
-  // enable attempt should fail if the extension parental controls are managed
-  // by the "Permissions" Family Link switch. Otherwise it should be enabled.
-  bool should_be_enabled = IsManagedBySwitch(
-                              ExtensionManagementSwitch::kManagedByExtensions);
-  {
-    supervised_user_test_util::
-        SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
-    std::string error;
-    bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
-                                         /*use_user_gesture=*/true,
-                                         /*accept_dialog=*/true, &error);
-
-    EXPECT_EQ(should_be_enabled, success);
-    EXPECT_EQ(should_be_enabled, error.empty());
-    EXPECT_EQ(!should_be_enabled,
-              registry()->disabled_extensions().Contains(extension_id));
-    EXPECT_EQ(should_be_enabled,
-              registry()->enabled_extensions().Contains(extension_id));
-    // Prefs will still contain the escalation information if the enable attempt
-    // failed.
-    EXPECT_EQ(!should_be_enabled,
-              prefs->DidExtensionEscalatePermissions(extension_id));
-  }
-
-  // Permissions for v2 extension should not be granted if the extension
-  // parental controls are managed by the "Permissions" switch.
-  known_perms = prefs->GetGrantedPermissions(extension_id);
-  ASSERT_TRUE(known_perms);
-  EXPECT_EQ(!should_be_enabled, known_perms->IsEmpty());
-
-  // The parent approval dialog should have not appeared: The parent approval
-  // dialog should never appear when the "Permissions for sites, apps and
-  // extensions" toggle is off and it is used to manage the extensions.
-  // If the "Extensions" toggle is used to manage the extensions, then the
-  // extension must have been enabled, so the dialog does not appear.
-  EXPECT_EQ(0, supervised_user_delegate_->show_dialog_count());
-
-  // There should be no new UMA metrics if the extension parental controls are
-  // managed by the "Permissions" switch.
-  // If the extension parental controls are managed by the "Extensions" switch
-  // the extension become enabled and the Permission increase is granted.
-  histogram_tester.ExpectBucketCount(
-      SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
-      SupervisedUserExtensionsMetricsRecorder::UmaExtensionState::
-          kPermissionsIncreaseGranted,
-      should_be_enabled ? 1 : 0);
-  histogram_tester.ExpectTotalCount(
-      SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
-      should_be_enabled ? 2 : 1);
-}
-
 // Tests that if an extension still requires parental consent, the supervised
 // user approving it for permissions increase won't enable the extension and
 // bypass parental consent.
 // Prevents a regression to crbug/1070760.
-TEST_P(ManagementApiSupervisedUserTest,
+TEST_F(ManagementApiSupervisedUserTest,
        SetEnabled_CustodianApprovalRequiredAndPermissionsIncrease) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
@@ -1703,7 +1511,7 @@
 
 // Tests that trying to enable an extension with parent approval for supervised
 // users still fails, if there's unsupported requirements.
-TEST_P(ManagementApiSupervisedUserTest, SetEnabled_UnsupportedRequirement) {
+TEST_F(ManagementApiSupervisedUserTest, SetEnabled_UnsupportedRequirement) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
   ASSERT_EQ(0, supervised_user_delegate_->show_dialog_count());
@@ -1749,7 +1557,7 @@
 
 // Tests UMA metrics related to supervised users enabling and disabling
 // extensions.
-TEST_P(ManagementApiSupervisedUserTest, SetEnabledDisabled_UmaMetrics) {
+TEST_F(ManagementApiSupervisedUserTest, SetEnabledDisabled_UmaMetrics) {
   base::HistogramTester histogram_tester;
   base::UserActionTester user_action_tester;
 
@@ -1813,18 +1621,6 @@
                 SupervisedUserExtensionsMetricsRecorder::kDisabledActionName));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    ManagementApiSupervisedUserTest,
-    testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                    ExtensionManagementSwitch::kManagedByPermissions),
-    [](const auto& info) {
-      return std::string(info.param ==
-                                 ExtensionManagementSwitch::kManagedByExtensions
-                             ? "ManagedByExtensionsSwitch"
-                             : "ManagedByPermissionsSwitch");
-    });
-
 // Tests for supervised users (child accounts) with additional setup code.
 class ManagementApiSupervisedUserTestWithSetup
     : public ManagementApiSupervisedUserTest {
@@ -1849,7 +1645,7 @@
   scoped_refptr<const Extension> extension_;
 };
 
-TEST_P(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentApproves) {
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentApproves) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
   ASSERT_EQ(0, delegate_->enable_count_);
@@ -1878,7 +1674,7 @@
   EXPECT_EQ(1, delegate_->enable_count_);
 }
 
-TEST_P(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentDenies) {
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentDenies) {
   // Start with a disabled extension that needs parent permission.
   service()->DisableExtension(
       extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
@@ -1902,7 +1698,7 @@
   EXPECT_EQ(0, delegate_->enable_count_);
 }
 
-TEST_P(ManagementApiSupervisedUserTestWithSetup, SetEnabled_DialogFails) {
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_DialogFails) {
   // Start with a disabled extension that needs parent permission.
   service()->DisableExtension(
       extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
@@ -1924,7 +1720,7 @@
   EXPECT_EQ(0, delegate_->enable_count_);
 }
 
-TEST_P(ManagementApiSupervisedUserTestWithSetup, SetEnabled_PreviouslyAllowed) {
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_PreviouslyAllowed) {
   // Disable the extension.
   service()->DisableExtension(extension_->id(),
                               disable_reason::DISABLE_USER_ACTION);
@@ -1946,7 +1742,7 @@
 
 // Tests launching the Parent Permission Dialog from a background page, where
 // there isn't active web contents. The parent approves the request.
-TEST_P(ManagementApiSupervisedUserTestWithSetup,
+TEST_F(ManagementApiSupervisedUserTestWithSetup,
        SetEnabled_ParentPermissionApprovedFromBackgroundPage) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
@@ -1978,7 +1774,7 @@
 
 // Tests launching the Parent Permission Dialog from a background page, where
 // there isn't active web contents. The parent cancels the request.
-TEST_P(ManagementApiSupervisedUserTestWithSetup,
+TEST_F(ManagementApiSupervisedUserTestWithSetup,
        SetEnabled_ParentPermissionCanceledFromBackgroundPage) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
@@ -2011,7 +1807,7 @@
 // Tests launching the Parent Permission Dialog from a background page, where
 // there isn't active web contents. The request will fail due to some sort of
 // error, such as a network error.
-TEST_P(ManagementApiSupervisedUserTestWithSetup,
+TEST_F(ManagementApiSupervisedUserTestWithSetup,
        SetEnabled_ParentPermissionFailedFromBackgroundPage) {
   // Preconditions.
   ASSERT_TRUE(profile()->IsChild());
@@ -2040,64 +1836,5 @@
   // Extension was not enabled.
   EXPECT_EQ(0, delegate_->enable_count_);
 }
-
-// Tests launching the Extension Install Blocked By Parent Dialog from a
-// background page, where there isn't active web contents. This dialog
-// appears only then the "Permissions" Family Link switch managed the
-// extension parental controls.
-TEST_P(ManagementApiSupervisedUserTestWithSetup,
-       SetEnabled_ExtensionInstallBlockedByParentFromBackgroundPage) {
-  // Preconditions.
-  ASSERT_TRUE(profile()->IsChild());
-
-  // Start with a disabled extension that needs parent permission.
-  service()->DisableExtension(
-      extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
-
-  // Simulate the parent disabling the "Permissions for sites, apps and
-  // extensions" toggle.
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
-
-  // Simulate a call to chrome.management.setEnabled(). The enable attempt
-  // should fail as the extension is missing parent approval.
-  std::string error;
-  bool success = RunSetEnabledFunction(
-      /*web_contents=*/nullptr, extension_->id(), /*use_user_gesture=*/true,
-      /*accept_dialog=*/true, &error);
-  EXPECT_FALSE(success);
-  bool should_be_blocked = IsManagedBySwitch(
-                              ExtensionManagementSwitch::kManagedByPermissions);
-  if (should_be_blocked) {
-    const std::string expected_error = ErrorUtils::FormatErrorMessage(
-        extension_management_api_constants::kUserCantModifyError,
-        extension_->id());
-    EXPECT_EQ(expected_error, error);
-  }
-  // The Extension Install Blocked By Parent Dialog should have opened despite
-  // the lack of web contents, if the extension is blocked (when managed by the
-  // "Permissions" switch). Otherwise (when managed by "Extensions" switch), the
-  // extension is never blocked and the parent permission dialog appears.
-  EXPECT_EQ(should_be_blocked ? 1 : 0,
-            supervised_user_delegate_->show_block_dialog_count());
-  EXPECT_EQ(should_be_blocked ? 0 : 1,
-            supervised_user_delegate_->show_dialog_count());
-
-  // Extension was not enabled.
-  EXPECT_EQ(0, delegate_->enable_count_);
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    ManagementApiSupervisedUserTestWithSetup,
-    testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                    ExtensionManagementSwitch::kManagedByPermissions),
-    [](const auto& info) {
-      return std::string(info.param ==
-                                 ExtensionManagementSwitch::kManagedByExtensions
-                             ? "ManagedByExtensionsSwitch"
-                             : "ManagedByPermissionsSwitch");
-    });
-
 }  // namespace
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/webstore_private/extension_install_status.cc b/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
index a60b3f20..b0d583f 100644
--- a/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
+++ b/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
@@ -16,7 +16,6 @@
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/supervised_user/core/browser/supervised_user_preferences.h"
-#include "components/supervised_user/core/common/features.h"
 #include "components/supervised_user/core/common/pref_names.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -113,10 +112,7 @@
 
   // Check if parent approval is needed for a supervised user to install
   // a new extension.
-  if (base::FeatureList::IsEnabled(
-          supervised_user::
-              kExposedParentalControlNeededForExtensionInstallation) &&
-      !registry->GetInstalledExtension(extension_id) &&
+  if (!registry->GetInstalledExtension(extension_id) &&
       supervised_user::AreExtensionsPermissionsEnabled(profile) &&
       !supervised_user::SupervisedUserCanSkipExtensionParentApprovals(
           profile) &&
diff --git a/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc b/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
index 8c50029..e54ef7c 100644
--- a/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
+++ b/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
@@ -664,28 +664,7 @@
 }
 
 class SupervisedUserExtensionInstallStatusTest
-    : public ExtensionInstallStatusTest {
- public:
-  SupervisedUserExtensionInstallStatusTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || \
-    BUILDFLAG(IS_DESKTOP_ANDROID)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) ||
-        // BUILDFLAG(IS_DESKTOP_ANDROID)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    enabled_features.push_back(
-        supervised_user::kExposedParentalControlNeededForExtensionInstallation);
-    feature_list_.InitWithFeatures(enabled_features, /*disabled_features=*/{});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
+    : public ExtensionInstallStatusTest {};
 
 // If a supervised user requires parent approval to install a new extension that
 // has not received parental approval before, then
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index d6693f6..97f9aaf 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -514,34 +514,6 @@
     return;
   }
 
-  // Check if the supervised user is allowed to install extensions in the legacy
-  // flow. NOTE: we do not block themes.
-  if (!dummy_extension_->is_theme()) {
-    if (supervised_user::AreExtensionsPermissionsEnabled(profile_) &&
-        !supervised_user::
-            IsSupervisedUserSkipParentApprovalToInstallExtensionsEnabled()) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-      SupervisedUserExtensionsDelegate* supervised_user_extensions_delegate =
-          ManagementAPI::GetFactoryInstance()
-              ->Get(profile_)
-              ->GetSupervisedUserExtensionsDelegate();
-      CHECK(supervised_user_extensions_delegate);
-      if (!supervised_user_extensions_delegate->CanInstallExtensions()) {
-        // Assume that the block dialog will be shown here since it was checked
-        // that extensions cannot be installed by the child user. If extensions
-        // are allowed, the install prompt will be shown before the request
-        // permission dialog is shown.
-        RequestExtensionApproval(web_contents);
-        return;
-      }
-#else
-      // TODO(crbug.com/410616937): Support supervised user install controls on
-      // desktop Android.
-      NOTIMPLEMENTED() << "Supervised user checks not yet supported.";
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-    }
-  }
-
   // Check the management policy before the installation process begins.
   ExtensionInstallStatus install_status = GetWebstoreExtensionInstallStatus(
       id, profile_, dummy_extension_->manifest()->type(),
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index 531d95f1..0eb1d7143 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -311,16 +311,9 @@
 static constexpr char kTestAppId[] = "iladmdjkfniedhfhcfoefgojhgaiaccc";
 static constexpr char kTestAppVersion[] = "0.1";
 
-enum class SupervisedUserExtensionManagedBySwitch : int {
-  kPermissions = 0,
-  kExtensions,
-};
-
 // Test fixture for various cases of installation for child accounts.
 class SupervisedUserExtensionWebstorePrivateApiTest
     : public ExtensionWebstorePrivateApiTest,
-      public ::testing::WithParamInterface<
-          SupervisedUserExtensionManagedBySwitch>,
 #if BUILDFLAG(IS_CHROMEOS)
       public TestExtensionApprovalsManagerObserver,
 #endif
@@ -348,32 +341,6 @@
                 .sign_in_mode =
                     supervised_user::SupervisionMixin::SignInMode::kSupervised,
             }) {
-
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif
-
-    if (GetParam() == SupervisedUserExtensionManagedBySwitch::kExtensions) {
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  ~SupervisedUserExtensionWebstorePrivateApiTest() override {
-    // Reset the feature list explicitly here, as other test members that may
-    // contain it will try to destruct it (e.g. objects contained in
-    // supervision_mixin_).
-    feature_list_.Reset();
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -445,19 +412,6 @@
                   crosapi::mojom::ParentAccessCanceledResult::New()));
           break;
         case NextDialogAction::kAccept:
-          bool can_request_permission =
-              (GetParam() ==
-               SupervisedUserExtensionManagedBySwitch::kPermissions)
-                  ? browser()->profile()->GetPrefs()->GetBoolean(
-                        prefs::kSupervisedUserExtensionsMayRequestPermissions)
-                  : true;
-
-          if (!can_request_permission) {
-            SetParentAccessDialogResult(
-                crosapi::mojom::ParentAccessResult::NewDisabled(
-                    crosapi::mojom::ParentAccessDisabledResult::New()));
-            break;
-          }
           SetParentAccessDialogResult(
               crosapi::mojom::ParentAccessResult::NewApproved(
                   crosapi::mojom::ParentAccessApprovedResult::New(
@@ -482,11 +436,10 @@
   std::unique_ptr<net::EmbeddedTestServer> embedded_test_server_;
   supervised_user::SupervisionMixin supervision_mixin_;
   std::optional<NextDialogAction> next_dialog_action_;
-  base::test::ScopedFeatureList feature_list_;
 };
 
 // Tests install for a child when parent permission is granted.
-IN_PROC_BROWSER_TEST_P(SupervisedUserExtensionWebstorePrivateApiTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionWebstorePrivateApiTest,
                        ParentPermissionGranted) {
   base::UserActionTester user_action_tester;
   WebstoreInstallListener listener;
@@ -520,7 +473,7 @@
 
 // Tests no install occurs for a child when the parent permission
 // dialog is canceled.
-IN_PROC_BROWSER_TEST_P(SupervisedUserExtensionWebstorePrivateApiTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionWebstorePrivateApiTest,
                        ParentPermissionCanceled) {
   base::UserActionTester user_action_tester;
   WebstoreInstallListener listener;
@@ -555,7 +508,7 @@
 }
 
 // Tests that no parent permission is required for a child to install a theme.
-IN_PROC_BROWSER_TEST_P(SupervisedUserExtensionWebstorePrivateApiTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionWebstorePrivateApiTest,
                        NoParentPermissionRequiredForTheme) {
   WebstoreInstallListener listener;
   auto delegate_reset = WebstorePrivateApi::SetDelegateForTesting(&listener);
@@ -565,13 +518,9 @@
   ASSERT_EQ("idlfhncioikpdnlhnmcjogambnefbbfp", listener.id());
 }
 
-// Tests that supervised user extension installs are blocked if
-// 1) the "Permissions for sites, apps and extensions" toggle is off and
-// 2) the extensions are managed by this toggle.
-// If the extensions are managed by the "Extensions" toggle (regardless of its
-// value), an extension installation is never blocked.
-IN_PROC_BROWSER_TEST_P(SupervisedUserExtensionWebstorePrivateApiTest,
-                       InstallBlockedWhenPermissionsToggleOff) {
+// Tests that supervised user extension installs are never blocked.
+IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionWebstorePrivateApiTest,
+                       InstallAlwaysAllowed) {
   base::HistogramTester histogram_tester;
   base::UserActionTester user_action_tester;
 
@@ -587,13 +536,9 @@
 
   // Expect the extension to be blocked or installed normally based on the
   // toggle that manages supervised user extensions.
-  std::string page =
-      GetParam() == SupervisedUserExtensionManagedBySwitch::kPermissions
-          ? "install_blocked_child.html"
-          : "install_child.html";
+  std::string page = "install_child.html";
   ASSERT_TRUE(RunInstallTest(page, "app.crx"));
 
-  if (GetParam() == SupervisedUserExtensionManagedBySwitch::kExtensions) {
     listener.Wait();
     ASSERT_TRUE(listener.received_success());
     ASSERT_EQ(kTestAppId, listener.id());
@@ -604,29 +549,25 @@
             .SetVersion(kTestAppVersion)
             .Build();
     ASSERT_TRUE(extensions_delegate_->IsExtensionAllowedByParent(*extension));
-  }
 
-  int expected_count_failed =
-      GetParam() == SupervisedUserExtensionManagedBySwitch::kPermissions ? 1
-                                                                         : 0;
-  histogram_tester.ExpectUniqueSample(
-      SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName,
-      SupervisedUserExtensionsMetricsRecorder::EnablementState::kFailedToEnable,
-      expected_count_failed);
-  histogram_tester.ExpectTotalCount(
-      SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName,
-      expected_count_failed);
-  EXPECT_EQ(
-      expected_count_failed,
-      user_action_tester.GetActionCount(
-          SupervisedUserExtensionsMetricsRecorder::kFailedToEnableActionName));
+    int expected_count_failed = 0;
+    histogram_tester.ExpectUniqueSample(
+        SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName,
+        SupervisedUserExtensionsMetricsRecorder::EnablementState::
+            kFailedToEnable,
+        expected_count_failed);
+    histogram_tester.ExpectTotalCount(
+        SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName,
+        expected_count_failed);
+    EXPECT_EQ(expected_count_failed,
+              user_action_tester.GetActionCount(
+                  SupervisedUserExtensionsMetricsRecorder::
+                      kFailedToEnableActionName));
 }
 
 // Tests a successful install for a child when parent permission can be skipped
-// on installation: 1) when extensions are managed via the dedicated
-// "Extensions" toggle and 2) the toggle is enabled. If extensions are managed
-// via the "Permissions" toggle, the parent approval is required.
-IN_PROC_BROWSER_TEST_P(SupervisedUserExtensionWebstorePrivateApiTest,
+// on installation (i.e. the "Extensions" toggle in ON).
+IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionWebstorePrivateApiTest,
                        InstallSuccessfulWhenExtensionsToggleOn) {
   base::UserActionTester user_action_tester;
   WebstoreInstallListener listener;
@@ -635,22 +576,17 @@
   // Turn on preference that skips parent approval on extension installations.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
-  if (GetParam() == SupervisedUserExtensionManagedBySwitch::kPermissions) {
-    set_next_dialog_action(NextDialogAction::kAccept);
-  } else {
-    // Turn off the "Permissions for sites, apps and extensions" toggle. It does
-    // not affect the successful installation on this mode.
-    supervised_user_test_util::
-        SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
-  }
+  // Turn off the "Permissions for sites, apps and extensions" toggle. It does
+  // not affect the successful installation of extensions.
+  supervised_user_test_util::
+      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
 
   ASSERT_TRUE(RunInstallTest("install_child.html", "app.crx"));
   listener.Wait();
   ASSERT_TRUE(listener.received_success());
   ASSERT_EQ(kTestAppId, listener.id());
 
-  EXPECT_EQ(GetParam() == SupervisedUserExtensionManagedBySwitch::kPermissions,
-            parent_permission_dialog_appeared_);
+  EXPECT_FALSE(parent_permission_dialog_appeared_);
 
   scoped_refptr<const Extension> extension =
       extensions::ExtensionBuilder("test extension")
@@ -660,8 +596,7 @@
   EXPECT_TRUE(extensions_delegate_->IsExtensionAllowedByParent(*extension));
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-  int parent_approval_dialog_count =
-      GetParam() == SupervisedUserExtensionManagedBySwitch::kExtensions ? 0 : 1;
+  int parent_approval_dialog_count = 0;
   // Parent Approval dialog metrics (when managed by Permissions toggle):
   EXPECT_EQ(parent_approval_dialog_count,
             user_action_tester.GetActionCount(
@@ -673,9 +608,8 @@
           SupervisedUserExtensionsMetricsRecorder::kApprovalGrantedActionName));
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 
-  // Extension Installation dialog metrics (when managed by Extensions toggle):
-  int extension_install_dialog_count =
-      GetParam() == SupervisedUserExtensionManagedBySwitch::kExtensions ? 1 : 0;
+  // Extension Installation dialog metrics.
+  int extension_install_dialog_count = 1;
   EXPECT_EQ(extension_install_dialog_count,
             user_action_tester.GetActionCount(
                 SupervisedUserExtensionsMetricsRecorder::
@@ -686,18 +620,6 @@
                     kApprovalGrantedByDefaultName));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    SupervisedUserExtensionWebstorePrivateApiTest,
-    testing::Values(SupervisedUserExtensionManagedBySwitch::kExtensions,
-                    SupervisedUserExtensionManagedBySwitch::kPermissions),
-    [](const auto& info) {
-      return (info.param) ==
-                     SupervisedUserExtensionManagedBySwitch::kPermissions
-                 ? "ManagedByPermissionsToggle"
-                 : "ManagedByExtensionsToggle";
-    });
-
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 class ExtensionWebstoreGetWebGLStatusTest : public PlatformBrowserTest {
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
index 0fe8b40..2a3df79c 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
@@ -328,26 +328,7 @@
 }
 
 class SupervisedUserWebstorePrivateGetExtensionStatusTest
-    : public WebstorePrivateGetExtensionStatusTest {
- public:
-  SupervisedUserWebstorePrivateGetExtensionStatusTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    enabled_features.push_back(
-        supervised_user::kExposedParentalControlNeededForExtensionInstallation);
-    feature_list_.InitWithFeatures(enabled_features, /*disabled_features=*/{});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
+    : public WebstorePrivateGetExtensionStatusTest {};
 
 TEST_F(SupervisedUserWebstorePrivateGetExtensionStatusTest,
        ExtensionCustodianApprovalRequired) {
diff --git a/chrome/browser/extensions/chrome_extension_system.cc b/chrome/browser/extensions/chrome_extension_system.cc
index d50ed04..8ce07fb 100644
--- a/chrome/browser/extensions/chrome_extension_system.cc
+++ b/chrome/browser/extensions/chrome_extension_system.cc
@@ -19,16 +19,12 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/chrome_app_sorting.h"
-#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
 #include "chrome/browser/extensions/chrome_extension_system_factory.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_error_controller.h"
 #include "chrome/browser/extensions/extension_garbage_collector.h"
 #include "chrome/browser/extensions/extension_management.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_sync_service.h"
 #include "chrome/browser/extensions/install_verifier.h"
 #include "chrome/browser/extensions/load_error_reporter.h"
 #include "chrome/browser/extensions/shared_module_service.h"
@@ -43,7 +39,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/url_data_source.h"
-#include "extensions/browser/content_verifier/content_verifier.h"
+#include "extensions/browser/app_sorting.h"
 #include "extensions/browser/delayed_install_manager.h"
 #include "extensions/browser/extension_pref_store.h"
 #include "extensions/browser/extension_pref_value_map.h"
@@ -62,6 +58,17 @@
 #include "extensions/common/manifest_url_handlers.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "chrome/browser/extensions/chrome_app_sorting.h"
+#include "chrome/browser/extensions/chrome_content_verifier_delegate.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_sync_service.h"
+#include "extensions/browser/content_verifier/content_verifier.h"
+#else
+#include "chrome/browser/extensions/chrome_extension_registrar_delegate.h"
+#include "extensions/browser/null_app_sorting.h"
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS)
 #include "ash/constants/ash_switches.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -80,7 +87,10 @@
 
 namespace {
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
 // Helper to serve as an UninstallPingSender::Filter callback.
+// TODO(crbug.com/413460628): This depends on initialization of ExtensionUpdater
+// performed by ExtensionService.
 UninstallPingSender::FilterResult ShouldSendUninstallPing(
     Profile* profile,
     const Extension* extension,
@@ -93,6 +103,7 @@
   }
   return UninstallPingSender::DO_NOT_SEND_PING;
 }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 }  // namespace
 
@@ -193,13 +204,18 @@
       !command_line->HasSwitch(::switches::kNoErrorDialogs);
   LoadErrorReporter::Init(allow_noisy_errors);
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // TODO(crbug.com/413122584): Port ChromeContentVerifierDelegate to desktop
+  // Android.
   content_verifier_ = new ContentVerifier(
       profile_, std::make_unique<ChromeContentVerifierDelegate>(profile_));
+#endif
 
   service_worker_manager_ = std::make_unique<ServiceWorkerManager>(profile_);
 
   user_script_manager_ = std::make_unique<UserScriptManager>(profile_);
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   bool autoupdate_enabled =
       !profile_->IsGuestSession() && !profile_->IsSystemProfile();
 #if BUILDFLAG(IS_CHROMEOS)
@@ -207,6 +223,7 @@
     autoupdate_enabled = false;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
+  // TODO(crbug.com/413460628): Port ExtensionService to desktop Android.
   extension_service_ = std::make_unique<ExtensionService>(
       profile_, base::CommandLine::ForCurrentProcess(),
       profile_->GetPath().AppendASCII(kInstallDirectoryName),
@@ -215,14 +232,29 @@
       ExtensionErrorController::Get(profile_), autoupdate_enabled,
       extensions_enabled, &ready_);
 
+  // TODO(crbug.com/413460628): This depends on the initialization of
+  // ExtensionUpdater by ExtensionService.
   uninstall_ping_sender_ = std::make_unique<UninstallPingSender>(
       ExtensionRegistry::Get(profile_),
       base::BindRepeating(&ShouldSendUninstallPing, profile_));
+#else
+  // Perform initialization usually handled by ExtensionService.
+  registrar_delegate_ =
+      std::make_unique<ChromeExtensionRegistrarDelegate>(profile_);
+  auto* registrar = ExtensionRegistrar::Get(profile_);
+  registrar->Init(
+      registrar_delegate_.get(), extensions_enabled,
+      base::CommandLine::ForCurrentProcess(),
+      profile_->GetPath().AppendASCII(kInstallDirectoryName),
+      profile_->GetPath().AppendASCII(kUnpackedInstallDirectoryName));
+  registrar_delegate_->Init(registrar);
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
   // These services must be registered before the ExtensionService tries to
   // load any extensions.
   {
     InstallVerifier::Get(profile_)->Init();
+#if BUILDFLAG(ENABLE_EXTENSIONS)
     ChromeContentVerifierDelegate::VerifyInfo::Mode mode =
         ChromeContentVerifierDelegate::GetDefaultMode();
 #if BUILDFLAG(IS_CHROMEOS)
@@ -232,6 +264,7 @@
     if (mode >= ChromeContentVerifierDelegate::VerifyInfo::Mode::BOOTSTRAP) {
       content_verifier_->Start();
     }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 #if BUILDFLAG(IS_CHROMEOS)
     // This class is used to check the permissions of the force-installed
     // extensions inside the managed guest session. It updates the local state
@@ -271,14 +304,25 @@
   component_loader->AddDefaultComponentExtensions(skip_session_extensions);
 #endif
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   app_sorting_ = std::make_unique<ChromeAppSorting>(profile_);
+#else
+  app_sorting_ = std::make_unique<NullAppSorting>();
+#endif
 
   InitInstallGates();
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   extension_service_->Init();
+#else
+  // This is usually handled by ExtensionSystem::Init().
+  ready_.Signal();
+#endif
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   // Make sure ExtensionSyncService is created.
   ExtensionSyncService::Get(profile_);
+#endif
 
   // Make the chrome://extension-icon/ resource available.
   content::URLDataSource::Add(profile_,
@@ -290,12 +334,16 @@
 }
 
 void ChromeExtensionSystem::Shared::Shutdown() {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   if (content_verifier_.get()) {
     content_verifier_->Shutdown();
   }
   if (extension_service_) {
     extension_service_->Shutdown();
   }
+#else
+  registrar_delegate_.reset();
+#endif
 }
 
 ServiceWorkerManager* ChromeExtensionSystem::Shared::service_worker_manager() {
@@ -320,7 +368,11 @@
 }
 
 ExtensionService* ChromeExtensionSystem::Shared::extension_service() {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   return extension_service_.get();
+#else
+  return nullptr;
+#endif
 }
 
 ManagementPolicy* ChromeExtensionSystem::Shared::management_policy() {
@@ -340,7 +392,11 @@
 }
 
 ContentVerifier* ChromeExtensionSystem::Shared::content_verifier() {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   return content_verifier_.get();
+#else
+  return nullptr;
+#endif
 }
 
 //
@@ -437,11 +493,8 @@
     InstallUpdateCallback install_update_callback) {
   DCHECK(!install_update_callback.is_null());
 
-  ExtensionService* service = extension_service();
-  DCHECK(service);
-
   scoped_refptr<CrxInstaller> installer =
-      CrxInstaller::CreateSilent(service->profile());
+      CrxInstaller::CreateSilent(profile_->GetOriginalProfile());
   installer->set_delete_source(true);
   installer->AddInstallerCallback(std::move(install_update_callback));
   installer->set_install_immediately(install_immediately);
@@ -452,8 +505,13 @@
 void ChromeExtensionSystem::PerformActionBasedOnOmahaAttributes(
     const std::string& extension_id,
     const base::Value::Dict& attributes) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // TODO(crbug.com/413460628): Port ExtensionService to desktop Android.
   extension_service()->PerformActionBasedOnOmahaAttributes(extension_id,
                                                            attributes);
+#else
+  NOTIMPLEMENTED();
+#endif
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/chrome_extension_system.h b/chrome/browser/extensions/chrome_extension_system.h
index ace1e3e..e5551b2 100644
--- a/chrome/browser/extensions/chrome_extension_system.h
+++ b/chrome/browser/extensions/chrome_extension_system.h
@@ -34,6 +34,7 @@
 
 namespace extensions {
 
+class ChromeExtensionRegistrarDelegate;
 class ChromeExtensionSystemSharedFactory;
 class UninstallPingSender;
 class InstallGate;
@@ -132,14 +133,20 @@
     // manifests. This region is shared between all extensions.
     std::unique_ptr<UserScriptManager> user_script_manager_;
     // ExtensionService depends on StateStore and Blocklist.
+#if BUILDFLAG(ENABLE_EXTENSIONS)
     std::unique_ptr<ExtensionService> extension_service_;
+#else
+    std::unique_ptr<ChromeExtensionRegistrarDelegate> registrar_delegate_;
+#endif
     std::unique_ptr<ManagementPolicy> management_policy_;
     std::unique_ptr<QuotaService> quota_service_;
     std::unique_ptr<AppSorting> app_sorting_;
     std::unique_ptr<InstallGate> update_install_gate_;
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
     // For verifying the contents of extensions read from disk.
     scoped_refptr<ContentVerifier> content_verifier_;
+#endif
 
     std::unique_ptr<UninstallPingSender> uninstall_ping_sender_;
 
diff --git a/chrome/browser/extensions/chrome_extension_system_factory.cc b/chrome/browser/extensions/chrome_extension_system_factory.cc
index 24dbd36..b912a07 100644
--- a/chrome/browser/extensions/chrome_extension_system_factory.cc
+++ b/chrome/browser/extensions/chrome_extension_system_factory.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/extensions/install_verifier_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/event_router_factory.h"
 #include "extensions/browser/extension_host_registry.h"
@@ -21,6 +20,10 @@
 #include "extensions/browser/process_manager_factory.h"
 #include "extensions/browser/renderer_startup_helper.h"
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "chrome/browser/ui/global_error/global_error_service_factory.h"
+#endif
+
 namespace extensions {
 
 // ChromeExtensionSystemSharedFactory
@@ -56,7 +59,10 @@
   DependsOn(ExtensionManagementFactory::GetInstance());
   // This depends on ExtensionService, which depends on ExtensionRegistry.
   DependsOn(ExtensionRegistryFactory::GetInstance());
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // GlobalErrorService is only used on Win/Mac/Linux.
   DependsOn(GlobalErrorServiceFactory::GetInstance());
+#endif
   DependsOn(InstallVerifierFactory::GetInstance());
   DependsOn(ProcessManagerFactory::GetInstance());
   DependsOn(RendererStartupHelperFactory::GetInstance());
diff --git a/chrome/browser/extensions/component_loader_unittest.cc b/chrome/browser/extensions/component_loader_unittest.cc
index fbe757e..49627df 100644
--- a/chrome/browser/extensions/component_loader_unittest.cc
+++ b/chrome/browser/extensions/component_loader_unittest.cc
@@ -260,6 +260,10 @@
   EXPECT_EQ(0u, registry->enabled_extensions().size());
 }
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+// TODO(crbug.com/408458901): Enable on Android when we have an extensions test
+// base class that works on Android. This test seems to depend on how
+// TestExtensionSystem initializes components.
 TEST_F(ComponentLoaderTest, LoadAll) {
   ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
 
@@ -279,6 +283,7 @@
 
   EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
 }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 // TODO(crbug.com/408458901): Port these to desktop Android when we have an
 // extensions unit test base class where we can move MaybeSetupTestUser().
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
deleted file mode 100644
index e429248..0000000
--- a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
+++ /dev/null
@@ -1,251 +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/extensions/desktop_android/desktop_android_extension_system.h"
-
-#include <memory>
-#include <string>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/functional/bind.h"
-#include "chrome/browser/extensions/chrome_extension_registrar_delegate.h"
-#include "chrome/browser/extensions/load_error_reporter.h"
-#include "chrome/browser/extensions/permissions/permissions_updater.h"
-#include "chrome/browser/extensions/shared_module_service.h"
-#include "chrome/browser/extensions/updater/chrome_extension_downloader_factory.h"
-#include "chrome/browser/extensions/updater/extension_updater.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
-#include "chrome/browser/ui/webui/extensions/extensions_internals_source.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/value_store/value_store_factory_impl.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/url_data_source.h"
-#include "extensions/browser/api/app_runtime/app_runtime_api.h"
-#include "extensions/browser/extension_registrar.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_registry_factory.h"
-#include "extensions/browser/extension_system_provider.h"
-#include "extensions/browser/extensions_browser_client.h"
-#include "extensions/browser/install_flag.h"
-#include "extensions/browser/management_policy.h"
-#include "extensions/browser/null_app_sorting.h"
-#include "extensions/browser/quota_service.h"
-#include "extensions/browser/service_worker_manager.h"
-#include "extensions/browser/user_script_manager.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/extension.h"
-
-using content::BrowserContext;
-namespace extensions {
-
-namespace {
-
-// A factory implementation to construct and return the
-// DesktopAndroidExtensionSystem.
-class DesktopAndroidExtensionSystemFactory : public ExtensionSystemProvider {
- public:
-  DesktopAndroidExtensionSystemFactory()
-      : ExtensionSystemProvider(
-            "DesktopAndroidExtensionSystem",
-            BrowserContextDependencyManager::GetInstance()) {
-    DependsOn(ExtensionRegistryFactory::GetInstance());
-  }
-  DesktopAndroidExtensionSystemFactory(
-      const DesktopAndroidExtensionSystemFactory&) = delete;
-  DesktopAndroidExtensionSystemFactory& operator=(
-      const DesktopAndroidExtensionSystemFactory&) = delete;
-  ~DesktopAndroidExtensionSystemFactory() override = default;
-
-  // ExtensionSystemProvider implementation:
-  ExtensionSystem* GetForBrowserContext(
-      content::BrowserContext* context) override {
-    return static_cast<DesktopAndroidExtensionSystem*>(
-        GetInstance()->GetServiceForBrowserContext(context, true));
-  }
-
-  static DesktopAndroidExtensionSystemFactory* GetInstance() {
-    static base::NoDestructor<DesktopAndroidExtensionSystemFactory> g_instance;
-    return g_instance.get();
-  }
-
- private:
-  // BrowserContextKeyedServiceFactory implementation:
-  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
-      content::BrowserContext* context) const override {
-    return std::make_unique<DesktopAndroidExtensionSystem>(context);
-  }
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override {
-    // Use a separate instance for incognito.
-    return context;
-  }
-  bool ServiceIsCreatedWithBrowserContext() const override { return true; }
-};
-
-}  // namespace
-
-DesktopAndroidExtensionSystem::DesktopAndroidExtensionSystem(
-    BrowserContext* browser_context)
-    : browser_context_(browser_context),
-      // TODO(crbug.com/356905053): Provide real sorting once the web app story
-      // on Android is finalized.
-      app_sorting_(std::make_unique<NullAppSorting>()),
-      // TODO(crbug.com/408523607): Populate ManagementPolicy with actual
-      // policies.
-      management_policy_(std::make_unique<ManagementPolicy>()),
-      store_factory_(base::MakeRefCounted<value_store::ValueStoreFactoryImpl>(
-          browser_context->GetPath())) {}
-
-DesktopAndroidExtensionSystem::~DesktopAndroidExtensionSystem() = default;
-
-// static
-ExtensionSystemProvider* DesktopAndroidExtensionSystem::GetFactory() {
-  return DesktopAndroidExtensionSystemFactory::GetInstance();
-}
-
-void DesktopAndroidExtensionSystem::Shutdown() {}
-
-void DesktopAndroidExtensionSystem::InitForRegularProfile(
-    bool extensions_enabled) {
-  if (is_ready()) {
-    return;
-  }
-
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  bool allow_noisy_errors =
-      !command_line->HasSwitch(::switches::kNoErrorDialogs);
-  LoadErrorReporter::Init(allow_noisy_errors);
-
-  registrar_delegate_ = std::make_unique<ChromeExtensionRegistrarDelegate>(
-      Profile::FromBrowserContext(browser_context_));
-  registrar_ = ExtensionRegistrar::Get(browser_context_);
-  registrar_->Init(
-      registrar_delegate_.get(), extensions_enabled,
-      base::CommandLine::ForCurrentProcess(),
-      browser_context_->GetPath().AppendASCII(kInstallDirectoryName),
-      browser_context_->GetPath().AppendASCII(kUnpackedInstallDirectoryName));
-  registrar_delegate_->Init(registrar_.get());
-
-  service_worker_manager_ =
-      std::make_unique<ServiceWorkerManager>(browser_context_);
-  quota_service_ = std::make_unique<QuotaService>();
-  user_script_manager_ = std::make_unique<UserScriptManager>(browser_context_);
-
-  Profile* profile = Profile::FromBrowserContext(browser_context_);
-  if (!browser_context_->IsOffTheRecord()) {
-    // Make the chrome://extension-icon/ resource available. Only do this for
-    // non-incognito profiles because OffTheRecordProfileImpl adds its own.
-    // Also, this mimics the behavior of ChromeExtensionSystem.
-
-    content::URLDataSource::Add(browser_context_,
-                                std::make_unique<ExtensionIconSource>(profile));
-
-    // Register the source for the chrome://extensions-internals page.
-    content::URLDataSource::Add(
-        profile, std::make_unique<ExtensionsInternalsSource>(profile));
-  }
-
-  bool autoupdate_enabled =
-      !profile->IsGuestSession() && !profile->IsSystemProfile();
-  if (autoupdate_enabled) {
-    auto* updater = ExtensionUpdater::Get(browser_context_);
-    // Note, if `updater` has already been initialized and started for regular
-    // profile, do not do this again for incognito profile.
-    if (!updater->enabled()) {
-      updater->InitAndEnable(
-          ExtensionPrefs::Get(browser_context_), profile->GetPrefs(),
-          kDefaultUpdateFrequency,
-          ExtensionsBrowserClient::Get()->GetExtensionCache(),
-          base::BindRepeating(
-              ChromeExtensionDownloaderFactory::CreateForProfile, profile));
-      if (updater && updater->enabled()) {
-        updater->Start();
-      }
-    }
-  }
-
-  ready_.Signal();
-}
-
-ExtensionService* DesktopAndroidExtensionSystem::extension_service() {
-  return nullptr;
-}
-
-ManagementPolicy* DesktopAndroidExtensionSystem::management_policy() {
-  return management_policy_.get();
-}
-
-ServiceWorkerManager* DesktopAndroidExtensionSystem::service_worker_manager() {
-  return service_worker_manager_.get();
-}
-
-UserScriptManager* DesktopAndroidExtensionSystem::user_script_manager() {
-  return user_script_manager_.get();
-}
-
-StateStore* DesktopAndroidExtensionSystem::state_store() {
-  return nullptr;
-}
-
-StateStore* DesktopAndroidExtensionSystem::rules_store() {
-  return nullptr;
-}
-
-StateStore* DesktopAndroidExtensionSystem::dynamic_user_scripts_store() {
-  return nullptr;
-}
-
-scoped_refptr<value_store::ValueStoreFactory>
-DesktopAndroidExtensionSystem::store_factory() {
-  return store_factory_;
-}
-
-QuotaService* DesktopAndroidExtensionSystem::quota_service() {
-  return quota_service_.get();
-}
-
-AppSorting* DesktopAndroidExtensionSystem::app_sorting() {
-  return app_sorting_.get();
-}
-
-const base::OneShotEvent& DesktopAndroidExtensionSystem::ready() const {
-  return ready_;
-}
-
-bool DesktopAndroidExtensionSystem::is_ready() const {
-  return ready_.is_signaled();
-}
-
-ContentVerifier* DesktopAndroidExtensionSystem::content_verifier() {
-  return nullptr;
-}
-
-std::unique_ptr<ExtensionSet>
-DesktopAndroidExtensionSystem::GetDependentExtensions(
-    const Extension* extension) {
-  return SharedModuleService::Get(browser_context_)
-      ->GetDependentExtensions(extension);
-}
-
-void DesktopAndroidExtensionSystem::InstallUpdate(
-    const std::string& extension_id,
-    const std::string& public_key,
-    const base::FilePath& temp_dir,
-    bool install_immediately,
-    InstallUpdateCallback install_update_callback) {
-  NOTREACHED();
-}
-
-void DesktopAndroidExtensionSystem::PerformActionBasedOnOmahaAttributes(
-    const std::string& extension_id,
-    const base::Value::Dict& attributes) {
-  NOTREACHED();
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.h b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.h
deleted file mode 100644
index 1212d61..0000000
--- a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.h
+++ /dev/null
@@ -1,146 +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_EXTENSIONS_DESKTOP_ANDROID_DESKTOP_ANDROID_EXTENSION_SYSTEM_H_
-#define CHROME_BROWSER_EXTENSIONS_DESKTOP_ANDROID_DESKTOP_ANDROID_EXTENSION_SYSTEM_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/one_shot_event.h"
-#include "extensions/browser/extension_registrar.h"
-#include "extensions/browser/extension_system.h"
-
-#if !BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS)
-#error "This file is only used for the experimental desktop-android build."
-#endif
-
-namespace base {
-class FilePath;
-}
-
-namespace content {
-class BrowserContext;
-}
-
-namespace value_store {
-class ValueStoreFactory;
-}
-
-namespace extensions {
-class AppSorting;
-class ChromeExtensionRegistrarDelegate;
-class ExtensionSystemProvider;
-class ManagementPolicy;
-
-////////////////////////////////////////////////////////////////////////////////
-// S  T  O  P
-// ALL THIS CODE WILL BE DELETED.
-// THINK TWICE (OR THRICE) BEFORE ADDING MORE.
-//
-// The details:
-// This is part of an experimental desktop-android build and allows us to
-// bootstrap the extension system by incorporating a lightweight extensions
-// runtime into the chrome binary. This allows us to do things like load
-// extensions in tests and exercise code in these builds without needing to have
-// the entirety of the //chrome/browser/extensions system either compiled and
-// implemented (which is a massive undertaking) or gracefully if-def'd out
-// (which is a massive amount of technical debt).
-// This approach, by comparison, allows us to have a minimal interface in the
-// chrome browser that mostly relies on the top-level //extensions layer, along
-// with small bits of the //chrome code that compile cleanly on the
-// experimental desktop-android build.
-//
-// This entire class should go away. Instead of adding new functionality here,
-// it should be added in a location that can be shared across desktop-android
-// and other desktop builds. In practice, this means:
-// * Pulling the code up to //extensions. If it can be cleanly segmented from
-//   the //chrome layer, this is preferable. It gets cleanly included across
-//   all builds, encourages proper separation of concerns, and reduces the
-//   interdependency between features.
-// * Including the functionality in the desktop-android build. This can be done
-//   for //chrome sources that do not have any dependencies on areas that
-//   cannot be included in desktop-android (such as dependencies on `Browser`
-//   or native UI code).
-//
-// TODO(https://crbug.com/356905053): Delete this class once desktop-android
-// properly leverages the extension system.
-////////////////////////////////////////////////////////////////////////////////
-class DesktopAndroidExtensionSystem : public ExtensionSystem {
- public:
-  using InstallUpdateCallback = ExtensionSystem::InstallUpdateCallback;
-  explicit DesktopAndroidExtensionSystem(
-      content::BrowserContext* browser_context);
-
-  DesktopAndroidExtensionSystem(const DesktopAndroidExtensionSystem&) = delete;
-  DesktopAndroidExtensionSystem& operator=(
-      const DesktopAndroidExtensionSystem&) = delete;
-
-  ~DesktopAndroidExtensionSystem() override;
-
-  // Returns the singleton instance of the ExtensionSystemProvider to construct
-  // the DesktopAndroidExtensionSystem.
-  static ExtensionSystemProvider* GetFactory();
-
-  // KeyedService implementation:
-  void Shutdown() override;
-
-  // DO NOT ADD MORE METHODS HERE.
-  // Calling methods directly on DesktopAndroidExtensionSystem results in code
-  // that is not portable between different OSes and is also incompatible with
-  // unit tests (which may use test versions of the ExtensionSystem).
-
-  // ExtensionSystem implementation:
-  void InitForRegularProfile(bool extensions_enabled) override;
-  ExtensionService* extension_service() override;
-  ManagementPolicy* management_policy() override;
-  ServiceWorkerManager* service_worker_manager() override;
-  UserScriptManager* user_script_manager() override;
-  StateStore* state_store() override;
-  StateStore* rules_store() override;
-  StateStore* dynamic_user_scripts_store() override;
-  scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
-  QuotaService* quota_service() override;
-  AppSorting* app_sorting() override;
-  const base::OneShotEvent& ready() const override;
-  bool is_ready() const override;
-  ContentVerifier* content_verifier() override;
-  std::unique_ptr<ExtensionSet> GetDependentExtensions(
-      const Extension* extension) override;
-  void InstallUpdate(const std::string& extension_id,
-                     const std::string& public_key,
-                     const base::FilePath& temp_dir,
-                     bool install_immediately,
-                     InstallUpdateCallback install_update_callback) override;
-  void PerformActionBasedOnOmahaAttributes(
-      const std::string& extension_id,
-      const base::Value::Dict& attributes) override;
-
- private:
-  raw_ptr<content::BrowserContext> browser_context_;  // Not owned.
-
-  std::unique_ptr<ServiceWorkerManager> service_worker_manager_;
-  std::unique_ptr<QuotaService> quota_service_;
-  std::unique_ptr<UserScriptManager> user_script_manager_;
-  std::unique_ptr<AppSorting> app_sorting_;
-  std::unique_ptr<ManagementPolicy> management_policy_;
-
-  scoped_refptr<value_store::ValueStoreFactory> store_factory_;
-
-  std::unique_ptr<ChromeExtensionRegistrarDelegate> registrar_delegate_;
-  raw_ptr<ExtensionRegistrar> registrar_;  // Not owned
-
-  // Signaled when the extension system has completed its startup tasks.
-  base::OneShotEvent ready_;
-
-  base::WeakPtrFactory<DesktopAndroidExtensionSystem> weak_factory_{this};
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_DESKTOP_ANDROID_DESKTOP_ANDROID_EXTENSION_SYSTEM_H_
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc
index 08381f4..42df3b8c 100644
--- a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc
+++ b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc
@@ -9,10 +9,10 @@
 
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h"
+#include "chrome/browser/extensions/chrome_extension_system_factory.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/extensions/chrome_extensions_browser_api_provider.h"
 #include "chrome/browser/extensions/desktop_android/desktop_android_extension_host_delegate.h"
-#include "chrome/browser/extensions/desktop_android/desktop_android_extension_system.h"
 #include "chrome/browser/extensions/desktop_android/desktop_android_runtime_api_delegate.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/profiles/profile.h"
@@ -281,7 +281,7 @@
 
 ExtensionSystemProvider*
 DesktopAndroidExtensionsBrowserClient::GetExtensionSystemFactory() {
-  return DesktopAndroidExtensionSystem::GetFactory();
+  return ChromeExtensionSystemFactory::GetInstance();
 }
 
 void DesktopAndroidExtensionsBrowserClient::
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browsertest.cc b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browsertest.cc
index 12ca490..c32fe98 100644
--- a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browsertest.cc
+++ b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
-#include "chrome/browser/extensions/desktop_android/desktop_android_extension_system.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "chrome/test/base/android/android_browser_test.h"
 #include "chrome/test/base/chrome_test_utils.h"
diff --git a/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc b/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc
index 1de80f9b..38160e372 100644
--- a/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc
+++ b/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc
@@ -8,6 +8,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/extensions/blocklist_factory.h"
 #include "chrome/browser/extensions/chrome_extension_cookies_factory.h"
+#include "chrome/browser/extensions/chrome_extension_system_factory.h"
 #include "chrome/browser/extensions/component_loader_factory.h"
 #include "chrome/browser/extensions/corrupted_extension_reinstaller_factory.h"
 #include "chrome/browser/extensions/cws_info_service_factory.h"
@@ -28,7 +29,6 @@
 #include "chrome/browser/extensions/account_extension_tracker.h"
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/chrome_app_icon_service_factory.h"
-#include "chrome/browser/extensions/chrome_extension_system_factory.h"
 #include "chrome/browser/extensions/extension_action_dispatcher.h"
 #include "chrome/browser/extensions/extension_error_controller_factory.h"
 #include "chrome/browser/extensions/extension_garbage_collector_factory.h"
@@ -56,6 +56,7 @@
               "EnsureChromeBrowserContextKeyedServiceFactoriesBuilt");
   extensions::BlocklistFactory::GetInstance();
   extensions::ChromeExtensionCookiesFactory::GetInstance();
+  extensions::ChromeExtensionSystemFactory::GetInstance();
   extensions::ComponentLoaderFactory::GetInstance();
   extensions::CorruptedExtensionReinstallerFactory::GetInstance();
   extensions::CWSInfoServiceFactory::GetInstance();
@@ -81,7 +82,6 @@
   extensions::ExtensionErrorControllerFactory::GetInstance();
   extensions::ExtensionGarbageCollectorFactory::GetInstance();
   extensions::ExtensionGCMAppHandler::GetFactoryInstance();
-  extensions::ChromeExtensionSystemFactory::GetInstance();
   extensions::ManifestV2ExperimentManager::GetFactory();
   extensions::MenuManagerFactory::GetInstance();
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/feedback/BUILD.gn b/chrome/browser/feedback/BUILD.gn
index 284054d..b2a9d75 100644
--- a/chrome/browser/feedback/BUILD.gn
+++ b/chrome/browser/feedback/BUILD.gn
@@ -101,6 +101,7 @@
       "//chrome/browser/crash_upload_list",
       "//chrome/browser/devtools",
       "//chrome/browser/extensions",
+      "//chrome/browser/first_party_sets",
       "//chrome/browser/google",
       "//chrome/browser/profiles:profile",
       "//chrome/browser/sync",
diff --git a/chrome/browser/first_party_sets/BUILD.gn b/chrome/browser/first_party_sets/BUILD.gn
index b24649fd..48b16b2a 100644
--- a/chrome/browser/first_party_sets/BUILD.gn
+++ b/chrome/browser/first_party_sets/BUILD.gn
@@ -15,6 +15,7 @@
   sources = [
     "first_party_sets_overrides_policy_handler.cc",
     "first_party_sets_overrides_policy_handler.h",
+    "first_party_sets_policy_service.h",
     "first_party_sets_pref_names.cc",
     "first_party_sets_pref_names.h",
     "scoped_mock_first_party_sets_handler.cc",
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index b27cca2..fa61af4 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -186,6 +186,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "android-adaptive-frame-rate",
+    "owners": [ "boliu@chromium.org", "//components/viz/OWNERS" ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "android-app-integration",
     "owners": [ "gangwu@chromium.org", "chrome-mobile-search@google.com" ],
     "expiry_milestone": 150
@@ -7670,15 +7675,6 @@
     "expiry_milestone": 141
   },
   {
-    "name": "privacy-sandbox-privacy-policy",
-    "owners": [
-      "jacobstanley@google.com",
-      "chrstne@google.com",
-      "koilos@google.com"
-    ],
-    "expiry_milestone": 136
-  },
-  {
     "name": "probabilistic-memory-saver",
     "owners": ["chrome-performance-ui-team@google.com"],
     "expiry_milestone": 125
@@ -8121,6 +8117,11 @@
       "expiry_milestone": 137
   },
   {
+    "name": "report-notification-content-detection-data",
+    "owners": ["skrakowi@chromium.org", "chrome-counter-abuse-alerts@google.com"],
+    "expiry_milestone": 143
+  },
+  {
     "name": "reset-audio-selection-improvement-pref",
     "owners": [ "zhangwenyu@google.com", "cros-device-enablement@google.com" ],
     "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index afb4cb4..9e03a2f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -95,6 +95,15 @@
     "extensions and will be removed in the future.";
 #endif
 
+#if BUILDFLAG(IS_ANDROID)
+const char kAndroidAdaptiveFrameRateName[] =
+    "Android Adaptive Refresh Rate features";
+const char kAndroidAdaptiveFrameRateDescription[] =
+    "Enable adaptive  refresh rate features on supported devices. Feature "
+    "include lowering frame rate for low speed scroll. Has no effect if device "
+    "does not support adaptive refresh rate.";
+#endif
+
 const char kAndroidAppIntegrationName[] = "Integrate with Android App Search";
 const char kAndroidAppIntegrationDescription[] =
     "If enabled, allows Chrome to integrate with the Android App Search.";
@@ -3235,6 +3244,12 @@
 const char kPermissionSiteSettingsRadioButtonDescription[] =
     "Enables radio buttons for permissions in SiteSettings";
 
+const char kReportNotificationContentDetectionDataName[] =
+    "Option to report notifications to Google";
+const char kReportNotificationContentDetectionDataDescription[] =
+    "Enables reporting a notification's contents to Google, when the user taps "
+    "the `Report` button on the notification.";
+
 const char kShowRelatedWebsiteSetsPermissionGrantsName[] =
     "Show permission grants from Related Website Sets";
 const char kShowRelatedWebsiteSetsPermissionGrantsDescription[] =
@@ -3334,12 +3349,6 @@
 const char kPrivacySandboxInternalsDescription[] =
     "Enables the chrome://privacy-sandbox-internals debugging page.";
 
-const char kPrivacySandboxPrivacyPolicyName[] =
-    "Privacy Sandbox Privacy Policy";
-const char kPrivacySandboxPrivacyPolicyDescription[] =
-    "Enables the Privacy Policy link to be displayed on the Privacy Sandbox "
-    "Consent dialog, subject to regional availability.";
-
 const char kProtectedAudiencesConsentedDebugTokenName[] =
     "Protected Audiences Consented Debug Token";
 const char kProtectedAudiencesConsentedDebugTokenDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 77e9517..2ce6ec7 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -77,6 +77,11 @@
 extern const char kAllowLegacyMV2ExtensionsName[];
 extern const char kAllowLegacyMV2ExtensionsDescription[];
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+        //
+#if BUILDFLAG(IS_ANDROID)
+extern const char kAndroidAdaptiveFrameRateName[];
+extern const char kAndroidAdaptiveFrameRateDescription[];
+#endif
 
 extern const char kAndroidAppIntegrationName[];
 extern const char kAndroidAppIntegrationDescription[];
@@ -1871,6 +1876,9 @@
 extern const char kPermissionSiteSettingsRadioButtonName[];
 extern const char kPermissionSiteSettingsRadioButtonDescription[];
 
+extern const char kReportNotificationContentDetectionDataName[];
+extern const char kReportNotificationContentDetectionDataDescription[];
+
 extern const char kShowRelatedWebsiteSetsPermissionGrantsName[];
 extern const char kShowRelatedWebsiteSetsPermissionGrantsDescription[];
 
@@ -1928,9 +1936,6 @@
 extern const char kPrivacySandboxInternalsName[];
 extern const char kPrivacySandboxInternalsDescription[];
 
-extern const char kPrivacySandboxPrivacyPolicyName[];
-extern const char kPrivacySandboxPrivacyPolicyDescription[];
-
 extern const char kProtectedAudiencesConsentedDebugTokenName[];
 extern const char kProtectedAudiencesConsentedDebugTokenDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 752a5909..fd0dc48 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -402,7 +402,6 @@
     &privacy_sandbox::kPrivacySandboxRelatedWebsiteSetsUi,
     &privacy_sandbox::kPrivacySandboxSettings4,
     &privacy_sandbox::kPrivacySandboxAdTopicsContentParity,
-    &privacy_sandbox::kPrivacySandboxPrivacyPolicy,
     &privacy_sandbox::kPrivacySandboxSentimentSurvey,
     &privacy_sandbox::kPrivacySandboxCctAdsNoticeSurvey,
     &privacy_sandbox::kTrackingProtectionUserBypassPwa,
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 0a217812..e92a99a 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
@@ -176,8 +176,8 @@
     public static final String ANDROID_KEYBOARD_A11Y = "AndroidKeyboardA11y";
     public static final String ANDROID_META_CLICK_HISTORY_NAVIGATION =
             "AndroidMetaClickHistoryNavigation";
-    public static final String ANDROID_NATIVE_PAGES_IN_NEW_TAB = "AndroidNativePagesInNewTab";
     public static final String ANDROID_MINIMAL_UI_LARGE_SCREEN = "AndroidMinimalUiLargeScreen";
+    public static final String ANDROID_NATIVE_PAGES_IN_NEW_TAB = "AndroidNativePagesInNewTab";
     public static final String ANDROID_NO_VISIBLE_HINT_FOR_DIFFERENT_TLD =
             "AndroidNoVisibleHintForDifferentTLD";
     public static final String ANDROID_OMNIBOX_FOCUSED_NEW_TAB_PAGE =
@@ -468,7 +468,6 @@
             "PrivacySandboxCctAdsNoticeSurvey";
     public static final String PRIVACY_SANDBOX_NOTICE_ACTION_DEBOUNCING_ANDROID =
             "PrivacySandboxNoticeActionDebouncingAndroid";
-    public static final String PRIVACY_SANDBOX_PRIVACY_POLICY = "PrivacySandboxPrivacyPolicy";
     public static final String PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI =
             "PrivacySandboxRelatedWebsiteSetsUi";
     public static final String PRIVACY_SANDBOX_SENTIMENT_SURVEY = "PrivacySandboxSentimentSurvey";
@@ -967,6 +966,8 @@
             newMutableFlagWithSafeDefault(ANDROID_BOOKMARK_BAR, false);
     public static final MutableFlagWithSafeDefault sAndroidDumpOnScrollWithoutResource =
             newMutableFlagWithSafeDefault(ANDROID_DUMP_ON_SCROLL_WITHOUT_RESOURCE, false);
+    public static final MutableFlagWithSafeDefault sAndroidNativePagesInNewTab =
+            newMutableFlagWithSafeDefault(ANDROID_NATIVE_PAGES_IN_NEW_TAB, false);
     public static final MutableFlagWithSafeDefault sAndroidTabDeclutter =
             newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER, true);
     public static final MutableFlagWithSafeDefault sAndroidTabDeclutterArchiveAllButActiveTab =
@@ -1437,6 +1438,10 @@
 
     // Mutable*ParamWithSafeDefault instances.
     /* Alphabetical: */
+    public static final MutableBooleanParamWithSafeDefault
+            sAndroidNativePagesInNewTabDownloadsEnabled =
+            sAndroidNativePagesInNewTab.newBooleanParam(
+                    "android_native_pages_in_new_tab_downloads_enabled", true);
     public static final MutableBooleanParamWithSafeDefault sAndroidTabDeclutterArchiveEnabled =
             sAndroidTabDeclutter.newBooleanParam("android_tab_declutter_archive_enabled", true);
     public static final MutableIntParamWithSafeDefault sAndroidTabDeclutterArchiveTimeDeltaHours =
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn
index 628633d..463aaf32 100644
--- a/chrome/browser/glic/BUILD.gn
+++ b/chrome/browser/glic/BUILD.gn
@@ -125,6 +125,8 @@
     "host/host.h",
     "host/webui_contents_container.cc",
     "host/webui_contents_container.h",
+    "media/glic_media_integration.cc",
+    "media/glic_media_integration.h",
     "widget/browser_conditions.cc",
     "widget/browser_conditions.h",
     "widget/glic_modal_manager.cc",
@@ -164,6 +166,9 @@
     "//components/feature_engagement/public:feature_constants",
     "//components/guest_view/browser",
     "//components/language/core/common",
+    "//components/live_caption:constants",
+    "//components/live_caption:live_caption",
+    "//components/live_caption:utils",
     "//components/metrics_services_manager:metrics_services_manager",
     "//components/optimization_guide/proto:optimization_guide_proto",
     "//components/pdf/browser:browser",
@@ -288,6 +293,7 @@
     "glic_metrics_unittest.cc",
     "host/context/glic_screenshot_capturer_unittest.cc",
     "host/glic_cookie_synchronizer_unittest.cc",
+    "media/glic_media_integration_unittest.cc",
   ]
   deps = [
     ":glic",
@@ -297,10 +303,13 @@
     "//chrome/browser:global_features",
     "//chrome/browser/background:background",
     "//chrome/browser/background/glic",
+    "//chrome/browser/prefs:prefs",
     "//chrome/browser/status_icons:status_icons",
     "//chrome/browser/ui",
     "//chrome/common:chrome_features",
     "//chrome/test:test_support",
+    "//components/live_caption:constants",
+    "//components/live_caption:live_caption",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/chrome/browser/glic/browser_ui/glic_border_view.cc b/chrome/browser/glic/browser_ui/glic_border_view.cc
index 34d90a2..1f84d9a 100644
--- a/chrome/browser/glic/browser_ui/glic_border_view.cc
+++ b/chrome/browser/glic/browser_ui/glic_border_view.cc
@@ -225,10 +225,7 @@
   }
 
   bool IsGlicWindowShowing() const {
-    auto* service =
-        GlicKeyedServiceFactory::GetGlicKeyedService(browser_->GetProfile());
-    CHECK(service);
-    return service->window_controller().IsShowing();
+    return border_view_->GetGlicService()->window_controller().IsShowing();
   }
 
   bool IsTabInCurrentWindow(const content::WebContents* tab) const {
@@ -611,6 +608,12 @@
     SCOPED_CRASH_KEY_NUMBER("crbug-398319435", "first_rampdown",
                             TimeTicksToMicroseconds(first_ramp_down_frame_));
     base::debug::DumpWithoutCrashing();
+
+    // Gracefully handling the crash case in b/398319435 by
+    // closing(minimizing) the glic window.
+    // TODO(b/413442838): Add tests to reproduce the dump without crash and
+    // validate the solution.
+    GetGlicService()->window_controller().Close();
     return;
   }
   CHECK(compositor_->HasObserver(this));
@@ -714,6 +717,13 @@
          !has_hardware_acceleration_;
 }
 
+GlicKeyedService* GlicBorderView::GetGlicService() const {
+  auto* service =
+      GlicKeyedServiceFactory::GetGlicKeyedService(browser_->GetProfile());
+  CHECK(service);
+  return service;
+}
+
 BEGIN_METADATA(GlicBorderView)
 END_METADATA
 
diff --git a/chrome/browser/glic/browser_ui/glic_border_view.h b/chrome/browser/glic/browser_ui/glic_border_view.h
index 0dc33505..daa88381 100644
--- a/chrome/browser/glic/browser_ui/glic_border_view.h
+++ b/chrome/browser/glic/browser_ui/glic_border_view.h
@@ -26,6 +26,8 @@
 
 namespace glic {
 
+class GlicKeyedService;
+
 class GlicBorderView : public views::View,
                        public ui::CompositorAnimationObserver,
                        public ui::CompositorObserver,
@@ -126,6 +128,8 @@
 
   bool ForceSimplifiedShader() const;
 
+  GlicKeyedService* GetGlicService() const;
+
   // A utility class that subscribe to `GlicKeyedService` for various browser UI
   // status change.
   class BorderViewUpdater;
diff --git a/chrome/browser/glic/browser_ui/glic_button_controller.cc b/chrome/browser/glic/browser_ui/glic_button_controller.cc
index ea2a322..5a0ef458 100644
--- a/chrome/browser/glic/browser_ui/glic_button_controller.cc
+++ b/chrome/browser/glic/browser_ui/glic_button_controller.cc
@@ -55,10 +55,11 @@
   } else {
     bool detached = panel_state.kind == mojom::PanelState_Kind::kDetached;
     if (detached) {
-      glic_controller_delegate_->SetIcon(GlicVectorIconManager::GetVectorIcon(
-          IDR_GLIC_ATTACH_BUTTON_VECTOR_ICON));
+      glic_controller_delegate_->SetGlicIcon(
+          GlicVectorIconManager::GetVectorIcon(
+              IDR_GLIC_ATTACH_BUTTON_VECTOR_ICON));
     } else {
-      glic_controller_delegate_->SetIcon(
+      glic_controller_delegate_->SetGlicIcon(
           GlicVectorIconManager::GetVectorIcon(IDR_GLIC_BUTTON_VECTOR_ICON));
     }
     UpdateShowState(detached);
@@ -75,7 +76,7 @@
   // If the glic window is detached, we want to show the re-attach icon
   // regardless of glic enabling/pinned state.
   if (detached && !GlicWindowController::AlwaysDetached()) {
-    glic_controller_delegate_->SetShowState(true);
+    glic_controller_delegate_->SetGlicShowState(true);
     return;
   }
 
@@ -86,9 +87,9 @@
 
   if (is_enabled_for_profile && is_pinned_to_tabstrip) {
     glic_keyed_service_->TryPreload();
-    glic_controller_delegate_->SetShowState(true);
+    glic_controller_delegate_->SetGlicShowState(true);
   } else {
-    glic_controller_delegate_->SetShowState(false);
+    glic_controller_delegate_->SetGlicShowState(false);
   }
 }
 
diff --git a/chrome/browser/glic/browser_ui/glic_button_controller_delegate.h b/chrome/browser/glic/browser_ui/glic_button_controller_delegate.h
index 3a6560fa..74fda935 100644
--- a/chrome/browser/glic/browser_ui/glic_button_controller_delegate.h
+++ b/chrome/browser/glic/browser_ui/glic_button_controller_delegate.h
@@ -18,10 +18,10 @@
   virtual ~GlicButtonControllerDelegate() = default;
 
   // Set the show state of the button
-  virtual void SetShowState(bool show) = 0;
+  virtual void SetGlicShowState(bool show) = 0;
 
   // Sets the icon of the button
-  virtual void SetIcon(const gfx::VectorIcon& icon) = 0;
+  virtual void SetGlicIcon(const gfx::VectorIcon& icon) = 0;
 };
 
 }  // namespace glic
diff --git a/chrome/browser/glic/browser_ui/glic_button_controller_unittest.cc b/chrome/browser/glic/browser_ui/glic_button_controller_unittest.cc
index 5ac4817..c90cce1 100644
--- a/chrome/browser/glic/browser_ui/glic_button_controller_unittest.cc
+++ b/chrome/browser/glic/browser_ui/glic_button_controller_unittest.cc
@@ -51,8 +51,8 @@
 class MockGlicButtonControllerDelegate
     : public glic::GlicButtonControllerDelegate {
  public:
-  void SetShowState(bool show) override { show_state_ = show; }
-  void SetIcon(const gfx::VectorIcon& icon) override { icon_ = &icon; }
+  void SetGlicShowState(bool show) override { show_state_ = show; }
+  void SetGlicIcon(const gfx::VectorIcon& icon) override { icon_ = &icon; }
 
   bool show_state() const { return show_state_; }
   const gfx::VectorIcon* icon() const { return icon_; }
diff --git a/chrome/browser/glic/host/context/glic_page_context_fetcher.cc b/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
index ded5c5e..dd60eaf 100644
--- a/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
+++ b/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/content_extraction/inner_text.h"
 #include "chrome/browser/glic/host/context/glic_tab_data.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
+#include "chrome/browser/glic/media/glic_media_integration.h"
 #include "components/favicon/content/content_favicon_driver.h"
 #include "components/optimization_guide/content/browser/page_content_proto_provider.h"
 #include "components/pdf/browser/pdf_document_helper.h"
@@ -161,6 +162,20 @@
     inner_text_done_ = true;
   }
 
+  // Get the media context if we'll have somewhere to store it.
+  if (auto* media_integration =
+          options.include_annotated_page_content
+              ? GlicMediaIntegration::GetFor(web_contents())
+              : nullptr) {
+    media_integration->ComputeContext(
+        web_contents(),
+        /*max_size_bytes_=*/20000,
+        base::BindOnce(&GlicPageContextFetcher::ReceivedMediaContext,
+                       GetWeakPtr()));
+  } else {
+    media_context_done_ = true;
+  }
+
   pdf_done_ = true;  // Will not fetch PDF contents by default.
   if (options.include_pdf) {
     bool is_pdf_document =
@@ -206,6 +221,13 @@
   RunCallbackIfComplete();
 }
 
+void GlicPageContextFetcher::ReceivedMediaContext(
+    const std::string& media_context) {
+  media_context_done_ = true;
+  media_context_ = media_context;
+  RunCallbackIfComplete();
+}
+
 void GlicPageContextFetcher::GetTabScreenshot(
     content::WebContents& web_contents) {
   // TODO(crbug.com/378937313): Finish this provisional implementation.
@@ -281,9 +303,10 @@
 
 void GlicPageContextFetcher::RunCallbackIfComplete() {
   // Continue only if the primary page changed or work is complete.
-  bool work_complete = (screenshot_done_ && inner_text_done_ &&
-                        annotated_page_content_done_ && pdf_done_) ||
-                       primary_page_changed_;
+  bool work_complete =
+      (screenshot_done_ && inner_text_done_ && annotated_page_content_done_ &&
+       pdf_done_ && media_context_done_) ||
+      primary_page_changed_;
   if (!work_complete) {
     return;
   }
@@ -330,6 +353,19 @@
 
     if (annotated_page_content_result_) {
       auto annotated_page_data = mojom::AnnotatedPageData::New();
+
+      if (media_context_.length() > 0) {
+        optimization_guide::proto::ContentNode* media_node =
+            annotated_page_content_result_->proto.mutable_root_node()
+                ->add_children_nodes();
+        media_node->mutable_content_attributes()->set_attribute_type(
+            optimization_guide::proto::CONTENT_ATTRIBUTE_TEXT);
+        media_node->mutable_content_attributes()
+            ->mutable_text_data()
+            ->set_text_content(std::move(media_context_));
+        media_context_.clear();
+      }
+
       annotated_page_data->annotated_page_content =
           mojo_base::ProtoWrapper(annotated_page_content_result_->proto);
 
diff --git a/chrome/browser/glic/host/context/glic_page_context_fetcher.h b/chrome/browser/glic/host/context/glic_page_context_fetcher.h
index 78b1d721..d974cf0 100644
--- a/chrome/browser/glic/host/context/glic_page_context_fetcher.h
+++ b/chrome/browser/glic/host/context/glic_page_context_fetcher.h
@@ -56,6 +56,7 @@
   void ReceivedPdfBytes(pdf::mojom::PdfListener_GetPdfBytesStatus status,
                         const std::vector<uint8_t>& pdf_bytes,
                         uint32_t page_count);
+  void ReceivedMediaContext(const std::string& media_context);
 
   base::WeakPtr<GlicPageContextFetcher> GetWeakPtr() {
     return weak_ptr_factory_.GetWeakPtr();
@@ -72,6 +73,7 @@
   bool inner_text_done_ = false;
   bool pdf_done_ = false;
   bool annotated_page_content_done_ = false;
+  bool media_context_done_ = false;
   // Whether the primary page has changed since context fetching began.
   bool primary_page_changed_ = false;
   url::Origin pdf_origin_;
@@ -84,6 +86,7 @@
   std::optional<optimization_guide::AIPageContentResult>
       annotated_page_content_result_;
   base::TimeTicks start_time_;
+  std::string media_context_;
 
   base::WeakPtrFactory<GlicPageContextFetcher> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/glic/host/glic.mojom b/chrome/browser/glic/host/glic.mojom
index 16e5403..001fd1b3 100644
--- a/chrome/browser/glic/host/glic.mojom
+++ b/chrome/browser/glic/host/glic.mojom
@@ -166,8 +166,8 @@
   string email;
   // The user's given name.
   string given_name;
-  // Whether the profile or browser is managed.
-  // See `policy::ManagementService::IsManaged()`.
+  // Whether the profile's signed-in account is a managed account.
+  // See `policy::ManagementService::IsAccountManaged()`.
   bool is_managed;
 };
 
diff --git a/chrome/browser/glic/host/glic_page_handler.cc b/chrome/browser/glic/host/glic_page_handler.cc
index b402ade..dd1bc54 100644
--- a/chrome/browser/glic/host/glic_page_handler.cc
+++ b/chrome/browser/glic/host/glic_page_handler.cc
@@ -550,7 +550,8 @@
         base::UTF16ToUTF8(entry->GetLocalProfileName());
     policy::ManagementService* management_service =
         policy::ManagementServiceFactory::GetForProfile(profile_);
-    result->is_managed = management_service && management_service->IsManaged();
+    result->is_managed =
+        management_service && management_service->IsAccountManaged();
     std::move(callback).Run(std::move(result));
   }
 
diff --git a/chrome/browser/glic/host/guest_util.cc b/chrome/browser/glic/host/guest_util.cc
index d3217f2a..ac664f0 100644
--- a/chrome/browser/glic/host/guest_util.cc
+++ b/chrome/browser/glic/host/guest_util.cc
@@ -65,14 +65,9 @@
   return url::Origin::Create(GetGuestURL());
 }
 
-bool IsGlicWebUI(content::WebContents* web_contents) {
-  if (!web_contents) {
-    return false;
-  }
-  if (web_contents->GetLastCommittedURL() != chrome::kChromeUIGlicURL) {
-    return false;
-  }
-  return true;
+bool IsGlicWebUI(const content::WebContents* web_contents) {
+  return web_contents &&
+         web_contents->GetLastCommittedURL() == chrome::kChromeUIGlicURL;
 }
 
 bool OnGuestAdded(content::WebContents* guest_contents) {
diff --git a/chrome/browser/glic/host/guest_util.h b/chrome/browser/glic/host/guest_util.h
index b3bc578c..463b438e 100644
--- a/chrome/browser/glic/host/guest_util.h
+++ b/chrome/browser/glic/host/guest_util.h
@@ -18,7 +18,7 @@
 url::Origin GetGuestOrigin();
 
 // Returns true if `web_contents` contains the Glic WebUI application.
-bool IsGlicWebUI(content::WebContents* web_contents);
+bool IsGlicWebUI(const content::WebContents* web_contents);
 
 // If `guest_contents` is the glic guest, do glic-specific setup and return
 // true, otherwise return false.
diff --git a/chrome/browser/glic/media/OWNERS b/chrome/browser/glic/media/OWNERS
new file mode 100644
index 0000000..bb19ba2
--- /dev/null
+++ b/chrome/browser/glic/media/OWNERS
@@ -0,0 +1,4 @@
+liberato@chromium.org
+steimel@chromium.org
+muyaoxu@google.com
+yrw@chromium.org
diff --git a/chrome/browser/glic/media/glic_media_integration.cc b/chrome/browser/glic/media/glic_media_integration.cc
new file mode 100644
index 0000000..f2f7064
--- /dev/null
+++ b/chrome/browser/glic/media/glic_media_integration.cc
@@ -0,0 +1,140 @@
+// Copyright 2025 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/media/glic_media_integration.h"
+
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "base/supports_user_data.h"
+#include "chrome/browser/accessibility/live_caption/live_caption_controller_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/live_caption/caption_controller_base.h"
+#include "components/live_caption/caption_util.h"
+#include "components/live_caption/live_caption_controller.h"
+#include "components/live_caption/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/web_contents.h"
+#include "media/base/media_switches.h"
+
+namespace {
+
+constexpr char kGlicMediaIntegrationKey[] = "GlicMediaIntegration";
+
+class GlicMediaIntegrationImpl : public glic::GlicMediaIntegration,
+                                 public base::SupportsUserData::Data {
+ public:
+  explicit GlicMediaIntegrationImpl(Profile*);
+  ~GlicMediaIntegrationImpl() override = default;
+
+  void ComputeContext(content::WebContents*,
+                      size_t max_size_bytes,
+                      ContextCallback) override;
+
+  void OnTranscription(const media::SpeechRecognitionResult&);
+
+ protected:
+  // Trim `context_` to `max_size_bytes_`.
+  void TrimContext();
+
+  raw_ptr<Profile> profile_;
+  std::string context_;
+  size_t max_size_bytes_ = 20000;
+};
+
+class CaptionListenerImpl : public captions::CaptionControllerBase::Listener {
+ public:
+  explicit CaptionListenerImpl(Profile* profile) : profile_(profile) {}
+  ~CaptionListenerImpl() override = default;
+
+  bool OnTranscription(captions::CaptionBubbleContext*,
+                       const media::SpeechRecognitionResult& result) override {
+    // could also wp callback, which is probably clearer.
+    auto* media_integration = static_cast<GlicMediaIntegrationImpl*>(
+        profile_->GetUserData(kGlicMediaIntegrationKey));
+
+    if (!media_integration) {
+      return false;
+    }
+
+    media_integration->OnTranscription(result);
+    return true;
+  }
+
+  void OnAudioStreamEnd(captions::CaptionBubbleContext*) override {}
+  void OnLanguageIdentificationEvent(
+      captions::CaptionBubbleContext*,
+      const media::mojom::LanguageIdentificationEventPtr&) override {}
+
+ private:
+  raw_ptr<Profile> profile_;
+};
+
+GlicMediaIntegrationImpl::GlicMediaIntegrationImpl(Profile* profile)
+    : profile_(profile) {
+  auto* lc = captions::LiveCaptionControllerFactory::GetForProfile(profile_);
+  lc->AddListener(std::make_unique<CaptionListenerImpl>(profile));
+
+  // For now, enable the pref if we get this far.  Do this after getting the
+  // Live Caption controller, since it resets the pref to false.
+  profile->GetPrefs()->SetBoolean(prefs::kHeadlessCaptionEnabled, true);
+}
+
+void GlicMediaIntegrationImpl::OnTranscription(
+    const media::SpeechRecognitionResult& result) {
+  if (!result.is_final) {
+    return;
+  }
+
+  context_ += result.transcription;
+  TrimContext();
+}
+
+void GlicMediaIntegrationImpl::ComputeContext(content::WebContents*,
+                                              size_t max_size_bytes,
+                                              ContextCallback cb) {
+  max_size_bytes_ = max_size_bytes;
+  TrimContext();
+  std::move(cb).Run(context_);
+}
+
+void GlicMediaIntegrationImpl::TrimContext() {
+  // Trim to `max_size`.  Note that we should utf8-trim, but this is easier.
+  if (size_t context_size = context_.length()) {
+    if (context_size > max_size_bytes_) {
+      // Remove the beginning of the context, leaving the end.
+      context_ = context_.substr(context_size - max_size_bytes_);
+    }
+  }
+}
+
+}  // namespace
+
+namespace glic {
+
+// static
+GlicMediaIntegration* GlicMediaIntegration::GetFor(content::WebContents* wc) {
+  // This should also check the pref, once it's not toggled automatically.
+  // We'll want to install a pref listener, and possibly clean up if the pref
+  // is switched off after construction.
+  if (!wc || !captions::IsHeadlessCaptionFeatureSupported()) {
+    return nullptr;
+  }
+
+  Profile* profile = Profile::FromBrowserContext(wc->GetBrowserContext());
+  if (!profile) {
+    return nullptr;
+  }
+
+  auto* data = static_cast<GlicMediaIntegrationImpl*>(
+      profile->GetUserData(kGlicMediaIntegrationKey));
+  if (!data) {
+    auto new_data = std::make_unique<GlicMediaIntegrationImpl>(profile);
+    data = new_data.get();
+    profile->SetUserData(kGlicMediaIntegrationKey, std::move(new_data));
+  }
+
+  return data;
+}
+
+}  // namespace glic
diff --git a/chrome/browser/glic/media/glic_media_integration.h b/chrome/browser/glic/media/glic_media_integration.h
new file mode 100644
index 0000000..be5ceeb6
--- /dev/null
+++ b/chrome/browser/glic/media/glic_media_integration.h
@@ -0,0 +1,37 @@
+// Copyright 2025 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_MEDIA_GLIC_MEDIA_INTEGRATION_H_
+#define CHROME_BROWSER_GLIC_MEDIA_GLIC_MEDIA_INTEGRATION_H_
+
+#include <string>
+
+#include "base/functional/callback.h"
+#include "chrome/browser/glic/host/glic.mojom.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace glic {
+
+class GlicMediaIntegration {
+ public:
+  using ContextCallback = base::OnceCallback<void(const std::string&)>;
+
+  GlicMediaIntegration() = default;
+  virtual ~GlicMediaIntegration() = default;
+
+  // May return null if no integration is needed.
+  static GlicMediaIntegration* GetFor(content::WebContents*);
+
+  // This may call back synchronously.
+  virtual void ComputeContext(content::WebContents*,
+                              size_t max_size_bytes,
+                              ContextCallback) = 0;
+};
+
+}  // namespace glic
+
+#endif  // CHROME_BROWSER_GLIC_MEDIA_GLIC_MEDIA_INTEGRATION_H_
diff --git a/chrome/browser/glic/media/glic_media_integration_unittest.cc b/chrome/browser/glic/media/glic_media_integration_unittest.cc
new file mode 100644
index 0000000..ae8f534f
--- /dev/null
+++ b/chrome/browser/glic/media/glic_media_integration_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2025 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/media/glic_media_integration.h"
+
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/accessibility/live_caption/live_caption_controller_factory.h"
+#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/live_caption/live_caption_controller.h"
+#include "components/live_caption/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/browser/web_contents.h"
+#include "media/base/media_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::WebContents;
+
+namespace glic {
+
+class GlicMediaIntegrationTest : public ChromeRenderViewHostTestHarness {
+ public:
+  void SetUp() override {
+    base::test::ScopedFeatureList features(media::kHeadlessLiveCaption);
+    ChromeRenderViewHostTestHarness::SetUp();
+    // Return a mock Live Caption controller.
+    auto controller = CreateLiveCaptionController();
+    live_caption_controller_ = controller.get();
+    captions::LiveCaptionControllerFactory::GetInstance()->SetTestingFactory(
+        web_contents()->GetBrowserContext(),
+        base::BindOnce(
+            [](std::unique_ptr<captions::LiveCaptionController> controller,
+               content::BrowserContext* context)
+                -> std::unique_ptr<KeyedService> {
+              return std::move(controller);
+            },
+            std::move(controller)));
+  }
+
+  void TearDown() override {
+    live_caption_controller_ = nullptr;
+    pref_registry_ = nullptr;
+    ChromeRenderViewHostTestHarness::TearDown();
+  }
+
+  // ChromeRenderViewHostTestHarness
+  std::unique_ptr<TestingProfile> CreateTestingProfile() override {
+    auto pref_service =
+        std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
+    pref_registry_ = pref_service->registry();
+    RegisterUserProfilePrefs(pref_registry_);
+    return TestingProfile::Builder()
+        .SetPrefService(std::move(pref_service))
+        .AddTestingFactories(GetTestingFactories())
+        .Build();
+  }
+
+  // Get the MediaIntegration instance, after doing some work to register prefs
+  GlicMediaIntegration* GetIntegration() {
+    scoped_feature_list_.emplace(media::kHeadlessLiveCaption);
+    return GlicMediaIntegration::GetFor(web_contents());
+  }
+
+  captions::LiveCaptionController* live_caption_controller() {
+    return live_caption_controller_;
+  }
+
+  PrefService* pref_service() {
+    return Profile::FromBrowserContext(web_contents()->GetBrowserContext())
+        ->GetPrefs();
+  }
+
+  bool get_headless_pref() {
+    return pref_service()->GetBoolean(prefs::kHeadlessCaptionEnabled);
+  }
+
+  std::unique_ptr<captions::LiveCaptionController>
+  CreateLiveCaptionController() {
+    return std::make_unique<captions::LiveCaptionController>(
+        pref_service(),
+        /*global_prefs=*/nullptr, "application_locale", browser_context(),
+        /*delegate=*/nullptr);
+  }
+
+ private:
+  TestingPrefServiceSimple pref_service_;
+  std::optional<base::test::ScopedFeatureList> scoped_feature_list_;
+  raw_ptr<captions::LiveCaptionController> live_caption_controller_ = nullptr;
+  raw_ptr<user_prefs::PrefRegistrySyncable> pref_registry_ = nullptr;
+};
+
+TEST_F(GlicMediaIntegrationTest, GetWithNullReturnsNull) {
+  // Make sure this doesn't crash.
+  EXPECT_EQ(GlicMediaIntegration::GetFor(nullptr), nullptr);
+}
+
+TEST_F(GlicMediaIntegrationTest, GetReturnsNullIfSwitchIsOff) {
+  EXPECT_EQ(GlicMediaIntegration::GetFor(web_contents()), nullptr);
+}
+
+TEST_F(GlicMediaIntegrationTest, GetReturnsNonNullIfSwitchIsOn) {
+  // Right now, this doesn't depend on the headless pref, but likely it should.
+  EXPECT_NE(GetIntegration(), nullptr);
+}
+
+TEST_F(GlicMediaIntegrationTest, ContextContainsTranscript) {
+  auto* integration = GetIntegration();
+
+  // Send the string in pieces, mixing final and non-final ones.
+  const std::string test_cap_1("ABC");
+  const std::string test_cap_2("DEF");
+  const std::string test_cap_3("XYZ");  // Should be ignored as non-final.
+  const std::string test_cap_4("GHIJ");
+  live_caption_controller()->DispatchTranscription(
+      nullptr, media::SpeechRecognitionResult(test_cap_1, /*is_final=*/true));
+  live_caption_controller()->DispatchTranscription(
+      nullptr, media::SpeechRecognitionResult(test_cap_2, /*is_final=*/true));
+  live_caption_controller()->DispatchTranscription(
+      nullptr, media::SpeechRecognitionResult(test_cap_3, /*is_final=*/false));
+  live_caption_controller()->DispatchTranscription(
+      nullptr, media::SpeechRecognitionResult(test_cap_4, /*is_final=*/true));
+
+  // Request a max length that's smaller than what we sent.
+  const size_t max_len =
+      test_cap_1.length() + test_cap_2.length() + test_cap_4.length() - 1;
+  std::string reported_cap;
+  base::MockCallback<GlicMediaIntegration::ContextCallback> cb;
+  EXPECT_CALL(cb, Run("BCDEFGHIJ"));
+  integration->ComputeContext(web_contents(), max_len, cb.Get());
+}
+
+TEST_F(GlicMediaIntegrationTest, HeadlessPrefTurnsOnAndOff) {
+  // Verify that the headless pref turns on with the integration, and turns
+  // back off the next time Live Caption starts.  This is temporary behavior.
+  EXPECT_FALSE(get_headless_pref());
+  GetIntegration();
+  EXPECT_TRUE(get_headless_pref());
+  auto controller = CreateLiveCaptionController();
+  EXPECT_FALSE(get_headless_pref());
+}
+
+}  // namespace glic
diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc
index ff10235..c7422800 100644
--- a/chrome/browser/history/history_browsertest.cc
+++ b/chrome/browser/history/history_browsertest.cc
@@ -1272,11 +1272,27 @@
 IN_PROC_BROWSER_TEST_P(HistoryVisitedLinksBrowserTest, GetSaltForSameOrigin) {
   constexpr char kOrigin[] = "foo.com";
   const GURL kUrl(embedded_https_test_server().GetURL(kOrigin, "/empty.html"));
+  int roundtrips = 5;
 
   // Obtain our expected salt value from the history service.
   history::HistoryService* history_service =
       HistoryServiceFactory::GetForProfile(browser()->profile(),
                                            ServiceAccessType::EXPLICIT_ACCESS);
+
+  // crbug.com/391985597: To obtain a salt from the `HistoryService`, the
+  // :visited links hashtable must have completed loading in data from the
+  // `HistoryDatabase`. Even though the `HistoryDatabase` is empty, on Windows
+  // and MacOS trybots, this test was flaky due to delays in switching from
+  // the DB to UI thread. To ensure that we can obtain our expected salt, we
+  // will run a few navigations which the test must wait for their completion
+  // to buy these trybots some more time to finish loading the table. (NOTE:
+  // this would traditionally be done with a waiter, but due to layering
+  // constraints, we cannot directly access the `(Partitioned)VisitedLink::
+  // TableBuilder` to be signaled once loading is complete.)
+  for (int i = 0; i < roundtrips; i++) {
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kUrl));
+  }
+
   std::optional<uint64_t> expected_salt =
       history_service->GetOrAddOriginSalt(url::Origin::Create(kUrl));
   ASSERT_TRUE(expected_salt.has_value());
@@ -1298,11 +1314,27 @@
 IN_PROC_BROWSER_TEST_P(HistoryVisitedLinksBrowserTest, AddSaltForCrossOrigin) {
   constexpr char kOrigin[] = "foo.com";
   const GURL kUrl(embedded_https_test_server().GetURL(kOrigin, "/empty.html"));
+  int roundtrips = 5;
 
   // Obtain our expected salt value for kOrigin from the history service.
   history::HistoryService* history_service =
       HistoryServiceFactory::GetForProfile(browser()->profile(),
                                            ServiceAccessType::EXPLICIT_ACCESS);
+
+  // crbug.com/391985597: To obtain a salt from the `HistoryService`, the
+  // :visited links hashtable must have completed loading in data from the
+  // `HistoryDatabase`. Even though the `HistoryDatabase` is empty, on Windows
+  // and MacOS trybots, this test was flaky due to delays in switching from
+  // the DB to UI thread. To ensure that we can obtain our expected salt, we
+  // will run a few navigations which the test must wait for their completion
+  // to buy these trybots some more time to finish loading the table. (NOTE:
+  // this would traditionally be done with a waiter, but due to layering
+  // constraints, we cannot directly access the `(Partitioned)VisitedLink::
+  // TableBuilder` to be signaled once loading is complete.)
+  for (int i = 0; i < roundtrips; i++) {
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kUrl));
+  }
+
   std::optional<uint64_t> expected_salt =
       history_service->GetOrAddOriginSalt(url::Origin::Create(kUrl));
   ASSERT_TRUE(expected_salt.has_value());
diff --git a/chrome/browser/image_decoder/BUILD.gn b/chrome/browser/image_decoder/BUILD.gn
index 839d4337..38e8b3c 100644
--- a/chrome/browser/image_decoder/BUILD.gn
+++ b/chrome/browser/image_decoder/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("//chrome/version.gni")
-
 source_set("image_decoder") {
   deps = [
     "//base",
@@ -27,10 +25,7 @@
     testonly = true
 
     configs += [ "//build/config:precompiled_headers" ]
-    defines = [
-      "HAS_OUT_OF_PROC_TEST_RUNNER",
-      "CHROME_VERSION_MAJOR=" + chrome_version_major,
-    ]
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
     deps = [
       ":image_decoder",
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc
index e4c0b2b5..7efbee9 100644
--- a/chrome/browser/media/webrtc/display_media_access_handler.cc
+++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -83,15 +83,13 @@
 
 #if !BUILDFLAG(IS_ANDROID)
 
+bool IsGlicWebUI(const content::WebContents* web_contents) {
 #if BUILDFLAG(ENABLE_GLIC)
-bool IsGlicWebUI(content::WebContents* web_contents) {
   return glic::IsGlicWebUI(web_contents);
-}
 #else
-bool IsGlicWebUI(content::WebContents* web_contents) {
   return false;
-}
 #endif
+}
 
 // If bypassing the media selection dialog is allowed for this request, this
 // returns the `DesktopMediaId` to use. Returns a null ID otherwise.
@@ -288,8 +286,7 @@
     }
   }
 
-  // The DISPLAY_MEDIA_SYSTEM_AUDIO / DISPLAY_VIDEO_CAPTURE_THIS_TAB settings
-  // are not supported on Android.
+  // Screen capture is not supported on Android.
 #if !BUILDFLAG(IS_ANDROID)
   HostContentSettingsMap* content_settings =
       HostContentSettingsMapFactory::GetForProfile(
diff --git a/chrome/browser/net/reporting_browsertest.cc b/chrome/browser/net/reporting_browsertest.cc
index bfa0d4c..1be0723 100644
--- a/chrome/browser/net/reporting_browsertest.cc
+++ b/chrome/browser/net/reporting_browsertest.cc
@@ -208,13 +208,9 @@
   ~ReportingBrowserTestMoreContextData() override = default;
 
   void SetUp() override {
-    if (GetParam()) {
-      scoped_feature_list_.InitAndEnableFeature(
-          blink::features::kCrashReportingAPIMoreContextData);
-    } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          blink::features::kCrashReportingAPIMoreContextData);
-    }
+    scoped_feature_list_.InitWithFeatureState(
+        blink::features::kCrashReportingAPIMoreContextData,
+        /*enabled=*/GetParam());
     BaseReportingBrowserTest::SetUp();
   }
 
diff --git a/chrome/browser/notifications/notification_display_service_impl.cc b/chrome/browser/notifications/notification_display_service_impl.cc
index d3519b21..a2d3922 100644
--- a/chrome/browser/notifications/notification_display_service_impl.cc
+++ b/chrome/browser/notifications/notification_display_service_impl.cc
@@ -169,6 +169,17 @@
     case NotificationOperation::kSettings:
       handler->OpenSettings(profile_, origin);
       break;
+    case NotificationOperation::kReportAsSafe:
+      handler->ReportNotificationAsSafe(notification_id, origin, profile_);
+      break;
+    case NotificationOperation::kReportWarnedAsSpam:
+      handler->ReportWarnedNotificationAsSpam(notification_id, origin,
+                                              profile_);
+      break;
+    case NotificationOperation::kReportUnwarnedAsSpam:
+      handler->ReportUnwarnedNotificationAsSpam(notification_id, origin,
+                                                profile_);
+      break;
   }
 }
 
diff --git a/chrome/browser/notifications/notification_handler.cc b/chrome/browser/notifications/notification_handler.cc
index 9fa2e2ea..0b721b39 100644
--- a/chrome/browser/notifications/notification_handler.cc
+++ b/chrome/browser/notifications/notification_handler.cc
@@ -38,3 +38,24 @@
   // to handle user interaction with it.
   NOTREACHED();
 }
+
+void NotificationHandler::ReportNotificationAsSafe(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  NOTREACHED();
+}
+
+void NotificationHandler::ReportWarnedNotificationAsSpam(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  NOTREACHED();
+}
+
+void NotificationHandler::ReportUnwarnedNotificationAsSpam(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  NOTREACHED();
+}
diff --git a/chrome/browser/notifications/notification_handler.h b/chrome/browser/notifications/notification_handler.h
index 5277ae6..d0faca3 100644
--- a/chrome/browser/notifications/notification_handler.h
+++ b/chrome/browser/notifications/notification_handler.h
@@ -70,6 +70,23 @@
 
   // Called when the settings page for the given origin has to be opened.
   virtual void OpenSettings(Profile* profile, const GURL& origin);
+
+  // Called when a user clicks to report a notification as safe.
+  virtual void ReportNotificationAsSafe(const std::string& notification_id,
+                                        const GURL& url,
+                                        Profile* profile);
+
+  // Called when a user clicks to report a warned notification as spam.
+  virtual void ReportWarnedNotificationAsSpam(
+      const std::string& notification_id,
+      const GURL& url,
+      Profile* profile);
+
+  // Called when a user clicks to report an unwarned notification as spam.
+  virtual void ReportUnwarnedNotificationAsSpam(
+      const std::string& notification_id,
+      const GURL& url,
+      Profile* profile);
 };
 
 #endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_HANDLER_H_
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc
index ac737f9..d3e07cf9 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -279,6 +279,66 @@
   test_is_suspicious_value_ = is_suspicious;
 }
 
+void NotificationPlatformBridgeAndroid::OnReportNotificationAsSafe(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& java_object,
+    std::string& notification_id,
+    std::string& origin,
+    std::string& profile_id,
+    jboolean incognito) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  CHECK(profile_manager);
+
+  profile_manager->LoadProfile(
+      GetProfileBaseNameFromProfileId(profile_id), incognito,
+      base::BindOnce(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
+                     NotificationOperation::kReportAsSafe,
+                     NotificationHandler::Type::WEB_PERSISTENT, GURL(origin),
+                     notification_id, std::nullopt /* action index */,
+                     std::nullopt /* reply */, std::nullopt /* by_user */,
+                     base::DoNothing()));
+}
+
+void NotificationPlatformBridgeAndroid::OnReportWarnedNotificationAsSpam(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& java_object,
+    std::string& notification_id,
+    std::string& origin,
+    std::string& profile_id,
+    jboolean incognito) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  CHECK(profile_manager);
+
+  profile_manager->LoadProfile(
+      GetProfileBaseNameFromProfileId(profile_id), incognito,
+      base::BindOnce(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
+                     NotificationOperation::kReportWarnedAsSpam,
+                     NotificationHandler::Type::WEB_PERSISTENT, GURL(origin),
+                     notification_id, std::nullopt /* action index */,
+                     std::nullopt /* reply */, std::nullopt /* by_user */,
+                     base::DoNothing()));
+}
+
+void NotificationPlatformBridgeAndroid::OnReportUnwarnedNotificationAsSpam(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& java_object,
+    std::string& notification_id,
+    std::string& origin,
+    std::string& profile_id,
+    jboolean incognito) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  CHECK(profile_manager);
+
+  profile_manager->LoadProfile(
+      GetProfileBaseNameFromProfileId(profile_id), incognito,
+      base::BindOnce(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
+                     NotificationOperation::kReportUnwarnedAsSpam,
+                     NotificationHandler::Type::WEB_PERSISTENT, GURL(origin),
+                     notification_id, std::nullopt /* action index */,
+                     std::nullopt /* reply */, std::nullopt /* by_user */,
+                     base::DoNothing()));
+}
+
 void NotificationPlatformBridgeAndroid::OnNotificationAlwaysAllowFromOrigin(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& java_object,
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.h b/chrome/browser/notifications/notification_platform_bridge_android.h
index a8e06fc..de5c7d7 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.h
+++ b/chrome/browser/notifications/notification_platform_bridge_android.h
@@ -93,6 +93,36 @@
       const base::android::JavaParamRef<jobject>& java_object,
       bool is_suspicious);
 
+  // Called by the Java implementation when the user decides they want to report
+  // their notification contents as safe to the server.
+  void OnReportNotificationAsSafe(
+      JNIEnv* env,
+      const jni_zero::JavaParamRef<jobject>& java_object,
+      std::string& notification_id,
+      std::string& origin,
+      std::string& profile_id,
+      jboolean incognito);
+
+  // Called by the Java implementation when the user decides they want to report
+  // their warned notification contents as spam to the server.
+  void OnReportWarnedNotificationAsSpam(
+      JNIEnv* env,
+      const jni_zero::JavaParamRef<jobject>& java_object,
+      std::string& notification_id,
+      std::string& origin,
+      std::string& profile_id,
+      jboolean incognito);
+
+  // Called by the Java implementation when the user decides they want to report
+  // their unwarned notification contents as spam to the server.
+  void OnReportUnwarnedNotificationAsSpam(
+      JNIEnv* env,
+      const jni_zero::JavaParamRef<jobject>& java_object,
+      std::string& notification_id,
+      std::string& origin,
+      std::string& profile_id,
+      jboolean incognito);
+
   // Called by the Java implementation when the user decides they no longer want
   // to receive warnings for suspicious notifications that come from `origin`.
   void OnNotificationAlwaysAllowFromOrigin(
diff --git a/chrome/browser/notifications/persistent_notification_handler.cc b/chrome/browser/notifications/persistent_notification_handler.cc
index 8376a0e..cb45922 100644
--- a/chrome/browser/notifications/persistent_notification_handler.cc
+++ b/chrome/browser/notifications/persistent_notification_handler.cc
@@ -16,8 +16,11 @@
 #include "chrome/browser/notifications/notification_permission_context.h"
 #include "chrome/browser/notifications/platform_notification_service_factory.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.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/permissions/notifications_engagement_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
@@ -26,12 +29,15 @@
 #include "components/permissions/permission_uma_util.h"
 #include "components/permissions/permission_util.h"
 #include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_constants.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "components/site_engagement/content/site_engagement_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_event_dispatcher.h"
 #include "content/public/browser/permission_controller.h"
 #include "content/public/browser/permission_descriptor_util.h"
 #include "content/public/browser/permission_result.h"
+#include "content/public/browser/platform_notification_context.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/common/persistent_notification_status.h"
 #include "third_party/blink/public/common/permissions/permission_utils.h"
 #include "url/gurl.h"
@@ -233,6 +239,74 @@
   NotificationCommon::OpenNotificationSettings(profile, origin);
 }
 
+void PersistentNotificationHandler::ReportNotificationAsSafe(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  OnMaybeReport(notification_id, url, profile, /*did_show_warning=*/true,
+                /*did_user_unsubscribe=*/false);
+}
+
+void PersistentNotificationHandler::ReportWarnedNotificationAsSpam(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  OnMaybeReport(notification_id, url, profile, /*did_show_warning=*/true,
+                /*did_user_unsubscribe=*/true);
+}
+
+void PersistentNotificationHandler::ReportUnwarnedNotificationAsSpam(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile) {
+  OnMaybeReport(notification_id, url, profile, /*did_show_warning=*/false,
+                /*did_user_unsubscribe=*/true);
+}
+
+void PersistentNotificationHandler::OnMaybeReport(
+    const std::string& notification_id,
+    const GURL& url,
+    Profile* profile,
+    bool did_show_warning,
+    bool did_user_unsubscribe) {
+  CHECK(profile);
+
+  // In case the data volume becomes excessive, logging should happen at a
+  // sampled rate. This rate is defined by the
+  // `kReportNotificationContentDetectionDataRate` feature parameter.
+  if (base::RandDouble() * 100 >
+      safe_browsing::kReportNotificationContentDetectionDataRate.Get()) {
+    return;
+  }
+
+  scoped_refptr<content::PlatformNotificationContext> notification_context =
+      profile->GetStoragePartitionForUrl(url)->GetPlatformNotificationContext();
+  if (!notification_context ||
+      !OptimizationGuideKeyedServiceFactory::GetForProfile(profile)) {
+    return;
+  }
+
+  blink::mojom::EngagementLevel engagement_level =
+      blink::mojom::EngagementLevel::NONE;
+  if (site_engagement::SiteEngagementService::Get(profile)) {
+    engagement_level = site_engagement::SiteEngagementService::Get(profile)
+                           ->GetEngagementLevel(url);
+  }
+
+  // Read notification data from database and upload as log to model quality
+  // service.
+  notification_context->ReadNotificationDataAndRecordInteraction(
+      notification_id, url,
+      content::PlatformNotificationContext::Interaction::NONE,
+      base::BindOnce(
+          &safe_browsing::SendNotificationContentDetectionDataToMQLSServer,
+          OptimizationGuideKeyedServiceFactory::GetForProfile(profile)
+              ->GetModelQualityLogsUploaderService()
+              ->GetWeakPtr(),
+          safe_browsing::NotificationContentDetectionMQLSMetadata(
+              did_show_warning, did_user_unsubscribe, engagement_level)));
+}
+
 #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
 
 PersistentNotificationHandler::NotificationKeepAliveState::
diff --git a/chrome/browser/notifications/persistent_notification_handler.h b/chrome/browser/notifications/persistent_notification_handler.h
index 1bcc269..5e57b4a 100644
--- a/chrome/browser/notifications/persistent_notification_handler.h
+++ b/chrome/browser/notifications/persistent_notification_handler.h
@@ -48,6 +48,15 @@
                base::OnceClosure completed_closure) override;
   void DisableNotifications(Profile* profile, const GURL& origin) override;
   void OpenSettings(Profile* profile, const GURL& origin) override;
+  void ReportNotificationAsSafe(const std::string& notification_id,
+                                const GURL& url,
+                                Profile* profile) override;
+  void ReportWarnedNotificationAsSpam(const std::string& notification_id,
+                                      const GURL& url,
+                                      Profile* profile) override;
+  void ReportUnwarnedNotificationAsSpam(const std::string& notification_id,
+                                        const GURL& url,
+                                        Profile* profile) override;
 
  private:
   void OnCloseCompleted(Profile* profile,
@@ -57,6 +66,11 @@
                         const std::string& notification_id,
                         base::OnceClosure completed_closure,
                         content::PersistentNotificationStatus status);
+  void OnMaybeReport(const std::string& notification_id,
+                     const GURL& url,
+                     Profile* profile,
+                     bool did_show_warning,
+                     bool did_user_unsubscribe);
 
 #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
   class NotificationKeepAliveState {
diff --git a/chrome/browser/notifications/persistent_notification_handler_unittest.cc b/chrome/browser/notifications/persistent_notification_handler_unittest.cc
index 0e34efd2..d42c3a1 100644
--- a/chrome/browser/notifications/persistent_notification_handler_unittest.cc
+++ b/chrome/browser/notifications/persistent_notification_handler_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
 #include "base/task/thread_pool.h"
+#include "base/test/test_future.h"
 #include "build/build_config.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
@@ -20,16 +21,26 @@
 #include "chrome/browser/notifications/notification_permission_context.h"
 #include "chrome/browser/notifications/platform_notification_service_factory.h"
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
+#include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.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/safe_browsing/notification_content_detection/mock_notification_content_detection_service.h"
 #include "chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_service_factory.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/optimization_guide/core/model_quality/test_model_quality_logs_uploader_service.h"
 #include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_constants.h"
 #include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_service.h"
 #include "components/safe_browsing/content/browser/notification_content_detection/test_model_observer_tracker.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/browser/notification_database_data.h"
 #include "content/public/browser/permission_result.h"
+#include "content/public/browser/platform_notification_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/storage_partition_config.h"
 #include "content/public/common/persistent_notification_status.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_permission_manager.h"
@@ -38,6 +49,7 @@
 #include "third_party/blink/public/common/notifications/notification_resources.h"
 #include "third_party/blink/public/common/permissions/permission_utils.h"
 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
 
 using ::testing::_;
 using ::testing::Return;
@@ -329,3 +341,266 @@
 
   run_loop.Run();
 }
+
+class
+    PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest
+    : public PersistentNotificationHandlerTest {
+ public:
+  PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest()
+      : manager_(TestingBrowserProcess::GetGlobal()) {}
+
+  void SetUp() override {
+    ASSERT_TRUE(manager_.SetUp());
+
+    testing_profile_ = manager_.CreateTestingProfile("foo");
+    mock_optimization_guide_keyed_service_ = static_cast<
+        MockOptimizationGuideKeyedService*>(
+        OptimizationGuideKeyedServiceFactory::GetInstance()
+            ->SetTestingFactoryAndUse(
+                testing_profile_,
+                base::BindRepeating([](content::BrowserContext* context)
+                                        -> std::unique_ptr<KeyedService> {
+                  return std::make_unique<MockOptimizationGuideKeyedService>();
+                })));
+    auto logs_uploader = std::make_unique<
+        optimization_guide::TestModelQualityLogsUploaderService>(
+        manager_.local_state()->Get());
+    mock_optimization_guide_keyed_service_
+        ->SetModelQualityLogsUploaderServiceForTesting(
+            std::move(logs_uploader));
+  }
+
+  void TearDown() override { PersistentNotificationHandlerTest::TearDown(); }
+
+  TestingProfile* profile() { return testing_profile_; }
+
+  optimization_guide::TestModelQualityLogsUploaderService* logs_uploader() {
+    return static_cast<
+        optimization_guide::TestModelQualityLogsUploaderService*>(
+        mock_optimization_guide_keyed_service_
+            ->GetModelQualityLogsUploaderService());
+  }
+
+  const std::vector<
+      std::unique_ptr<optimization_guide::proto::LogAiDataRequest>>&
+  uploaded_logs() {
+    return logs_uploader()->uploaded_logs();
+  }
+
+  content::PlatformNotificationContext* GetPlatformNotificationContext(
+      GURL origin) {
+    return testing_profile_->GetStoragePartitionForUrl(origin)
+        ->GetPlatformNotificationContext();
+  }
+
+  void WriteNotificationDataAndMetadataToDatabase(bool is_on_global_cache_list,
+                                                  bool is_allowlisted_by_user,
+                                                  double suspicious_score) {
+    // Store notification data in `NotificationDatabase`.
+    const int64_t kFakeServiceWorkerRegistrationId = 42;
+    int notification_id = 1;
+    GURL origin(kExampleOrigin);
+    content::NotificationDatabaseData notification_database_data;
+    notification_database_data.origin = origin;
+    GetPlatformNotificationContext(origin)->WriteNotificationData(
+        notification_id, kFakeServiceWorkerRegistrationId, origin,
+        notification_database_data, base::DoNothing());
+    base::RunLoop().RunUntilIdle();
+
+    // Store metadata in `NotificationDatabase`.
+    std::string notification_id_str =
+        "p#" + origin.spec() + "#0" + base::NumberToString(notification_id);
+    std::string serialized_metadata =
+        "{\"" +
+        std::string(safe_browsing::kMetadataIsOriginAllowlistedByUserKey) +
+        "\":" + (is_allowlisted_by_user ? "true" : "false") + ",\"" +
+        std::string(safe_browsing::kMetadataIsOriginOnGlobalCacheListKey) +
+        "\":" + (is_on_global_cache_list ? "true" : "false") + ",\"" +
+        std::string(safe_browsing::kMetadataSuspiciousKey) +
+        "\":" + base::NumberToString(suspicious_score) + "}";
+    GetPlatformNotificationContext(origin)->WriteNotificationMetadata(
+        notification_id_str, origin, safe_browsing::kMetadataDictionaryKey,
+        serialized_metadata, base::DoNothing());
+  }
+
+ private:
+  TestingProfileManager manager_;
+  raw_ptr<TestingProfile> testing_profile_;
+  raw_ptr<MockOptimizationGuideKeyedService>
+      mock_optimization_guide_keyed_service_;
+};
+
+TEST_F(
+    PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest,
+    ReportNotificationAsSafe) {
+  bool is_url_on_allowlist = true;
+  bool did_user_always_allow_url = false;
+  double suspicious_score = 70.0;
+  WriteNotificationDataAndMetadataToDatabase(
+      is_url_on_allowlist, did_user_always_allow_url, suspicious_score);
+  int notification_id = 1;
+
+  GURL origin(origin_);
+  std::string notification_id_str =
+      "p#" + origin.spec() + "#0" + base::NumberToString(notification_id);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportNotificationAsSafe(notification_id_str, origin_, profile());
+
+  // Check the MQLS log.
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  ASSERT_TRUE(notification_content_detection->has_request());
+  ASSERT_TRUE(notification_content_detection->has_response());
+  ASSERT_TRUE(notification_content_detection->has_quality());
+  ASSERT_EQ(
+      origin.spec(),
+      notification_content_detection->request().notification_contents().url());
+  ASSERT_EQ(suspicious_score,
+            notification_content_detection->response().suspicious_score());
+  ASSERT_TRUE(notification_content_detection->quality().is_url_on_allowlist());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_always_allow_url());
+  ASSERT_TRUE(
+      notification_content_detection->quality().was_user_shown_warning());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_unsubscribe());
+  ASSERT_EQ(optimization_guide::proto::SiteEngagementScore::
+                SITE_ENGAGEMENT_SCORE_NONE,
+            notification_content_detection->quality().site_engagement_score());
+}
+
+TEST_F(
+    PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest,
+    ReportWarnedNotificationAsSpam) {
+  bool is_url_on_allowlist = true;
+  bool did_user_always_allow_url = false;
+  double suspicious_score = 70.0;
+  WriteNotificationDataAndMetadataToDatabase(
+      is_url_on_allowlist, did_user_always_allow_url, suspicious_score);
+  int notification_id = 1;
+
+  GURL origin(origin_);
+  std::string notification_id_str =
+      "p#" + origin.spec() + "#0" + base::NumberToString(notification_id);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportWarnedNotificationAsSpam(notification_id_str, origin_,
+                                          profile());
+
+  // Check the MQLS log.
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  ASSERT_TRUE(notification_content_detection->has_request());
+  ASSERT_TRUE(notification_content_detection->has_response());
+  ASSERT_TRUE(notification_content_detection->has_quality());
+  ASSERT_EQ(
+      origin.spec(),
+      notification_content_detection->request().notification_contents().url());
+  ASSERT_EQ(suspicious_score,
+            notification_content_detection->response().suspicious_score());
+  ASSERT_TRUE(notification_content_detection->quality().is_url_on_allowlist());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_always_allow_url());
+  ASSERT_TRUE(
+      notification_content_detection->quality().was_user_shown_warning());
+  ASSERT_TRUE(notification_content_detection->quality().did_user_unsubscribe());
+  ASSERT_EQ(optimization_guide::proto::SiteEngagementScore::
+                SITE_ENGAGEMENT_SCORE_NONE,
+            notification_content_detection->quality().site_engagement_score());
+}
+
+TEST_F(
+    PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest,
+    ReportUnwarnedNotificationAsSpam) {
+  bool is_url_on_allowlist = true;
+  bool did_user_always_allow_url = false;
+  double suspicious_score = 70.0;
+  WriteNotificationDataAndMetadataToDatabase(
+      is_url_on_allowlist, did_user_always_allow_url, suspicious_score);
+  int notification_id = 1;
+
+  GURL origin(origin_);
+  std::string notification_id_str =
+      "p#" + origin.spec() + "#0" + base::NumberToString(notification_id);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportUnwarnedNotificationAsSpam(notification_id_str, origin_,
+                                            profile());
+
+  // Check the MQLS log.
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  ASSERT_TRUE(notification_content_detection->has_request());
+  ASSERT_TRUE(notification_content_detection->has_response());
+  ASSERT_TRUE(notification_content_detection->has_quality());
+  ASSERT_EQ(
+      origin.spec(),
+      notification_content_detection->request().notification_contents().url());
+  ASSERT_EQ(suspicious_score,
+            notification_content_detection->response().suspicious_score());
+  ASSERT_TRUE(notification_content_detection->quality().is_url_on_allowlist());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_always_allow_url());
+  ASSERT_FALSE(
+      notification_content_detection->quality().was_user_shown_warning());
+  ASSERT_TRUE(notification_content_detection->quality().did_user_unsubscribe());
+  ASSERT_EQ(optimization_guide::proto::SiteEngagementScore::
+                SITE_ENGAGEMENT_SCORE_NONE,
+            notification_content_detection->quality().site_engagement_score());
+}
+
+class
+    PersistentNotificationHandlerWithNotificationContentDetectionLowLoggingRateTest
+    : public PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest {
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        safe_browsing::kReportNotificationContentDetectionData,
+        {{"ReportNotificationContentDetectionDataRate", "0"}});
+    PersistentNotificationHandlerWithNotificationContentDetectionAndLoggingTest::
+        SetUp();
+  }
+};
+
+TEST_F(
+    PersistentNotificationHandlerWithNotificationContentDetectionLowLoggingRateTest,
+    NoReportSent) {
+  bool is_url_on_allowlist = true;
+  bool did_user_always_allow_url = false;
+  double suspicious_score = 70.0;
+  WriteNotificationDataAndMetadataToDatabase(
+      is_url_on_allowlist, did_user_always_allow_url, suspicious_score);
+  int notification_id = 1;
+
+  GURL origin(origin_);
+  std::string notification_id_str =
+      "p#" + origin.spec() + "#0" + base::NumberToString(notification_id);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportNotificationAsSafe(notification_id_str, origin_, profile());
+
+  // Check no MQLS logs.
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(0u, logs.size());
+}
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc
index 02293a6..2f9eb931 100644
--- a/chrome/browser/notifications/platform_notification_service_impl.cc
+++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -776,28 +776,18 @@
   if (base::FeatureList::IsEnabled(
           safe_browsing::kReportNotificationContentDetectionData) &&
       serialized_content_detection_metadata.has_value()) {
-    // Obtain the storage partition for the url and if found, update
-    // `NotificationDatabase` with metadata.
-    auto storage_partition_config = content::StoragePartitionConfig::Create(
-        profile_, notification.origin_url().host(), /*partition_name=*/"",
-        /*in_memory=*/false);
-    // If there is no storage partition for the url, then there is also no
-    // notification data so do not create a partition to store metadata.
-    content::StoragePartition* current_storage_partition_ =
-        profile_->GetStoragePartition(storage_partition_config,
-                                      /*can_create=*/false);
-    if (current_storage_partition_ &&
-        current_storage_partition_->GetPlatformNotificationContext()) {
-      current_storage_partition_->GetPlatformNotificationContext()
-          ->WriteNotificationMetadata(
-              notification.id(), notification.origin_url(),
-              safe_browsing::kMetadataDictionaryKey,
-              serialized_content_detection_metadata.value(),
-              base::BindOnce(
-                  &PlatformNotificationServiceImpl::DidUpdatePersistentMetadata,
-                  weak_ptr_factory_.GetWeakPtr(),
-                  std::move(persistent_metadata), notification,
-                  should_show_warning));
+    scoped_refptr<content::PlatformNotificationContext> notification_context =
+        profile_->GetStoragePartitionForUrl(notification.origin_url())
+            ->GetPlatformNotificationContext();
+    if (notification_context) {
+      notification_context->WriteNotificationMetadata(
+          notification.id(), notification.origin_url(),
+          safe_browsing::kMetadataDictionaryKey,
+          serialized_content_detection_metadata.value(),
+          base::BindOnce(
+              &PlatformNotificationServiceImpl::DidUpdatePersistentMetadata,
+              weak_ptr_factory_.GetWeakPtr(), std::move(persistent_metadata),
+              notification, should_show_warning));
       return;
     }
   }
diff --git a/chrome/browser/notifications/platform_notification_service_unittest.cc b/chrome/browser/notifications/platform_notification_service_unittest.cc
index a97c366..c2be3d4c 100644
--- a/chrome/browser/notifications/platform_notification_service_unittest.cc
+++ b/chrome/browser/notifications/platform_notification_service_unittest.cc
@@ -146,11 +146,8 @@
   }
 
   content::PlatformNotificationContext* GetPlatformNotificationContext(
-      std::string origin_host) {
-    auto storage_partition_config = content::StoragePartitionConfig::Create(
-        profile_.get(), origin_host, /*partition_name=*/"",
-        /*in_memory=*/false);
-    return profile_->GetStoragePartition(storage_partition_config, true)
+      GURL origin) {
+    return profile_->GetStoragePartitionForUrl(origin)
         ->GetPlatformNotificationContext();
   }
 
@@ -1058,10 +1055,9 @@
   GURL origin("https://example.com");
   NotificationDatabaseData notification_database_data;
   notification_database_data.origin = origin;
-  GetPlatformNotificationContext(origin.host())
-      ->WriteNotificationData(notification_id, kFakeServiceWorkerRegistrationId,
-                              origin, notification_database_data,
-                              base::DoNothing());
+  GetPlatformNotificationContext(origin)->WriteNotificationData(
+      notification_id, kFakeServiceWorkerRegistrationId, origin,
+      notification_database_data, base::DoNothing());
   base::RunLoop().RunUntilIdle();
   // Update `NotificationDatabase` entry with metadata.
   Notification notification = message_center::Notification(
@@ -1082,7 +1078,7 @@
   // Read and check the entry from `NotificationDatabase`.
   NotificationDatabaseData data =
       ReadNotificationDataAndRecordInteractionSynchronous(
-          GetPlatformNotificationContext(origin.host()),
+          GetPlatformNotificationContext(origin),
           base::NumberToString(notification_id), origin);
   ASSERT_TRUE(
       data.serialized_metadata.contains(safe_browsing::kMetadataDictionaryKey));
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
index 7b93965..7d54182 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -37,6 +37,10 @@
 class BrowserContext;
 }  // namespace content
 
+namespace contextual_cueing {
+class ZeroStateSuggestionsPageData;
+}  // namespace contextual_cueing
+
 namespace download {
 class BackgroundDownloadService;
 }  // namespace download
@@ -246,6 +250,7 @@
   friend class BrowserView;
   friend class ChromeBrowserMainExtraPartsOptimizationGuide;
   friend class ChromeBrowsingDataRemoverDelegate;
+  friend class contextual_cueing::ZeroStateSuggestionsPageData;
   friend class HintsFetcherBrowserTest;
   friend class on_device_internals::PageHandler;
   friend class OptimizationGuideInternalsUI;
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientHelper.java
index f7e28032..63395c7 100644
--- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientHelper.java
+++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientHelper.java
@@ -7,6 +7,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError;
 
 import java.util.Optional;
@@ -54,7 +55,7 @@
      */
     default void getPasswordCheckupIntent(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<PendingIntent> successCallback,
             Callback<Exception> failureCallback) {}
 
@@ -88,7 +89,7 @@
      */
     default void runPasswordCheckupInBackground(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<Void> successCallback,
             Callback<Exception> failureCallback) {}
 
@@ -120,7 +121,7 @@
      */
     default void getBreachedCredentialsCount(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<Integer> successCallback,
             Callback<Exception> failureCallback) {}
 
@@ -135,7 +136,7 @@
      */
     default void getWeakCredentialsCount(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<Integer> successCallback,
             Callback<Exception> failureCallback) {}
 
@@ -150,7 +151,7 @@
      */
     default void getReusedCredentialsCount(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<Integer> successCallback,
             Callback<Exception> failureCallback) {}
 }
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
index 196d7e5..8272560 100644
--- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
+++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
@@ -431,7 +431,7 @@
      */
     public void runPasswordCheckupInBackground(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<@Nullable Void> successCallback,
             Callback<Exception> failureCallback) {
         PasswordCheckupClientMetricsRecorder passwordCheckupMetricsRecorder =
@@ -470,7 +470,7 @@
      */
     public void getBreachedCredentialsCount(
             @PasswordCheckReferrer int referrer,
-            String accountName,
+            @Nullable String accountName,
             Callback<Integer> successCallback,
             Callback<Exception> failureCallback) {
         PasswordCheckupClientMetricsRecorder passwordCheckupMetricsRecorder =
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/ChromeNativePasswordCheckController.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/ChromeNativePasswordCheckController.java
index 80181f2a..e5f7457 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/ChromeNativePasswordCheckController.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/ChromeNativePasswordCheckController.java
@@ -4,16 +4,22 @@
 
 package org.chromium.chrome.browser.pwd_check_wrapper;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.password_check.PasswordCheck;
 import org.chromium.chrome.browser.password_check.PasswordCheckFactory;
 import org.chromium.chrome.browser.password_check.PasswordCheckUIStatus;
 
 import java.util.concurrent.CompletableFuture;
 
+@NullMarked
 class ChromeNativePasswordCheckController
         implements PasswordCheckController, PasswordCheck.Observer {
-    private CompletableFuture<Integer> mPasswordsTotalCount;
-    private CompletableFuture<PasswordCheckResult> mPasswordCheckResult;
+    private @Nullable CompletableFuture<Integer> mPasswordsTotalCount = new CompletableFuture<>();
+    private @Nullable CompletableFuture<PasswordCheckResult> mPasswordCheckResult =
+            new CompletableFuture<>();
 
     @Override
     public CompletableFuture<PasswordCheckResult> checkPasswords(
@@ -64,19 +70,20 @@
     // PasswordCheck.Observer implementation.
     @Override
     public void onCompromisedCredentialsFetchCompleted() {
-        mPasswordsTotalCount.thenAccept(
-                totalCount -> {
-                    int breachedCount = getPasswordCheck().getCompromisedCredentialsCount();
-                    mPasswordCheckResult.complete(
-                            new PasswordCheckResult(totalCount, breachedCount));
-                    getPasswordCheck().removeObserver(this);
-                });
+        assumeNonNull(mPasswordsTotalCount)
+                .thenAccept(
+                        totalCount -> {
+                            int breachedCount = getPasswordCheck().getCompromisedCredentialsCount();
+                            assumeNonNull(mPasswordCheckResult)
+                                    .complete(new PasswordCheckResult(totalCount, breachedCount));
+                            getPasswordCheck().removeObserver(this);
+                        });
     }
 
     @Override
     public void onSavedPasswordsFetchCompleted() {
         int totalCount = getPasswordCheck().getSavedPasswordsCount();
-        mPasswordsTotalCount.complete(totalCount);
+        assumeNonNull(mPasswordsTotalCount).complete(totalCount);
     }
 
     @Override
@@ -90,11 +97,12 @@
             PasswordCheckNativeException error =
                     new PasswordCheckNativeException(
                             "Password check finished with the error " + status + ".", status);
-            mPasswordCheckResult.complete(new PasswordCheckResult(error));
+            assumeNonNull(mPasswordCheckResult).complete(new PasswordCheckResult(error));
         } else {
             int totalCount = getPasswordCheck().getSavedPasswordsCount();
             int breachedCount = getPasswordCheck().getCompromisedCredentialsCount();
-            mPasswordCheckResult.complete(new PasswordCheckResult(totalCount, breachedCount));
+            assumeNonNull(mPasswordCheckResult)
+                    .complete(new PasswordCheckResult(totalCount, breachedCount));
         }
 
         getPasswordCheck().removeObserver(this);
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
index ba96474..c0c9133 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge.usesSplitStoresAndUPMForLocal;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.password_manager.PasswordCheckReferrer;
 import org.chromium.chrome.browser.password_manager.PasswordManagerHelper;
 import org.chromium.chrome.browser.password_manager.PasswordStoreBridge;
@@ -20,6 +21,7 @@
  * The implementation of {@link PasswordCheckController} which calls the Gms core API to perform the
  * password check and get breached credentials number.
  */
+@NullMarked
 class GmsCorePasswordCheckController
         implements PasswordCheckController, PasswordStoreBridge.PasswordStoreObserver {
     private final SyncService mSyncService;
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckController.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckController.java
index e9c7d7d..38a5e78d 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckController.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckController.java
@@ -6,6 +6,8 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.password_manager.PasswordManagerHelper;
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.sync.SyncService;
@@ -19,6 +21,7 @@
  * The controller, which manages the breached credentials check. It runs the password check
  * asynchronously and provides the result whenever it's ready.
  */
+@NullMarked
 public interface PasswordCheckController {
 
     /**
@@ -35,7 +38,7 @@
     public static class PasswordCheckResult {
         private OptionalInt mTotalPasswordsCount = OptionalInt.empty();
         private OptionalInt mBreachedCount = OptionalInt.empty();
-        private Exception mError;
+        private @Nullable Exception mError;
 
         public PasswordCheckResult(int totalPasswordsCount, int breachedCount) {
             mTotalPasswordsCount = OptionalInt.of(totalPasswordsCount);
@@ -54,12 +57,12 @@
             return mTotalPasswordsCount;
         }
 
-        public Exception getError() {
+        public @Nullable Exception getError() {
             return mError;
         }
     }
 
-    static String getAccountNameForPasswordStorageType(
+    static @Nullable String getAccountNameForPasswordStorageType(
             @PasswordStorageType int passwordStorageType, SyncService syncService) {
         switch (passwordStorageType) {
             case PasswordStorageType.LOCAL_STORAGE:
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckControllerFactory.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckControllerFactory.java
index 8356107..a5f631a 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckControllerFactory.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckControllerFactory.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.LOGIN_DB_DEPRECATION_ANDROID;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.password_manager.PasswordManagerHelper;
 import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge;
@@ -13,6 +14,7 @@
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.sync.SyncService;
 
+@NullMarked
 public class PasswordCheckControllerFactory {
     public PasswordCheckController create(
             SyncService syncService,
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckNativeException.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckNativeException.java
index 993776c..1382ab3 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckNativeException.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/PasswordCheckNativeException.java
@@ -4,12 +4,14 @@
 
 package org.chromium.chrome.browser.pwd_check_wrapper;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.password_check.PasswordCheckUIStatus;
 
 /**
  * The exception returned by {@link ChromeNativePasswordCheckController} notifying there was an
  * error during password check.
  */
+@NullMarked
 public class PasswordCheckNativeException extends Exception {
     public @PasswordCheckUIStatus int errorCode;
 
diff --git a/chrome/browser/password_manager/chrome_password_change_service.h b/chrome/browser/password_manager/chrome_password_change_service.h
index e8411a1..144522b 100644
--- a/chrome/browser/password_manager/chrome_password_change_service.h
+++ b/chrome/browser/password_manager/chrome_password_change_service.h
@@ -53,16 +53,16 @@
   // Indicates that password change will be proposed to the user for a given
   // `url`, `username` and `password`. `originator` belongs to a tab which
   // initiated the process.
-  void OfferPasswordChangeUi(const GURL& url,
-                             const std::u16string& username,
-                             const std::u16string& password,
-                             content::WebContents* originator);
+  virtual void OfferPasswordChangeUi(const GURL& url,
+                                     const std::u16string& username,
+                                     const std::u16string& password,
+                                     content::WebContents* originator);
 
   // Responds with PasswordChangeDelegate for a given `web_contents`.
   // The same object is returned for a tab which initiated password change and a
   // tab where password change is performed. Returns nullptr if `web_contents`
   // isn't associated with any delegate.
-  PasswordChangeDelegate* GetPasswordChangeDelegate(
+  virtual PasswordChangeDelegate* GetPasswordChangeDelegate(
       content::WebContents* web_contents);
 
   // PasswordChangeServiceInterface implementation.
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 16ae6b54..9fc0111d 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -248,6 +248,27 @@
 
 #endif
 
+void InformPasswordChangeServiceIfOtpPresent(
+    content::WebContents* web_contents,
+    const base::flat_map<autofill::FieldGlobalId, autofill::FieldType>&
+        predictions) {
+  bool has_otp_field = std::any_of(
+      predictions.begin(), predictions.end(), [](const auto& field) {
+        return field.second == autofill::ONE_TIME_CODE;
+      });
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  if (has_otp_field) {
+    ChromePasswordChangeService* password_change_service =
+        PasswordChangeServiceFactory::GetForProfile(profile);
+    if (password_change_service &&
+        password_change_service->GetPasswordChangeDelegate(web_contents)) {
+      password_change_service->GetPasswordChangeDelegate(web_contents)
+          ->OnOtpFieldDetected(web_contents);
+    }
+  }
+}
+
 }  // namespace
 
 // static
@@ -1939,13 +1960,15 @@
             driver, form,
             manager.GetServerPredictionsForForm(form_id, field_ids));
         break;
-      case FieldTypeSource::kHeuristicsOrAutocomplete:
-        password_manager_.ProcessClassificationModelPredictions(
-            driver, form,
-            manager.GetHeursticPredictionForForm(
-                autofill::HeuristicSource::kPasswordManagerMachineLearning,
-                form_id, field_ids));
+      case FieldTypeSource::kHeuristicsOrAutocomplete: {
+        auto predictions = manager.GetHeursticPredictionForForm(
+            autofill::HeuristicSource::kPasswordManagerMachineLearning, form_id,
+            field_ids);
+        password_manager_.ProcessClassificationModelPredictions(driver, form,
+                                                                predictions);
+        InformPasswordChangeServiceIfOtpPresent(web_contents(), predictions);
         break;
+      }
     }
   }
 }
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index d658bba3..fd4acdd 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -27,6 +27,9 @@
 #include "build/build_config.h"
 #include "chrome/browser/autofill/mock_manual_filling_view.h"
 #include "chrome/browser/keyboard_accessory/test_utils/android/mock_address_accessory_controller.h"
+#include "chrome/browser/password_manager/chrome_password_change_service.h"
+#include "chrome/browser/password_manager/password_change_delegate_mock.h"
+#include "chrome/browser/password_manager/password_change_service_factory.h"
 #include "chrome/browser/password_manager/password_manager_settings_service_factory.h"
 #include "chrome/browser/password_manager/profile_password_store_factory.h"
 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
@@ -351,11 +354,36 @@
 
 #endif
 
+class MockPasswordChangeService : public ChromePasswordChangeService {
+ public:
+  MockPasswordChangeService()
+      : ChromePasswordChangeService(/*affiliation_service=*/nullptr,
+                                    /*optimization_keyed_service=*/nullptr,
+                                    /*feature_manager=*/nullptr) {}
+
+  MOCK_METHOD(void,
+              OfferPasswordChangeUi,
+              (const GURL&,
+               const std::u16string&,
+               const std::u16string&,
+               content::WebContents*),
+              (override));
+  MOCK_METHOD(PasswordChangeDelegate*,
+              GetPasswordChangeDelegate,
+              (content::WebContents*),
+              (override));
+};
+
 std::unique_ptr<KeyedService> CreateTestSyncService(
     content::BrowserContext* context) {
   return std::make_unique<syncer::TestSyncService>();
 }
 
+std::unique_ptr<KeyedService> CreateMockPasswordChangeService(
+    content::BrowserContext* context) {
+  return std::make_unique<MockPasswordChangeService>();
+}
+
 }  // namespace
 
 class ChromePasswordManagerClientTest : public ChromeRenderViewHostTestHarness {
@@ -385,6 +413,11 @@
         }));
   }
 
+  void SetupMockPasswordChangeService() {
+    PasswordChangeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+        profile(), base::BindRepeating(&CreateMockPasswordChangeService));
+  }
+
  protected:
   ChromePasswordManagerClient* GetClient();
   password_manager::MockPasswordManagerSettingsService& settings_service() {
@@ -395,6 +428,10 @@
     return static_cast<syncer::TestSyncService*>(
         SyncServiceFactory::GetInstance()->GetForProfile(profile()));
   }
+  MockPasswordChangeService* password_change_service() {
+    return static_cast<MockPasswordChangeService*>(
+        PasswordChangeServiceFactory::GetInstance()->GetForProfile(profile()));
+  }
 
   // If autofill::mojom::PasswordAutofillAgent::SetLoggingState() got called,
   // copies its argument into `activation_flag` and returns true. Otherwise
@@ -444,6 +481,7 @@
   ChromePasswordManagerClient::CreateForWebContents(web_contents());
 
   SetupSettingsServiceFactory();
+  SetupMockPasswordChangeService();
 }
 
 void ChromePasswordManagerClientTest::TearDown() {
@@ -1953,3 +1991,46 @@
       AcknowledgeGroupedCredentialSheetBridge::DismissReason::kBack);
 }
 #endif  // BUILDFLAG(IS_ANDROID)
+
+TEST_F(ChromePasswordManagerClientTest,
+       PasswordChangeDelegateIsNotifiedAboutOTP) {
+  base::test::ScopedFeatureList features(
+      password_manager::features::kPasswordFormClientsideClassifier);
+
+  PasswordChangeDelegateMock mock;
+  ON_CALL(*password_change_service(), GetPasswordChangeDelegate)
+      .WillByDefault(Return(&mock));
+
+  NavigateAndCommit(GURL("https://www.foo.com/login.html"));
+  ContentAutofillDriver* autofill_driver =
+      ContentAutofillDriver::GetForRenderFrameHost(main_rfh());
+  ASSERT_TRUE(autofill_driver);
+
+  std::vector<FormFieldData> fields = {
+      CreateTestFormField("OTP", "one-time-code", "",
+                          FormControlType::kInputText, "one-time-code")};
+  FormData form =
+      CreateFormDataForRenderFrameHost(*main_rfh(), std::move(fields));
+  {
+    autofill::TestAutofillManagerWaiter waiter(
+        autofill_driver->GetAutofillManager(),
+        {autofill::AutofillManagerEvent::kFormsSeen});
+    autofill_driver->renderer_events().FormsSeen(/*updated_forms=*/{form},
+                                                 /*removed_forms=*/{});
+    ASSERT_TRUE(waiter.Wait(/*num_expected_relevant_events=*/1));
+  }
+
+  EXPECT_CALL(mock, OnOtpFieldDetected(web_contents()));
+
+  // Simulate that the field types have been determined.
+  using Observer = autofill::AutofillManager::Observer;
+  autofill_driver->GetAutofillManager()
+      .FindCachedFormById(form.global_id())
+      ->field(0)
+      ->set_heuristic_type(
+          autofill::HeuristicSource::kPasswordManagerMachineLearning,
+          autofill::FieldType::ONE_TIME_CODE);
+  autofill_driver->GetAutofillManager().NotifyObservers(
+      &Observer::OnFieldTypesDetermined, form.global_id(),
+      Observer::FieldTypeSource::kHeuristicsOrAutocomplete);
+}
diff --git a/chrome/browser/password_manager/password_change/change_password_form_finder.cc b/chrome/browser/password_manager/password_change/change_password_form_finder.cc
new file mode 100644
index 0000000..53b7ab3
--- /dev/null
+++ b/chrome/browser/password_manager/password_change/change_password_form_finder.cc
@@ -0,0 +1,66 @@
+// Copyright 2025 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/password_manager/password_change/change_password_form_finder.h"
+
+#include "chrome/browser/password_manager/password_change/change_password_form_waiter.h"
+#include "components/optimization_guide/content/browser/page_content_proto_provider.h"
+#include "content/public/browser/web_contents.h"
+
+ChangePasswordFormFinder::ChangePasswordFormFinder(
+    content::WebContents* web_contents,
+    ChangePasswordFormWaiter::PasswordFormFoundCallback callback)
+    : web_contents_(web_contents->GetWeakPtr()),
+      callback_(std::move(callback)) {
+  capture_annotated_page_content_ =
+      base::BindOnce(&optimization_guide::GetAIPageContent, web_contents,
+                     optimization_guide::DefaultAIPageContentOptions());
+  form_waiter_ = std::make_unique<ChangePasswordFormWaiter>(
+      web_contents,
+      base::BindOnce(&ChangePasswordFormFinder::OnInitialFormWaitingResult,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+ChangePasswordFormFinder::ChangePasswordFormFinder(
+    base::PassKey<class ChangePasswordFormFinderTest>,
+    content::WebContents* web_contents,
+    ChangePasswordFormWaiter::PasswordFormFoundCallback callback,
+    base::OnceCallback<void(optimization_guide::OnAIPageContentDone)>
+        capture_annotated_page_content)
+    : ChangePasswordFormFinder(web_contents, std::move(callback)) {
+  capture_annotated_page_content_ = std::move(capture_annotated_page_content);
+}
+
+ChangePasswordFormFinder::~ChangePasswordFormFinder() = default;
+
+void ChangePasswordFormFinder::OnInitialFormWaitingResult(
+    password_manager::PasswordFormManager* form_manager) {
+  form_waiter_.reset();
+  if (form_manager) {
+    std::move(callback_).Run(form_manager);
+    return;
+  }
+
+  // The tab closed, fail immediately.
+  if (!web_contents_) {
+    std::move(callback_).Run(nullptr);
+    return;
+  }
+
+  CHECK(capture_annotated_page_content_);
+  std::move(capture_annotated_page_content_)
+      .Run(base::BindOnce(&ChangePasswordFormFinder::OnPageContentReceived,
+                          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ChangePasswordFormFinder::OnPageContentReceived(
+    std::optional<optimization_guide::AIPageContentResult> content) {
+  if (!content || !web_contents_) {
+    std::move(callback_).Run(nullptr);
+    return;
+  }
+  // TODO(crbug.com/407486413): Check if it's a settings page and try to find a
+  // button which opens a change-pwd form.
+  std::move(callback_).Run(nullptr);
+}
diff --git a/chrome/browser/password_manager/password_change/change_password_form_finder.h b/chrome/browser/password_manager/password_change/change_password_form_finder.h
new file mode 100644
index 0000000..33e537bd
--- /dev/null
+++ b/chrome/browser/password_manager/password_change/change_password_form_finder.h
@@ -0,0 +1,62 @@
+// Copyright 2025 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_PASSWORD_MANAGER_PASSWORD_CHANGE_CHANGE_PASSWORD_FORM_FINDER_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_CHANGE_CHANGE_PASSWORD_FORM_FINDER_H_
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/password_manager/password_change/change_password_form_waiter.h"
+#include "components/optimization_guide/content/browser/page_content_proto_provider.h"
+
+namespace password_manager {
+class PasswordFormManager;
+}
+
+namespace content {
+class WebContents;
+}
+
+// Helper class which searches for a change password form, performs actuation
+// when necessary. Invokes a callback with a form when it's found, or nullptr
+// otherwise.
+class ChangePasswordFormFinder {
+ public:
+  ChangePasswordFormFinder(
+      content::WebContents* web_contents,
+      ChangePasswordFormWaiter::PasswordFormFoundCallback callback);
+
+  ChangePasswordFormFinder(
+      base::PassKey<class ChangePasswordFormFinderTest>,
+      content::WebContents* web_contents,
+      ChangePasswordFormWaiter::PasswordFormFoundCallback callback,
+      base::OnceCallback<void(optimization_guide::OnAIPageContentDone)>
+          capture_annotated_page_content);
+
+  ~ChangePasswordFormFinder();
+
+#if defined(UNIT_TEST)
+  void RespondWithFormNotFound() { std::move(callback_).Run(nullptr); }
+
+  ChangePasswordFormWaiter* form_waiter() { return form_waiter_.get(); }
+#endif
+
+ private:
+  void OnInitialFormWaitingResult(
+      password_manager::PasswordFormManager* form_manager);
+
+  void OnPageContentReceived(
+      std::optional<optimization_guide::AIPageContentResult> content);
+
+  base::WeakPtr<content::WebContents> web_contents_;
+  ChangePasswordFormWaiter::PasswordFormFoundCallback callback_;
+  base::OnceCallback<void(optimization_guide::OnAIPageContentDone)>
+      capture_annotated_page_content_;
+
+  std::unique_ptr<ChangePasswordFormWaiter> form_waiter_;
+
+  base::WeakPtrFactory<ChangePasswordFormFinder> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_CHANGE_CHANGE_PASSWORD_FORM_FINDER_H_
diff --git a/chrome/browser/password_manager/password_change/change_password_form_finder_unittest.cc b/chrome/browser/password_manager/password_change/change_password_form_finder_unittest.cc
new file mode 100644
index 0000000..8405a43a
--- /dev/null
+++ b/chrome/browser/password_manager/password_change/change_password_form_finder_unittest.cc
@@ -0,0 +1,170 @@
+// Copyright 2025 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/password_manager/password_change/change_password_form_finder.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/mock_callback.h"
+#include "base/types/pass_key.h"
+#include "chrome/browser/password_manager/account_password_store_factory.h"
+#include "chrome/browser/password_manager/chrome_password_manager_client.h"
+#include "chrome/browser/password_manager/profile_password_store_factory.h"
+#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/autofill/core/common/autofill_test_utils.h"
+#include "components/os_crypt/sync/os_crypt_mocker.h"
+#include "components/password_manager/core/browser/fake_form_fetcher.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/password_save_manager_impl.h"
+#include "components/password_manager/core/browser/password_store/mock_password_store_interface.h"
+#include "components/password_manager/core/browser/password_store/test_password_store.h"
+#include "components/password_manager/core/browser/stub_password_manager_driver.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/visibility.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+using autofill::test::CreateTestFormField;
+using testing::Return;
+
+class FakeChromePasswordManagerClient : public ChromePasswordManagerClient {
+ public:
+  static void CreateForWebContents(content::WebContents* contents) {
+    auto* client = new FakeChromePasswordManagerClient(contents);
+    contents->SetUserData(UserDataKey(), base::WrapUnique(client));
+  }
+
+  password_manager::WebAuthnCredentialsDelegate*
+  GetWebAuthnCredentialsDelegateForDriver(
+      password_manager::PasswordManagerDriver*) override {
+    return nullptr;
+  }
+
+ private:
+  explicit FakeChromePasswordManagerClient(content::WebContents* web_contents)
+      : ChromePasswordManagerClient(web_contents) {}
+};
+
+}  // namespace
+
+class ChangePasswordFormFinderTest : public ChromeRenderViewHostTestHarness {
+ public:
+  ChangePasswordFormFinderTest()
+      : ChromeRenderViewHostTestHarness(
+            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+  ~ChangePasswordFormFinderTest() override = default;
+
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    OSCryptMocker::SetUp();
+
+    ProfilePasswordStoreFactory::GetInstance()->SetTestingFactory(
+        GetBrowserContext(),
+        base::BindRepeating(&password_manager::BuildPasswordStoreInterface<
+                            content::BrowserContext,
+                            password_manager::MockPasswordStoreInterface>));
+
+    // `ChromePasswordManagerClient` observes `AutofillManager`s, so
+    // `ChromeAutofillClient` needs to be set up, too.
+    autofill::ChromeAutofillClient::CreateForWebContents(web_contents());
+    FakeChromePasswordManagerClient::CreateForWebContents(web_contents());
+  }
+
+  std::unique_ptr<password_manager::PasswordFormManager> CreateFormManager(
+      const autofill::FormData& form_data) {
+    auto form_manager = std::make_unique<password_manager::PasswordFormManager>(
+        client(), driver().AsWeakPtr(), form_data, &form_fetcher(),
+        std::make_unique<password_manager::PasswordSaveManagerImpl>(client()),
+        /*metrics_recorder=*/nullptr);
+    // Force form parsing, otherwise there will be no parsed observed form.
+    form_fetcher_.NotifyFetchCompleted();
+    static_cast<password_manager::PasswordFormPredictionWaiter::Client*>(
+        form_manager.get())
+        ->OnWaitCompleted();
+    return form_manager;
+  }
+
+  ChromePasswordManagerClient* client() {
+    return ChromePasswordManagerClient::FromWebContents(web_contents());
+  }
+
+  password_manager::StubPasswordManagerDriver& driver() { return driver_; }
+
+  PrefService* prefs() { return profile()->GetPrefs(); }
+
+  password_manager::FakeFormFetcher& form_fetcher() { return form_fetcher_; }
+
+  base::PassKey<class ChangePasswordFormFinderTest> pass_key() {
+    return base::PassKey<class ChangePasswordFormFinderTest>();
+  }
+
+ private:
+  autofill::test::AutofillUnitTestEnvironment autofill_environment_{
+      {.disable_server_communication = true}};
+  password_manager::FakeFormFetcher form_fetcher_;
+  password_manager::StubPasswordManagerDriver driver_;
+};
+
+TEST_F(ChangePasswordFormFinderTest, PasswordChangeFormFound) {
+  std::vector<autofill::FormFieldData> fields;
+  fields.push_back(CreateTestFormField(
+      /*label=*/"Password:", /*name=*/"password",
+      /*value=*/"", autofill::FormControlType::kInputPassword));
+  fields.push_back(CreateTestFormField(
+      /*label=*/"New password:", /*name=*/"new_password_1",
+      /*value=*/"", autofill::FormControlType::kInputPassword));
+  fields.push_back(CreateTestFormField(
+      /*label=*/"Password confirmation:", /*name=*/"new_password_2",
+      /*value=*/"", autofill::FormControlType::kInputPassword));
+  autofill::FormData form;
+  form.set_url(GURL("https://www.foo.com"));
+  form.set_fields(std::move(fields));
+  auto form_manager = CreateFormManager(form);
+
+  base::MockOnceCallback<void(password_manager::PasswordFormManager*)>
+      completion_callback;
+  base::MockCallback<
+      base::OnceCallback<void(optimization_guide::OnAIPageContentDone)>>
+      capture_annotated_page_content;
+  ChangePasswordFormFinder form_waiter(pass_key(), web_contents(),
+                                       completion_callback.Get(),
+                                       capture_annotated_page_content.Get());
+
+  ASSERT_TRUE(form_waiter.form_waiter());
+  EXPECT_CALL(capture_annotated_page_content, Run).Times(0);
+  EXPECT_CALL(completion_callback, Run(form_manager.get()));
+  static_cast<password_manager::PasswordFormManagerObserver*>(
+      form_waiter.form_waiter())
+      ->OnPasswordFormParsed(form_manager.get());
+}
+
+TEST_F(ChangePasswordFormFinderTest,
+       AnnotatedPageContextRequestedWhenFormNotFound) {
+  base::MockOnceCallback<void(password_manager::PasswordFormManager*)>
+      completion_callback;
+  base::MockCallback<
+      base::OnceCallback<void(optimization_guide::OnAIPageContentDone)>>
+      capture_annotated_page_content;
+  auto form_finder = std::make_unique<ChangePasswordFormFinder>(
+      pass_key(), web_contents(), completion_callback.Get(),
+      capture_annotated_page_content.Get());
+
+  ASSERT_TRUE(form_finder->form_waiter());
+  static_cast<content::WebContentsObserver*>(form_finder->form_waiter())
+      ->DocumentOnLoadCompletedInPrimaryMainFrame();
+
+  EXPECT_CALL(capture_annotated_page_content, Run)
+      .WillOnce(base::test::RunOnceCallback<0>(
+          optimization_guide::AIPageContentResult()));
+  EXPECT_CALL(completion_callback, Run(nullptr));
+  task_environment()->FastForwardBy(
+      ChangePasswordFormWaiter::kChangePasswordFormWaitingTimeout);
+}
diff --git a/chrome/browser/password_manager/password_change/change_password_form_waiter.h b/chrome/browser/password_manager/password_change/change_password_form_waiter.h
index cea6afc..fb63ad2f 100644
--- a/chrome/browser/password_manager/password_change/change_password_form_waiter.h
+++ b/chrome/browser/password_manager/password_change/change_password_form_waiter.h
@@ -34,12 +34,6 @@
 
   ~ChangePasswordFormWaiter() override;
 
-#if defined(UNIT_TEST)
-  void MarkPageFinishedLoading() {
-    DocumentOnLoadCompletedInPrimaryMainFrame();
-  }
-#endif
-
  private:
   // password_manager::PasswordFormManagerObserver Impl
   void OnPasswordFormParsed(
diff --git a/chrome/browser/password_manager/password_change_browsertest.cc b/chrome/browser/password_manager/password_change_browsertest.cc
index 36da51dd..62b08d1 100644
--- a/chrome/browser/password_manager/password_change_browsertest.cc
+++ b/chrome/browser/password_manager/password_change_browsertest.cc
@@ -979,3 +979,32 @@
   browser()->tab_strip_model()->ActivateTabAt(0);
   EXPECT_TRUE(prompt_observer.IsBubbleDisplayedAutomatically());
 }
+
+IN_PROC_BROWSER_TEST_F(PasswordChangeBrowserTest, OTPDetectionHaltsTheFlow) {
+  SetPrivacyNoticeAcceptedPref();
+  const GURL main_url = WebContents()->GetLastCommittedURL();
+  EXPECT_CALL(*affiliation_service(), GetChangePasswordURL(main_url))
+      .WillOnce(testing::Return(
+          embedded_test_server()->GetURL("/password/done.html")));
+
+  StartPasswordChange(main_url, u"test", u"pa$$word", WebContents());
+
+  base::WeakPtr<PasswordChangeDelegate> delegate =
+      password_change_service()
+          ->GetPasswordChangeDelegate(
+              browser()->tab_strip_model()->GetWebContentsAt(0))
+          ->AsWeakPtr();
+  ASSERT_TRUE(delegate);
+  EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
+            delegate->GetCurrentState());
+
+  BubbleObserver prompt_observer(WebContents());
+
+  delegate->OnOtpFieldDetected(
+      browser()->tab_strip_model()->GetWebContentsAt(1));
+
+  EXPECT_EQ(PasswordChangeDelegate::State::kOtpDetected,
+            delegate->GetCurrentState());
+  EXPECT_TRUE(prompt_observer.IsBubbleDisplayedAutomatically());
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+}
diff --git a/chrome/browser/password_manager/password_change_delegate.h b/chrome/browser/password_manager/password_change_delegate.h
index 1df35eb0..d346332 100644
--- a/chrome/browser/password_manager/password_change_delegate.h
+++ b/chrome/browser/password_manager/password_change_delegate.h
@@ -94,6 +94,8 @@
 
   virtual void OnPrivacyNoticeAccepted() = 0;
 
+  virtual void OnOtpFieldDetected(content::WebContents* web_contents) = 0;
+
   // Adds/removes an observer.
   virtual void AddObserver(Observer* observer) = 0;
   virtual void RemoveObserver(Observer* observer) = 0;
diff --git a/chrome/browser/password_manager/password_change_delegate_impl.cc b/chrome/browser/password_manager/password_change_delegate_impl.cc
index 2861e5cf..161fb39 100644
--- a/chrome/browser/password_manager/password_change_delegate_impl.cc
+++ b/chrome/browser/password_manager/password_change_delegate_impl.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/password_manager/password_change/change_form_submission_verifier.h"
-#include "chrome/browser/password_manager/password_change/change_password_form_waiter.h"
+#include "chrome/browser/password_manager/password_change/change_password_form_finder.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
@@ -101,6 +101,7 @@
 void DisplayChangePasswordBubbleAutomatically(
     base::WeakPtr<content::WebContents> original_tab,
     base::WeakPtr<content::WebContents> tab_with_password_change) {
+#if !BUILDFLAG(IS_ANDROID)
   for (auto web_content : {original_tab, tab_with_password_change}) {
     if (!web_content) {
       continue;
@@ -110,6 +111,7 @@
       manage_controller->ShowChangePasswordBubble();
     }
   }
+#endif
 }
 
 std::unique_ptr<BrowserSavePasswordProgressLogger> GetLoggerIfAvailable(
@@ -197,16 +199,16 @@
   }
   executor_ = new_tab->GetWeakPtr();
 
-  form_waiter_ = std::make_unique<ChangePasswordFormWaiter>(
+  form_finder_ = std::make_unique<ChangePasswordFormFinder>(
       executor_.get(),
-      base::BindOnce(&PasswordChangeDelegateImpl::OnPasswordChangeFormParsed,
+      base::BindOnce(&PasswordChangeDelegateImpl::OnPasswordChangeFormFound,
                      weak_ptr_factory_.GetWeakPtr()));
   Observe(executor_.get());
 }
 
-void PasswordChangeDelegateImpl::OnPasswordChangeFormParsed(
+void PasswordChangeDelegateImpl::OnPasswordChangeFormFound(
     password_manager::PasswordFormManager* form_manager) {
-  form_waiter_.reset();
+  form_finder_.reset();
 
   LogPasswordFormDetectedMetric(/*form_detected=*/form_manager,
                                 base::Time::Now() - flow_start_time_);
@@ -275,6 +277,25 @@
   }
 }
 
+void PasswordChangeDelegateImpl::OnOtpFieldDetected(
+    content::WebContents* web_contents) {
+  if (!executor_ || web_contents != executor_.get()) {
+    return;
+  }
+
+  // OTP is relevant only when the change password flow is "ongoing", other
+  // states should be disregarded.
+  if (current_state_ != State::kChangingPassword &&
+      current_state_ != State::kWaitingForChangePasswordForm) {
+    return;
+  }
+
+  form_finder_.reset();
+  submission_verifier_.reset();
+
+  UpdateState(State::kOtpDetected);
+}
+
 #if !BUILDFLAG(IS_ANDROID)
 void PasswordChangeDelegateImpl::OpenPasswordChangeTab() {
   if (executor_) {
diff --git a/chrome/browser/password_manager/password_change_delegate_impl.h b/chrome/browser/password_manager/password_change_delegate_impl.h
index aba5ba6..87c22ea 100644
--- a/chrome/browser/password_manager/password_change_delegate_impl.h
+++ b/chrome/browser/password_manager/password_change_delegate_impl.h
@@ -27,7 +27,7 @@
 }  // namespace password_manager
 
 class ChangeFormSubmissionVerifier;
-class ChangePasswordFormWaiter;
+class ChangePasswordFormFinder;
 
 // This class controls password change process including acceptance of privacy
 // notice, opening of a new tab, navigation to the change password url, password
@@ -60,7 +60,7 @@
     test_navigator_ = navigator;
   }
 
-  ChangePasswordFormWaiter* form_waiter() { return form_waiter_.get(); }
+  ChangePasswordFormFinder* form_finder() { return form_finder_.get(); }
 #endif
 
  private:
@@ -74,6 +74,7 @@
   void OpenPasswordChangeTab() override;
 #endif
   void OnPasswordFormSubmission(content::WebContents* web_contents) override;
+  void OnOtpFieldDetected(content::WebContents* web_contents) override;
   void OnPrivacyNoticeAccepted() override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
@@ -92,7 +93,7 @@
   // Updates `current_state_` and notifies `observers_`.
   void UpdateState(State new_state);
 
-  void OnPasswordChangeFormParsed(
+  void OnPasswordChangeFormFound(
       password_manager::PasswordFormManager* form_manager);
 
   void OnChangeFormSubmissionVerified(bool result);
@@ -112,8 +113,8 @@
 
   State current_state_ = static_cast<State>(-1);
 
-  // Class which awaits for change password form to appear.
-  std::unique_ptr<ChangePasswordFormWaiter> form_waiter_;
+  // Helper class which looks for a change password form.
+  std::unique_ptr<ChangePasswordFormFinder> form_finder_;
 
   // Helper class which submits a form and verifies submission.
   std::unique_ptr<ChangeFormSubmissionVerifier> submission_verifier_;
diff --git a/chrome/browser/password_manager/password_change_delegate_impl_unittest.cc b/chrome/browser/password_manager/password_change_delegate_impl_unittest.cc
index 1eaa4944..4ec1a3a 100644
--- a/chrome/browser/password_manager/password_change_delegate_impl_unittest.cc
+++ b/chrome/browser/password_manager/password_change_delegate_impl_unittest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
-#include "chrome/browser/password_manager/password_change/change_password_form_waiter.h"
+#include "chrome/browser/password_manager/password_change/change_password_form_finder.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
@@ -48,24 +48,6 @@
             base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
   ~PasswordChangeDelegateImplTest() override = default;
 
-  std::unique_ptr<PasswordChangeDelegateImpl> CreateDelegate() {
-    auto delegate = std::make_unique<PasswordChangeDelegateImpl>(
-        GURL(kChangePasswordURL), kTestEmail, kPassword, web_contents());
-    delegate->SetNavigator(&navigator_);
-    delegate->OfferPasswordChangeUi();
-    return delegate;
-  }
-
-  std::unique_ptr<content::WebContents> CreateWebContents() {
-    auto contents = content::WebContentsTester::CreateTestWebContents(
-        web_contents()->GetBrowserContext(), nullptr);
-    // `ChromePasswordManagerClient` observes `AutofillManager`s, so
-    // `ChromeAutofillClient` needs to be set up, too.
-    autofill::ChromeAutofillClient::CreateForWebContents(contents.get());
-    ChromePasswordManagerClient::CreateForWebContents(contents.get());
-    return contents;
-  }
-
   void FastForwardBy(base::TimeDelta delta) {
     task_environment()->FastForwardBy(delta);
   }
@@ -93,27 +75,45 @@
                       return std::make_unique<testing::NiceMock<
                           MockOptimizationGuideKeyedService>>();
                     })));
+    delegate_ = std::make_unique<PasswordChangeDelegateImpl>(
+        GURL(kChangePasswordURL), kTestEmail, kPassword, web_contents());
+    delegate_->SetNavigator(&navigator_);
+    delegate_->OfferPasswordChangeUi();
+
+    new_web_contents_ = content::WebContentsTester::CreateTestWebContents(
+        web_contents()->GetBrowserContext(), nullptr);
+    // `ChromePasswordManagerClient` observes `AutofillManager`s, so
+    // `ChromeAutofillClient` needs to be set up, too.
+    autofill::ChromeAutofillClient::CreateForWebContents(
+        new_web_contents_.get());
+    ChromePasswordManagerClient::CreateForWebContents(new_web_contents_.get());
   }
 
   void TearDown() override {
+    delegate_.reset();
+    new_web_contents_.reset();
     mock_optimization_guide_keyed_service_ = nullptr;
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
+  PasswordChangeDelegate* delegate() { return delegate_.get(); }
+  content::WebContents* new_web_contents() { return new_web_contents_.get(); }
+
+  void ResetDelegate() { delegate_.reset(); }
+
  protected:
   raw_ptr<MockOptimizationGuideKeyedService>
       mock_optimization_guide_keyed_service_;
 
  private:
   MockPageNavigator navigator_;
+  std::unique_ptr<content::WebContents> new_web_contents_;
+  std::unique_ptr<PasswordChangeDelegateImpl> delegate_;
 };
 
 TEST_F(PasswordChangeDelegateImplTest, WaitingForAgreement) {
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  delegate->StartPasswordChangeFlow();
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
 
   EXPECT_EQ(
       prefs()->GetInteger(optimization_guide::prefs::GetSettingEnabledPrefName(
@@ -123,9 +123,9 @@
           optimization_guide::prefs::FeatureOptInState::kNotInitialized));
 
   EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForAgreement,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 
-  delegate->OnPrivacyNoticeAccepted();
+  delegate()->OnPrivacyNoticeAccepted();
   SetOptimizationFeatureEnabled(/*enabled=*/true);
   // Both pref and state reflect acceptance.
   EXPECT_EQ(
@@ -134,28 +134,25 @@
               kPasswordChangeSubmission)),
       static_cast<int>(optimization_guide::prefs::FeatureOptInState::kEnabled));
   EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 }
 
 TEST_F(PasswordChangeDelegateImplTest, PasswordChangeFormNotFound) {
   SetOptimizationFeatureEnabled(/*enabled=*/true);
   base::HistogramTester histogram_tester;
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  delegate->StartPasswordChangeFlow();
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
 
   EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 
-  static_cast<PasswordChangeDelegateImpl*>(delegate.get())
-      ->form_waiter()
-      ->MarkPageFinishedLoading();
-  FastForwardBy(ChangePasswordFormWaiter::kChangePasswordFormWaitingTimeout);
+  static_cast<PasswordChangeDelegateImpl*>(delegate())
+      ->form_finder()
+      ->RespondWithFormNotFound();
 
   EXPECT_EQ(PasswordChangeDelegate::State::kChangePasswordFormNotFound,
-            delegate->GetCurrentState());
-  delegate.reset();
+            delegate()->GetCurrentState());
+  ResetDelegate();
   histogram_tester.ExpectUniqueSample(
       PasswordChangeDelegateImpl::kFinalPasswordChangeStatusHistogram,
       PasswordChangeDelegate::State::kChangePasswordFormNotFound, 1);
@@ -163,33 +160,28 @@
 
 TEST_F(PasswordChangeDelegateImplTest, RestartPasswordChange) {
   SetOptimizationFeatureEnabled(/*enabled=*/true);
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  delegate->StartPasswordChangeFlow();
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
 
   EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 
-  static_cast<PasswordChangeDelegateImpl*>(delegate.get())
-      ->form_waiter()
-      ->MarkPageFinishedLoading();
-  FastForwardBy(ChangePasswordFormWaiter::kChangePasswordFormWaitingTimeout);
+  static_cast<PasswordChangeDelegateImpl*>(delegate())
+      ->form_finder()
+      ->RespondWithFormNotFound();
 
   EXPECT_EQ(PasswordChangeDelegate::State::kChangePasswordFormNotFound,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  delegate->Restart();
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->Restart();
   EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
-            delegate->GetCurrentState());
+            delegate()->GetCurrentState());
 }
 
 TEST_F(PasswordChangeDelegateImplTest, MetricsReportedFlowOffered) {
   base::HistogramTester histogram_tester;
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-  delegate.reset();
+  ResetDelegate();
   histogram_tester.ExpectUniqueSample(
       PasswordChangeDelegateImpl::kFinalPasswordChangeStatusHistogram,
       PasswordChangeDelegate::State::kOfferingPasswordChange, 1);
@@ -199,11 +191,9 @@
        MetricsReportedFlowCanceledInPrivacyNotice) {
   SetOptimizationFeatureEnabled(/*enabled=*/false);
   base::HistogramTester histogram_tester;
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-  delegate->StartPasswordChangeFlow();
+  delegate()->StartPasswordChangeFlow();
 
-  delegate.reset();
+  ResetDelegate();
   histogram_tester.ExpectUniqueSample(
       PasswordChangeDelegateImpl::kFinalPasswordChangeStatusHistogram,
       PasswordChangeDelegate::State::kWaitingForAgreement, 1);
@@ -213,11 +203,10 @@
        MetricsReportedFlowCanceledDuringSignInCheck) {
   SetOptimizationFeatureEnabled(/*enabled=*/true);
   base::HistogramTester histogram_tester;
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegate> delegate = CreateDelegate();
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  delegate->StartPasswordChangeFlow();
-  delegate.reset();
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
+
+  ResetDelegate();
   histogram_tester.ExpectUniqueSample(
       PasswordChangeDelegateImpl::kFinalPasswordChangeStatusHistogram,
       PasswordChangeDelegate::State::kWaitingForChangePasswordForm, 1);
@@ -227,14 +216,64 @@
        MetricsReportedWasPasswordChangeNewTabFocused) {
   SetOptimizationFeatureEnabled(/*enabled=*/true);
   base::HistogramTester histogram_tester;
-  std::unique_ptr<content::WebContents> test_web_contents = CreateWebContents();
-  std::unique_ptr<PasswordChangeDelegateImpl> delegate = CreateDelegate();
-  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(test_web_contents.get()));
-  static_cast<PasswordChangeDelegate*>(delegate.get())
-      ->StartPasswordChangeFlow();
-  static_cast<content::WebContentsObserver*>(delegate.get())
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
+  static_cast<content::WebContentsObserver*>(
+      static_cast<PasswordChangeDelegateImpl*>(delegate()))
       ->OnVisibilityChanged(content::Visibility::VISIBLE);
-  delegate.reset();
+  ResetDelegate();
   histogram_tester.ExpectUniqueSample(
       PasswordChangeDelegateImpl::kWasPasswordChangeNewTabFocused, true, 1);
 }
+
+TEST_F(PasswordChangeDelegateImplTest,
+       OtpDetectionIgnoredWhenFlowIsNotStarted) {
+  EXPECT_CALL(navigator(), OpenURL).Times(0);
+
+  ASSERT_EQ(PasswordChangeDelegate::State::kOfferingPasswordChange,
+            delegate()->GetCurrentState());
+
+  delegate()->OnOtpFieldDetected(web_contents());
+  EXPECT_EQ(PasswordChangeDelegate::State::kOfferingPasswordChange,
+            delegate()->GetCurrentState());
+}
+
+TEST_F(PasswordChangeDelegateImplTest,
+       OtpDetectionIgnoredWhenWaitingForAgreement) {
+  EXPECT_CALL(navigator(), OpenURL).Times(0);
+  delegate()->StartPasswordChangeFlow();
+
+  ASSERT_EQ(PasswordChangeDelegate::State::kWaitingForAgreement,
+            delegate()->GetCurrentState());
+
+  delegate()->OnOtpFieldDetected(new_web_contents());
+  EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForAgreement,
+            delegate()->GetCurrentState());
+}
+
+TEST_F(PasswordChangeDelegateImplTest, OtpDetectionIgnoredOnOriginalTab) {
+  SetOptimizationFeatureEnabled(/*enabled=*/true);
+
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
+
+  EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
+            delegate()->GetCurrentState());
+
+  delegate()->OnOtpFieldDetected(web_contents());
+  EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
+            delegate()->GetCurrentState());
+}
+
+TEST_F(PasswordChangeDelegateImplTest, OtpDetectionProcessed) {
+  SetOptimizationFeatureEnabled(/*enabled=*/true);
+  EXPECT_CALL(navigator(), OpenURL).WillOnce(Return(new_web_contents()));
+  delegate()->StartPasswordChangeFlow();
+
+  EXPECT_EQ(PasswordChangeDelegate::State::kWaitingForChangePasswordForm,
+            delegate()->GetCurrentState());
+
+  delegate()->OnOtpFieldDetected(new_web_contents());
+  EXPECT_EQ(PasswordChangeDelegate::State::kOtpDetected,
+            delegate()->GetCurrentState());
+}
diff --git a/chrome/browser/password_manager/password_change_delegate_mock.h b/chrome/browser/password_manager/password_change_delegate_mock.h
index 4c95071..8524c55e 100644
--- a/chrome/browser/password_manager/password_change_delegate_mock.h
+++ b/chrome/browser/password_manager/password_change_delegate_mock.h
@@ -31,12 +31,15 @@
               (const override));
   MOCK_METHOD(void, Stop, (), (override));
   MOCK_METHOD(void, Restart, (), (override));
+#if !BUILDFLAG(IS_ANDROID)
   MOCK_METHOD(void, OpenPasswordChangeTab, (), (override));
+#endif
   MOCK_METHOD(void,
               OnPasswordFormSubmission,
               (content::WebContents*),
               (override));
   MOCK_METHOD(void, OnPrivacyNoticeAccepted, (), (override));
+  MOCK_METHOD(void, OnOtpFieldDetected, (content::WebContents*), (override));
   MOCK_METHOD(void, AddObserver, (Observer*), (override));
   MOCK_METHOD(void, RemoveObserver, (Observer*), (override));
   MOCK_METHOD(std::u16string, GetDisplayOrigin, (), (const override));
diff --git a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
index 2dafa11..d2a36ec 100644
--- a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
+++ b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.cc
@@ -60,18 +60,31 @@
     active_tab_ = tab;
   }
 
-  // TabRemoved is not triggered when the tab model goes away. But it does not
-  // cause holding a dead tab in active_tab_ because `ActiveTabTracker` itself
-  // is removed anyway at `ActiveTabObserver::OnTabModelRemoved()`.
-  void TabRemoved(TabAndroid* tab) override {
+  // OnFinishingTabClosure is not triggered when the tab model goes away. But it
+  // does not cause holding a dead tab in active_tab_ because `ActiveTabTracker`
+  // itself is removed anyway at `ActiveTabObserver::OnTabModelRemoved()`.
+  void OnFinishingTabClosure(TabAndroid* tab) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (tab == active_tab_) {
       active_tab_ = nullptr;
     }
   }
 
+  // This is triggered when a tab is removed from a tab model (e.g. tab is moved
+  // to another window).
+  void TabRemoved(TabAndroid* tab) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    if (tab == active_tab_) {
+      if (tab && tab->web_contents()) {
+        PageLiveStateDecorator::SetIsActiveTab(tab->web_contents(), false);
+      }
+      active_tab_ = nullptr;
+    }
+  }
+
  private:
-  // The cached TabAndroid* is cleared on TabRemoved().
+  // The cached TabAndroid* is cleared on OnFinishingTabClosure() or
+  // TabRemoved() so that no obsolete pointer is left.
   raw_ptr<TabAndroid> active_tab_ GUARDED_BY_CONTEXT(sequence_checker_) =
       nullptr;
 
diff --git a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
index 97c2237c..e9f3b28 100644
--- a/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
+++ b/chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc
@@ -310,7 +310,7 @@
       contents2, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
       &PageLiveStateDecorator::Data::IsActiveTab, true);
 
-  tab_model.GetObserver()->TabRemoved(tab2.get());
+  tab_model.GetObserver()->OnFinishingTabClosure(tab2.get());
   tab_model.GetObserver()->DidSelectTab(tab1.get(),
                                         TabModel::TabSelectionType::FROM_USER);
 
@@ -325,6 +325,63 @@
   TabModelList::RemoveTabModel(&tab_model);
 }
 
+TEST_F(PageLiveStateDecoratorHelperTabsTest, IsActiveTabAfterRemoved) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      chrome::android::kProcessRankPolicyAndroid);
+  auto helper = std::make_unique<PageLiveStateDecoratorHelper>();
+  TestTabModel tab_model(profile());
+  TabModelList::AddTabModel(&tab_model);
+  std::unique_ptr<content::WebContents> web_contents1(CreateTestWebContents());
+  std::unique_ptr<content::WebContents> web_contents2(CreateTestWebContents());
+  content::WebContents* contents1 = web_contents1.get();
+  content::WebContents* contents2 = web_contents2.get();
+  std::unique_ptr<TabAndroid> tab1 =
+      TabAndroid::CreateForTesting(profile(), 1, std::move(web_contents1));
+  std::unique_ptr<TabAndroid> tab2 =
+      TabAndroid::CreateForTesting(profile(), 2, std::move(web_contents2));
+
+  tab_model.GetObserver()->DidSelectTab(tab1.get(),
+                                        TabModel::TabSelectionType::FROM_USER);
+
+  testing::TestPageNodeProperty(
+      contents1, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, true);
+  testing::TestPageNodeProperty(
+      contents2, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, false);
+
+  tab_model.GetObserver()->DidSelectTab(tab2.get(),
+                                        TabModel::TabSelectionType::FROM_USER);
+
+  testing::TestPageNodeProperty(
+      contents1, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, false);
+  testing::TestPageNodeProperty(
+      contents2, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, true);
+
+  tab_model.GetObserver()->TabRemoved(tab2.get());
+
+  // After removed the tab should not be active anymore.
+  testing::TestPageNodeProperty(
+      contents2, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, false);
+
+  // Destroy tab2.
+  tab2.reset();
+
+  // Moving to the tab1 from tab2 does not cause invalid pointer access.
+  tab_model.GetObserver()->DidSelectTab(tab1.get(),
+                                        TabModel::TabSelectionType::FROM_USER);
+
+  testing::TestPageNodeProperty(
+      contents1, &PageLiveStateDecorator::Data::GetOrCreateForPageNode,
+      &PageLiveStateDecorator::Data::IsActiveTab, true);
+
+  TabModelList::RemoveTabModel(&tab_model);
+}
+
 TEST_F(PageLiveStateDecoratorHelperTabsTest, IsActiveTabWithMultipleTabModels) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
diff --git a/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc b/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc
index ca8fbacd..7c1d247 100644
--- a/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc
+++ b/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc
@@ -2660,11 +2660,11 @@
     log_watcher.FlushAndStopWatching();
     ASSERT_FALSE(log_watcher.last_auto_picture_in_picture_event_info().empty());
     const std::string expected_auto_pip_info =
-        "{\"auto_picture_in_picture_info\":\"{Reason: MediaPlayback, has audio "
-        "focus: true, is_playing: true, was recently audible: true, has safe "
-        "url: true, meets media engagement conditions: true, blocked due to "
-        "content setting: "
-        "false}\",\"event\":\"kAutoPictureInPictureInfoChanged\"}";
+        "{\"auto_picture_in_picture_info\":{\"Reason\":\"MediaPlayback\","
+        "\"blocked_due_to_content_setting\":false,\"has_audio_focus\":true,"
+        "\"has_safe_url\":true,\"is_playing\":true,\"meets_media_engagement_"
+        "conditions\":true,\"was_recently_audible\":true},\"event\":"
+        "\"kAutoPictureInPictureInfoChanged\"}";
     EXPECT_EQ(expected_auto_pip_info,
               log_watcher.last_auto_picture_in_picture_event_info());
   }
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 14d207b..fbfd810 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -69,6 +69,7 @@
 #include "components/bookmarks/managed/managed_bookmarks_policy_handler.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/certificate_transparency/pref_names.h"
+#include "components/collaboration/public/pref_names.h"
 #include "components/commerce/core/pref_names.h"
 #include "components/component_updater/pref_names.h"
 #include "components/content_settings/core/browser/cookie_settings_policy_handler.h"
@@ -3386,6 +3387,12 @@
   handlers->AddHandler(std::make_unique<GenAiDefaultSettingsPolicyHandler>(
       std::move(gen_ai_default_policies)));
 
+  handlers->AddHandler(std::make_unique<CloudUserOnlyPolicyHandler>(
+      std::make_unique<SimplePolicyHandler>(
+          key::kTabGroupSharingSettings,
+          collaboration::prefs::kSharedTabGroupsManagedAccountSetting,
+          base::Value::Type::INTEGER)));
+
 #if BUILDFLAG(IS_CHROMEOS)
   handlers->AddHandler(std::make_unique<SimpleDeprecatingPolicyHandler>(
       std::make_unique<SimplePolicyHandler>(
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index a776ea45..8d9d0d9 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -252,10 +252,17 @@
      * last opened. Used to determine whether to show on startup a message informing the user about
      * the setting change.
      */
-    public static final String DEFAULT_OS_ADVANCED_PROTECTION_SETTING =
+    public static final String OS_ADVANCED_PROTECTION_SETTING =
             "Chrome.OsAdvancedProtection.DefaultEnabled";
 
     /**
+     * Indicates the later time of: - user changing advanced-protection android-OS setting OR - user
+     * launching Chrome.
+     */
+    public static final String OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME =
+            "Chrome.OsAdvancedProtection.UpdatedTime";
+
+    /**
      * Indicates that Chrome should show an alert to the user about data privacy if the device lock
      * is removed.
      */
@@ -1009,7 +1016,6 @@
                 DEFAULT_BROWSER_PROMO_PROMOED_COUNT,
                 DEFAULT_BROWSER_PROMO_SESSION_COUNT,
                 DEFAULT_ENABLED_DESKTOP_SITE_GLOBAL_SETTING,
-                DEFAULT_OS_ADVANCED_PROTECTION_SETTING,
                 DEPRECATED_HOMEPAGE_LOCATION_POLICY,
                 DEPRECATED_HOMEPAGE_PARTNER_CUSTOMIZED_DEFAULT_URI,
                 DEVICE_LOCK_SHOW_ALERT_IF_REMOVED,
@@ -1069,6 +1075,8 @@
                 OFFLINE_MEASUREMENTS_USER_AGENT_STRING,
                 OMNIBOX_CACHED_ZERO_SUGGEST_GROUPS_INFO,
                 OPTIMIZATION_GUIDE_PUSH_NOTIFICATION_CACHE.pattern(),
+                OS_ADVANCED_PROTECTION_SETTING,
+                OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
                 PASSWORD_PROTECTION_ACCOUNTS,
                 PERSISTENT_OFFLINE_CONTENT_AVAILABILITY_STATUS,
                 PIH_PRIVACY_NOTICE_CLOSED,
diff --git a/chrome/browser/prefs/BUILD.gn b/chrome/browser/prefs/BUILD.gn
index 0553710..4b2f1238 100644
--- a/chrome/browser/prefs/BUILD.gn
+++ b/chrome/browser/prefs/BUILD.gn
@@ -76,6 +76,7 @@
     "//components/browser_sync:switches",
     "//components/browsing_data/core",
     "//components/certificate_transparency",
+    "//components/collaboration/public:prefs",
     "//components/commerce/core:pref_names",
     "//components/content_settings/core/browser",
     "//components/custom_handlers",
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 259168ef..d6e6788 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -102,6 +102,7 @@
 #include "components/breadcrumbs/core/breadcrumbs_status.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/certificate_transparency/pref_names.h"
+#include "components/collaboration/public/pref_names.h"
 #include "components/commerce/core/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -1863,6 +1864,7 @@
   ChromeVersionService::RegisterProfilePrefs(registry);
   chrome_browser_net::NetErrorTabHelper::RegisterProfilePrefs(registry);
   chrome_prefs::RegisterProfilePrefs(registry);
+  collaboration::prefs::RegisterProfilePrefs(registry);
   commerce::RegisterPrefs(registry);
   enterprise::RegisterIdentifiersProfilePrefs(registry);
   enterprise_connectors::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent_eea_dropdown.xml b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent_eea_dropdown.xml
index 6a55a5eba..a9960a9 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent_eea_dropdown.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_consent_eea_dropdown.xml
@@ -36,7 +36,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingStart="14dp"
-        android:text="@string/privacy_sandbox_m1_consent_learn_more_bullet_2_description_no_link"
+        android:text="@string/privacy_sandbox_m1_consent_learn_more_bullet_2_description_clank"
         app:leading="@dimen/text_size_medium_leading"
         style="@style/TextAppearance.TextMedium.Secondary" />
 
@@ -53,7 +53,7 @@
         android:layout_marginBottom="@dimen/promo_between_text_margin"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/privacy_sandbox_m1_consent_learn_more_link"
+        android:text="@string/privacy_sandbox_m1_notice_learn_more_v2_clank"
         app:leading="@dimen/text_size_medium_leading"
         style="@style/TextAppearance.TextMedium.Secondary" />
 
diff --git a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_eea_site_suggested_ads_dropdown.xml b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_eea_site_suggested_ads_dropdown.xml
index 87e29b0..bbcaa87 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_eea_site_suggested_ads_dropdown.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_eea_site_suggested_ads_dropdown.xml
@@ -27,7 +27,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingStart="14dp"
-        android:text="@string/privacy_sandbox_m1_notice_eea_site_suggested_ads_learn_more_bullet_1_description_no_link"
+        android:text="@string/privacy_sandbox_m1_notice_eea_site_suggested_ads_learn_more_bullet_1_description_clank"
         app:leading="@dimen/text_size_medium_leading"
         style="@style/TextAppearance.TextMedium.Secondary" />
 
diff --git a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_row_dropdown.xml b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_row_dropdown.xml
index f51bca9..885ffc8a 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_row_dropdown.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/layout/privacy_sandbox_notice_row_dropdown.xml
@@ -118,7 +118,7 @@
         android:layout_marginBottom="@dimen/promo_between_text_margin"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/privacy_sandbox_m1_notice_row_learn_more_description_5_v2_no_link"
+        android:text="@string/privacy_sandbox_m1_notice_row_learn_more_description_5_v2_clank"
         app:leading="@dimen/text_size_medium_leading"
         style="@style/TextAppearance.TextMedium.Secondary" />
 
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsentEEA.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsentEEA.java
index 4812906c..e9a10901 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsentEEA.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsentEEA.java
@@ -200,6 +200,9 @@
             description2.setText(
                     context.getString(
                             R.string.privacy_sandbox_m1_consent_description_1_content_parity));
+            mLearnMoreLinkString =
+                    R.string
+                            .privacy_sandbox_m1_consent_learn_more_bullet_2_description_content_parity_clank;
         }
     }
 
@@ -277,21 +280,12 @@
                             .findViewById(R.id.privacy_sandbox_learn_more_text)
                             .setVisibility(View.GONE);
                 }
-                if (ChromeFeatureList.isEnabled(
-                        ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY)) {
-                    mLearnMoreText = mContentView.findViewById(mLearnMoreTextIdRes);
-                    mLearnMoreText.setText(
-                            getContext()
-                                    .getString(
-                                            R.string
-                                                    .privacy_sandbox_m1_consent_learn_more_bullet_2_description_no_link_content_parity));
-                }
 
                 mScrollView.post(
                         () -> {
                             mScrollView.scrollTo(0, mDropdownElement.getTop());
                         });
-                handlePrivacyPolicyFeature();
+                handlePrivacyPolicyLink();
             }
 
             mExpandArrowView.setChecked(isDropdownExpanded());
@@ -317,62 +311,45 @@
         mConsentViewContainer.setVisibility(View.VISIBLE);
     }
 
-    // If all Ad Topics Content Parity, Ads API UX Enhancements and Privacy Policy features are
-    // enabled, we want to show the new ad topics content parity learn more bullet description with
-    // the privacy policy link.
-    private void handleAdTopicsContentParityPrivacyPolicyEnabled() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY)
-                && ChromeFeatureList.isEnabled(
-                        ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)) {
-            mLearnMoreLinkString =
-                    R.string
-                            .privacy_sandbox_m1_consent_learn_more_bullet_2_description_content_parity_clank;
-        }
-    }
-
-    private void handlePrivacyPolicyFeature() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)) {
-            handleAdTopicsContentParityPrivacyPolicyEnabled();
-            mLearnMoreText = mContentView.findViewById(mLearnMoreTextIdRes);
-            mLearnMoreText.setText(
-                    SpanApplier.applySpans(
-                            getContext().getString(mLearnMoreLinkString),
-                            new SpanApplier.SpanInfo(
-                                    "<link>",
-                                    "</link>",
-                                    new ChromeClickableSpan(
-                                            getContext(), this::onPrivacyPolicyClicked))));
-            mLearnMoreText.setMovementMethod(LinkMovementMethod.getInstance());
-            if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
-                mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
-                mWebContentsObserver =
-                        new WebContentsObserver(mWebContents) {
-                            @Override
-                            public void didFirstVisuallyNonEmptyPaint() {
-                                if (!mIsPrivacyPageLoaded) {
-                                    RecordHistogram.recordTimesHistogram(
-                                            "PrivacySandbox.PrivacyPolicy.LoadingTime",
-                                            System.currentTimeMillis()
-                                                    - mPrivacyPolicyClickedTimestamp);
-                                    mIsPrivacyPageLoaded = true;
-                                }
+    private void handlePrivacyPolicyLink() {
+        mLearnMoreText = mContentView.findViewById(mLearnMoreTextIdRes);
+        mLearnMoreText.setText(
+                SpanApplier.applySpans(
+                        getContext().getString(mLearnMoreLinkString),
+                        new SpanApplier.SpanInfo(
+                                "<link>",
+                                "</link>",
+                                new ChromeClickableSpan(
+                                        getContext(), this::onPrivacyPolicyClicked))));
+        mLearnMoreText.setMovementMethod(LinkMovementMethod.getInstance());
+        if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
+            mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
+            mWebContentsObserver =
+                    new WebContentsObserver(mWebContents) {
+                        @Override
+                        public void didFirstVisuallyNonEmptyPaint() {
+                            if (!mIsPrivacyPageLoaded) {
+                                RecordHistogram.recordTimesHistogram(
+                                        "PrivacySandbox.PrivacyPolicy.LoadingTime",
+                                        System.currentTimeMillis()
+                                                - mPrivacyPolicyClickedTimestamp);
+                                mIsPrivacyPageLoaded = true;
                             }
+                        }
 
-                            @Override
-                            public void didFailLoad(
-                                    boolean isInPrimaryMainFrame,
-                                    int errorCode,
-                                    GURL failingUrl,
-                                    @LifecycleState int rfhLifecycleState) {
-                                RecordHistogram.recordSparseHistogram(
-                                        "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode",
-                                        errorCode);
-                            }
-                        };
-                mThinWebView =
-                        PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
-                                mWebContents, mProfile, mActivityWindowAndroid);
-            }
+                        @Override
+                        public void didFailLoad(
+                                boolean isInPrimaryMainFrame,
+                                int errorCode,
+                                GURL failingUrl,
+                                @LifecycleState int rfhLifecycleState) {
+                            RecordHistogram.recordSparseHistogram(
+                                    "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode", errorCode);
+                        }
+                    };
+            mThinWebView =
+                    PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
+                            mWebContents, mProfile, mActivityWindowAndroid);
         }
     }
 
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeEeaV2.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeEeaV2.java
index 4617c09..6fc15c4 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeEeaV2.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeEeaV2.java
@@ -20,7 +20,6 @@
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.content.WebContentsFactory;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeUtils;
 import org.chromium.components.browser_ui.widget.ChromeDialog;
@@ -214,7 +213,7 @@
 
             mScrollView.post(
                     () -> mScrollView.scrollTo(0, mSiteSuggestedAdsDropdownElement.getTop()));
-            handlePrivacyPolicyFeature();
+            handlePrivacyPolicyLink();
         }
 
         mSiteSuggestedAdsExpandArrowView.setChecked(isSiteSuggestedAdsDropdownExpanded());
@@ -321,54 +320,48 @@
         }
     }
 
-    private void handlePrivacyPolicyFeature() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)) {
-            mLearnMoreBullet1Description =
-                    mContentView.findViewById(
-                            R.id
-                                    .privacy_sandbox_m1_notice_eea_site_suggested_ads_learn_more_bullet_one_description);
-            mLearnMoreBullet1Description.setText(
-                    SpanApplier.applySpans(
-                            getContext()
-                                    .getString(
-                                            R.string
-                                                    .privacy_sandbox_m1_notice_eea_site_suggested_ads_learn_more_bullet_1_description_clank),
-                            new SpanApplier.SpanInfo(
-                                    "<link>",
-                                    "</link>",
-                                    new ChromeClickableSpan(
-                                            getContext(), this::onPrivacyPolicyClicked))));
-            mLearnMoreBullet1Description.setMovementMethod(LinkMovementMethod.getInstance());
-            if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
-                mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
-                mWebContentsObserver =
-                        new WebContentsObserver(mWebContents) {
-                            @Override
-                            public void didFirstVisuallyNonEmptyPaint() {
-                                if (!mIsPrivacyPageLoaded) {
-                                    RecordHistogram.recordTimesHistogram(
-                                            "PrivacySandbox.PrivacyPolicy.LoadingTime",
-                                            System.currentTimeMillis()
-                                                    - mPrivacyPolicyClickedTimestamp);
-                                    mIsPrivacyPageLoaded = true;
-                                }
+    private void handlePrivacyPolicyLink() {
+        mLearnMoreBullet1Description =
+                mContentView.findViewById(
+                        R.id
+                                .privacy_sandbox_m1_notice_eea_site_suggested_ads_learn_more_bullet_one_description);
+        mLearnMoreBullet1Description.setText(
+                SpanApplier.applySpans(
+                        mLearnMoreBullet1Description.getText().toString(),
+                        new SpanApplier.SpanInfo(
+                                "<link>",
+                                "</link>",
+                                new ChromeClickableSpan(
+                                        getContext(), this::onPrivacyPolicyClicked))));
+        mLearnMoreBullet1Description.setMovementMethod(LinkMovementMethod.getInstance());
+        if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
+            mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
+            mWebContentsObserver =
+                    new WebContentsObserver(mWebContents) {
+                        @Override
+                        public void didFirstVisuallyNonEmptyPaint() {
+                            if (!mIsPrivacyPageLoaded) {
+                                RecordHistogram.recordTimesHistogram(
+                                        "PrivacySandbox.PrivacyPolicy.LoadingTime",
+                                        System.currentTimeMillis()
+                                                - mPrivacyPolicyClickedTimestamp);
+                                mIsPrivacyPageLoaded = true;
                             }
+                        }
 
-                            @Override
-                            public void didFailLoad(
-                                    boolean isInPrimaryMainFrame,
-                                    int errorCode,
-                                    GURL failingUrl,
-                                    @LifecycleState int rfhLifecycleState) {
-                                RecordHistogram.recordSparseHistogram(
-                                        "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode",
-                                        errorCode);
-                            }
-                        };
-                mThinWebView =
-                        PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
-                                mWebContents, mProfile, mActivityWindowAndroid);
-            }
+                        @Override
+                        public void didFailLoad(
+                                boolean isInPrimaryMainFrame,
+                                int errorCode,
+                                GURL failingUrl,
+                                @LifecycleState int rfhLifecycleState) {
+                            RecordHistogram.recordSparseHistogram(
+                                    "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode", errorCode);
+                        }
+                    };
+            mThinWebView =
+                    PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
+                            mWebContents, mProfile, mActivityWindowAndroid);
         }
     }
 
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeROW.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeROW.java
index 1865e74..d263cc97 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeROW.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogNoticeROW.java
@@ -265,7 +265,7 @@
                             mScrollView.scrollTo(0, mDropdownElement.getTop());
                         });
                 handleAdsApiUxEnhancementsDropdown();
-                handlePrivacyPolicyFeature();
+                handlePrivacyPolicyLink();
             }
 
             mExpandArrowView.setChecked(isDropdownExpanded());
@@ -314,53 +314,47 @@
         }
     }
 
-    private void handlePrivacyPolicyFeature() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)) {
-            mLearnMoreDescription5V2 =
-                    mContentView.findViewById(
-                            R.id.privacy_sandbox_m1_notice_row_learn_more_description_5_v2);
-            mLearnMoreDescription5V2.setText(
-                    SpanApplier.applySpans(
-                            getContext()
-                                    .getString(
-                                            R.string
-                                                    .privacy_sandbox_m1_notice_row_learn_more_description_5_v2_clank),
-                            new SpanApplier.SpanInfo(
-                                    "<link>",
-                                    "</link>",
-                                    new ChromeClickableSpan(
-                                            getContext(), this::onPrivacyPolicyClicked))));
-            mLearnMoreDescription5V2.setMovementMethod(LinkMovementMethod.getInstance());
-            if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
-                mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
-                mWebContentsObserver =
-                        new WebContentsObserver(mWebContents) {
-                            @Override
-                            public void didFirstVisuallyNonEmptyPaint() {
-                                if (!mIsPrivacyPageLoaded) {
-                                    RecordHistogram.recordTimesHistogram(
-                                            "PrivacySandbox.PrivacyPolicy.LoadingTime",
-                                            System.currentTimeMillis()
-                                                    - mPrivacyPolicyClickedTimestamp);
-                                    mIsPrivacyPageLoaded = true;
-                                }
+    private void handlePrivacyPolicyLink() {
+        mLearnMoreDescription5V2 =
+                mContentView.findViewById(
+                        R.id.privacy_sandbox_m1_notice_row_learn_more_description_5_v2);
+        mLearnMoreDescription5V2.setText(
+                SpanApplier.applySpans(
+                        mLearnMoreDescription5V2.getText().toString(),
+                        new SpanApplier.SpanInfo(
+                                "<link>",
+                                "</link>",
+                                new ChromeClickableSpan(
+                                        getContext(), this::onPrivacyPolicyClicked))));
+        mLearnMoreDescription5V2.setMovementMethod(LinkMovementMethod.getInstance());
+        if (mThinWebView == null || mWebContents == null || mWebContents.isDestroyed()) {
+            mWebContents = WebContentsFactory.createWebContents(mProfile, true, false);
+            mWebContentsObserver =
+                    new WebContentsObserver(mWebContents) {
+                        @Override
+                        public void didFirstVisuallyNonEmptyPaint() {
+                            if (!mIsPrivacyPageLoaded) {
+                                RecordHistogram.recordTimesHistogram(
+                                        "PrivacySandbox.PrivacyPolicy.LoadingTime",
+                                        System.currentTimeMillis()
+                                                - mPrivacyPolicyClickedTimestamp);
+                                mIsPrivacyPageLoaded = true;
                             }
+                        }
 
-                            @Override
-                            public void didFailLoad(
-                                    boolean isInPrimaryMainFrame,
-                                    int errorCode,
-                                    GURL failingUrl,
-                                    @LifecycleState int rfhLifecycleState) {
-                                RecordHistogram.recordSparseHistogram(
-                                        "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode",
-                                        errorCode);
-                            }
-                        };
-                mThinWebView =
-                        PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
-                                mWebContents, mProfile, mActivityWindowAndroid);
-            }
+                        @Override
+                        public void didFailLoad(
+                                boolean isInPrimaryMainFrame,
+                                int errorCode,
+                                GURL failingUrl,
+                                @LifecycleState int rfhLifecycleState) {
+                            RecordHistogram.recordSparseHistogram(
+                                    "PrivacySandbox.PrivacyPolicy.FailedLoadErrorCode", errorCode);
+                        }
+                    };
+            mThinWebView =
+                    PrivacySandboxDialogController.createPrivacyPolicyThinWebView(
+                            mWebContents, mProfile, mActivityWindowAndroid);
         }
     }
 
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
index c5057c2..0ead026 100644
--- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
+++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
@@ -234,10 +234,7 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures({
-        ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
-        ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY
-    })
+    @EnableFeatures({ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS})
     @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY)
     // TODO(crbug.com/381241999): fix and re-enable on ARM devices.
     @DisableIf.Build(supported_abis_includes = "armeabi-v7a")
@@ -255,25 +252,6 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
-    @DisableFeatures({
-        ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY,
-        ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY
-    })
-    @DisabledTest(message = "https://crbug.com/399734809")
-    public void renderEeaConsentV2PrivacyPolicyDisabled() throws IOException {
-        mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_CONSENT);
-        launchDialog();
-        onViewWaiting(withId(R.id.privacy_sandbox_dialog));
-        onView(withId(R.id.dropdown_element)).inRoot(isDialog()).perform(scrollTo(), click());
-        renderViewWithId(
-                R.id.privacy_sandbox_dialog,
-                "privacy_sandbox_eea_consent_dialog_v2_privacy_policy_link_not_shown");
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"RenderTest"})
     @EnableFeatures({
         ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
         ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY
@@ -292,7 +270,6 @@
     @Feature({"RenderTest"})
     @EnableFeatures({
         ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
-        ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY,
         ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY
     })
     @DisabledTest(message = "https://crbug.com/399734809")
@@ -308,25 +285,6 @@
 
     @Test
     @SmallTest
-    @Feature({"RenderTest"})
-    @EnableFeatures({
-        ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
-        ChromeFeatureList.PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY
-    })
-    @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)
-    public void renderEeaConsentV2ContentParityPrivacyPolicyDisabled() throws IOException {
-        mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_CONSENT);
-        launchDialog();
-        onViewWaiting(withId(R.id.privacy_sandbox_dialog));
-        onView(withId(R.id.dropdown_element)).inRoot(isDialog()).perform(scrollTo(), click());
-        renderViewWithId(
-                R.id.privacy_sandbox_dialog,
-                "privacy_sandbox_eea_consent_dialog_v2_content_parity_privacy_policy_link_not_shown");
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)
     @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
     // TODO(crbug.com/369540483): fix and re-enable on ARM devices.
     @DisableIf.Build(supported_abis_includes = "armeabi-v7a")
@@ -375,7 +333,6 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)
     @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
     // TODO(crbug.com/381241999): fix and re-enable on ARM devices.
     @DisableIf.Build(supported_abis_includes = "armeabi-v7a")
@@ -422,10 +379,7 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures({
-        ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
-        ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY
-    })
+    @EnableFeatures({ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS})
     public void renderEeaNoticeV2PrivacyPolicyEnabled() throws IOException {
         mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_NOTICE_EEA);
         launchDialog();
@@ -567,23 +521,6 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
-    @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)
-    public void renderEeaNoticeV2PrivacyPolicyDisabled() throws IOException {
-        mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_NOTICE_EEA);
-        launchDialog();
-        onViewWaiting(withId(R.id.privacy_sandbox_dialog));
-        onView(withId(R.id.site_suggested_ads_dropdown_element))
-                .inRoot(isDialog())
-                .perform(scrollTo(), click());
-        renderViewWithId(
-                R.id.privacy_sandbox_dialog,
-                "privacy_sandbox_eea_notice_dialog_v2_privacy_policy_link_not_shown");
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"RenderTest"})
     @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
     public void renderEEANotice() throws IOException {
         ThreadUtils.runOnUiThreadBlocking(
@@ -653,30 +590,7 @@
     @Test
     @SmallTest
     @Feature({"RenderTest"})
-    @EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS)
-    @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY)
-    @DisabledTest(message = "https://crbug.com/383531831 - the test is flaky")
-    public void renderRowNoticeV2PrivacyPolicyDisabled() throws IOException {
-        mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_NOTICE_ROW);
-        launchDialog();
-        onViewWaiting(withId(R.id.privacy_sandbox_dialog));
-        onView(withId(R.id.dropdown_element)).inRoot(isDialog()).perform(scrollTo(), click());
-        onView(withId(R.id.dropdown_container)).inRoot(isDialog()).check(matches(isDisplayed()));
-        onView(withId(R.id.privacy_sandbox_m1_notice_row_learn_more_description_5_v2))
-                .inRoot(isDialog())
-                .perform(scrollTo());
-        renderViewWithId(
-                R.id.privacy_sandbox_dialog,
-                "privacy_sandbox_row_notice_dialog_v2_privacy_policy_link_not_shown");
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"RenderTest"})
-    @EnableFeatures({
-        ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS,
-        ChromeFeatureList.PRIVACY_SANDBOX_PRIVACY_POLICY
-    })
+    @EnableFeatures({ChromeFeatureList.PRIVACY_SANDBOX_ADS_API_UX_ENHANCEMENTS})
     @DisabledTest(message = "https://crbug.com/383473428 - the test is flaky")
     public void renderRowNoticeV2PrivacyPolicyEnabled() throws IOException {
         mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.M1_NOTICE_ROW);
diff --git a/chrome/browser/privacy_sandbox/android/privacy_sandbox_bridge.cc b/chrome/browser/privacy_sandbox/android/privacy_sandbox_bridge.cc
index 43c93a5..c808929 100644
--- a/chrome/browser/privacy_sandbox/android/privacy_sandbox_bridge.cc
+++ b/chrome/browser/privacy_sandbox/android/privacy_sandbox_bridge.cc
@@ -14,8 +14,6 @@
 #include "base/time/time.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_activity_types_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_activity_types_service.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
diff --git a/chrome/browser/privacy_sandbox/notice/notice_storage.cc b/chrome/browser/privacy_sandbox/notice/notice_storage.cc
index 27d8d564..81b34e0 100644
--- a/chrome/browser/privacy_sandbox/notice/notice_storage.cc
+++ b/chrome/browser/privacy_sandbox/notice/notice_storage.cc
@@ -161,9 +161,9 @@
                           const NoticeStorageData& data) {
   ScopedDictPrefUpdate update(pref_service, kNoticeDataPath);
   update.Get().SetByDottedPath(CreatePrefPath(notice, kSchemaVersionKey),
-                               data.GetSchemaVersion());
+                               data.schema_version);
 
-  for (const auto& event : data.GetNoticeEvents()) {
+  for (const auto& event : data.notice_events) {
     update.Get()
         .EnsureDict(notice)
         ->EnsureList(kEventsKey)
@@ -174,6 +174,44 @@
 
 }  // namespace
 
+std::optional<base::Time> GetNoticeFirstShownFromEvents(
+    const NoticeStorageData& notice_data) {
+  for (const auto& notice_event : notice_data.notice_events) {
+    if (notice_event->event == PrivacySandboxNoticeEvent::kShown) {
+      return notice_event->timestamp;
+    }
+  }
+  return std::nullopt;
+}
+
+std::optional<base::Time> GetNoticeLastShownFromEvents(
+    const NoticeStorageData& notice_data) {
+  for (const auto& notice_event : base::Reversed(notice_data.notice_events)) {
+    if (notice_event->event == PrivacySandboxNoticeEvent::kShown) {
+      return notice_event->timestamp;
+    }
+  }
+  return std::nullopt;
+}
+
+std::optional<NoticeEventTimestampPair>
+GetNoticeActionTakenForFirstShownFromEvents(
+    const NoticeStorageData& notice_data) {
+  std::optional<NoticeEventTimestampPair> notice_event_data;
+  int last_shown_idx = 0;
+  int first_notice_idx = 0;
+  for (const auto& event_data : notice_data.notice_events) {
+    if (event_data->event == PrivacySandboxNoticeEvent::kShown) {
+      last_shown_idx++;
+    } else if (!notice_event_data.has_value() ||
+               first_notice_idx == last_shown_idx) {
+      first_notice_idx = last_shown_idx;
+      notice_event_data = *event_data;
+    }
+  }
+  return notice_event_data;
+}
+
 void NoticeEventTimestampPair::RegisterJSONConverter(
     base::JSONValueConverter<NoticeEventTimestampPair>* converter) {
   converter->RegisterCustomValueField<PrivacySandboxNoticeEvent>(
@@ -185,82 +223,20 @@
 
 // PrivacySandboxNoticeData definitions.
 NoticeStorageData::NoticeStorageData() = default;
-
 NoticeStorageData::~NoticeStorageData() = default;
 
 NoticeStorageData::NoticeStorageData(NoticeStorageData&& data) = default;
 NoticeStorageData& NoticeStorageData::operator=(NoticeStorageData&& data) =
     default;
 
-int NoticeStorageData::GetSchemaVersion() const {
-  return schema_version_;
-}
-std::string NoticeStorageData::GetChromeVersion() const {
-  return chrome_version_;
-}
-base::span<const std::unique_ptr<NoticeEventTimestampPair>>
-NoticeStorageData::GetNoticeEvents() const {
-  return notice_events_;
-}
-
-void NoticeStorageData::SetSchemaVersion(int schema_version) {
-  schema_version_ = schema_version;
-}
-
-void NoticeStorageData::SetChromeVersion(std::string_view chrome_version) {
-  chrome_version_ = chrome_version;
-}
-
-void NoticeStorageData::SetNoticeEvents(
-    std::vector<std::unique_ptr<NoticeEventTimestampPair>>&& events) {
-  notice_events_ = std::move(events);
-}
-
-std::optional<base::Time> NoticeStorageData::GetNoticeFirstShownFromEvents()
-    const {
-  for (const auto& notice_event : notice_events_) {
-    if (notice_event->event == PrivacySandboxNoticeEvent::kShown) {
-      return notice_event->timestamp;
-    }
-  }
-  return std::nullopt;
-}
-
-std::optional<base::Time> NoticeStorageData::GetNoticeLastShownFromEvents()
-    const {
-  for (const auto& notice_event : base::Reversed(notice_events_)) {
-    if (notice_event->event == PrivacySandboxNoticeEvent::kShown) {
-      return notice_event->timestamp;
-    }
-  }
-  return std::nullopt;
-}
-
-std::optional<NoticeEventTimestampPair>
-NoticeStorageData::GetNoticeActionTakenForFirstShownFromEvents() const {
-  std::optional<NoticeEventTimestampPair> notice_event_data;
-  int last_shown_idx = 0;
-  int first_notice_idx = 0;
-  for (const auto& event_data : notice_events_) {
-    if (event_data->event == PrivacySandboxNoticeEvent::kShown) {
-      last_shown_idx++;
-    } else if (!notice_event_data.has_value() ||
-               first_notice_idx == last_shown_idx) {
-      first_notice_idx = last_shown_idx;
-      notice_event_data = *event_data;
-    }
-  }
-  return notice_event_data;
-}
-
 void NoticeStorageData::RegisterJSONConverter(
     base::JSONValueConverter<NoticeStorageData>* converter) {
   converter->RegisterIntField(kSchemaVersionKey,
-                              &NoticeStorageData::schema_version_);
+                              &NoticeStorageData::schema_version);
   converter->RegisterStringField(kChromeVersionKey,
-                                 &NoticeStorageData::chrome_version_);
+                                 &NoticeStorageData::chrome_version);
   converter->RegisterRepeatedMessage<NoticeEventTimestampPair>(
-      kEventsKey, &NoticeStorageData::notice_events_);
+      kEventsKey, &NoticeStorageData::notice_events);
 }
 
 void V1MigrationData::RegisterJSONConverter(
@@ -326,9 +302,7 @@
 // static
 NoticeStorageData PrivacySandboxNoticeStorage::ToV2Schema(
     const V1MigrationData& data_v1) {
-  NoticeStorageData data_v2;
   std::vector<std::unique_ptr<NoticeEventTimestampPair>> notice_events;
-  data_v2.SetSchemaVersion(2);
 
   if (data_v1.notice_last_shown != base::Time()) {
     notice_events.emplace_back(
@@ -343,8 +317,10 @@
             *notice_event, data_v1.notice_action_taken_time}));
   }
 
-  data_v2.SetNoticeEvents(std::move(notice_events));
-  return data_v2;
+  NoticeStorageData notice_data;
+  notice_data.schema_version = 2;
+  notice_data.notice_events = std::move(notice_events);
+  return notice_data;
 }
 
 // static
@@ -395,17 +371,17 @@
 
     NoticeStartupState startup_state;
 
-    if (!notice_data.has_value() || notice_data->GetNoticeEvents().empty() ||
-        (notice_data->GetNoticeFirstShownFromEvents() == std::nullopt &&
-         notice_data->GetNoticeActionTakenForFirstShownFromEvents() ==
+    if (!notice_data.has_value() || notice_data->notice_events.empty() ||
+        (GetNoticeFirstShownFromEvents(*notice_data) == std::nullopt &&
+         GetNoticeActionTakenForFirstShownFromEvents(*notice_data) ==
              std::nullopt)) {
       startup_state = NoticeStartupState::kPromptNotShown;
-    } else if (notice_data->GetNoticeFirstShownFromEvents() == std::nullopt ||
-               *notice_data->GetNoticeFirstShownFromEvents() == base::Time()) {
+    } else if (auto time = GetNoticeFirstShownFromEvents(*notice_data);
+               time == std::nullopt || time == base::Time()) {
       // E.g. UnknownActionPreMigration && no first shown time set.
       startup_state = NoticeStartupState::kUnknownState;
     } else {  // Notice has been shown, action handling below.
-      switch (notice_data->GetNoticeEvents().back().get()->event) {
+      switch (notice_data->notice_events.back().get()->event) {
         case PrivacySandboxNoticeEvent::kShown:
           startup_state = NoticeStartupState::kPromptWaiting;
           break;
@@ -462,7 +438,7 @@
 
   // The notice should be shown first before action can be taken on it.
   if (!notice_data.has_value() ||
-      notice_data->GetNoticeLastShownFromEvents() == std::nullopt) {
+      GetNoticeLastShownFromEvents(*notice_data) == std::nullopt) {
     base::UmaHistogramEnumeration(
         base::StrCat(
             {"PrivacySandbox.Notice.NoticeActionTakenBehavior.", notice}),
@@ -471,7 +447,7 @@
   }
 
   // Performing multiple actions on an existing notice is unexpected.
-  if (notice_data->GetNoticeEvents().back().get()->event !=
+  if (notice_data->notice_events.back().get()->event !=
       PrivacySandboxNoticeEvent::kShown) {
     base::UmaHistogramEnumeration(
         base::StrCat(
@@ -507,7 +483,7 @@
           notice_action_taken);
   if (!notice_action_str.empty()) {
     // First shown to interacted duration.
-    auto notice_first_shown = notice_data->GetNoticeFirstShownFromEvents();
+    auto notice_first_shown = GetNoticeFirstShownFromEvents(*notice_data);
     if (notice_first_shown) {
       base::TimeDelta first_shown_to_interacted_duration =
           notice_action_taken_time - *notice_first_shown;
@@ -518,7 +494,7 @@
     }
 
     // Set last shown to interacted.
-    auto notice_last_shown = notice_data->GetNoticeLastShownFromEvents();
+    auto notice_last_shown = GetNoticeLastShownFromEvents(*notice_data);
     if (notice_last_shown) {
       auto last_shown_to_interacted_duration =
           notice_action_taken_time - *notice_last_shown;
@@ -537,10 +513,7 @@
 
   base::Value::Dict entry =
       BuildDictEntryEvent(PrivacySandboxNoticeEvent::kShown, notice_shown_time);
-  update.Get()
-      .EnsureDict(notice)
-      ->EnsureList(kEventsKey)
-      ->Append(std::move(entry));
+  update->EnsureDict(notice)->EnsureList(kEventsKey)->Append(std::move(entry));
 
   // TODO(chrstne): Deprecate NoticeShown histogram once it is no longer used
   // in other codepaths.
@@ -551,7 +524,8 @@
       PrivacySandboxNoticeEvent::kShown);
 
   auto notice_data = ReadNoticeData(notice);
-  if (*notice_data->GetNoticeFirstShownFromEvents() == notice_shown_time) {
+  CHECK(notice_data.has_value());
+  if (GetNoticeFirstShownFromEvents(*notice_data) == notice_shown_time) {
     base::UmaHistogramBoolean(
         base::StrCat(
             {"PrivacySandbox.Notice.NoticeShownForFirstTime.", notice}),
diff --git a/chrome/browser/privacy_sandbox/notice/notice_storage.h b/chrome/browser/privacy_sandbox/notice/notice_storage.h
index 7d4c5b2..42a93ff4 100644
--- a/chrome/browser/privacy_sandbox/notice/notice_storage.h
+++ b/chrome/browser/privacy_sandbox/notice/notice_storage.h
@@ -100,47 +100,21 @@
   base::Time timestamp;
 };
 
-class NoticeStorageData {
- public:
+struct NoticeStorageData {
   NoticeStorageData();
   ~NoticeStorageData();
   NoticeStorageData& operator=(const NoticeStorageData&) = delete;
   NoticeStorageData(const NoticeStorageData& data) = delete;
   NoticeStorageData(NoticeStorageData&& data);
   NoticeStorageData& operator=(NoticeStorageData&& data);
-
-  int GetSchemaVersion() const;
-  std::string GetChromeVersion() const;
-  base::span<const std::unique_ptr<NoticeEventTimestampPair>> GetNoticeEvents()
-      const;
-
-  void SetSchemaVersion(int schema_version);
-  void SetChromeVersion(std::string_view chrome_version);
-  void SetNoticeEvents(
-      std::vector<std::unique_ptr<NoticeEventTimestampPair>>&& events);
-
-  // Gets the timestamp when the notice was first shown. If the notice was never
-  // shown, the default timestamp will be returned.
-  std::optional<base::Time> GetNoticeFirstShownFromEvents() const;
-
-  // Gets the timestamp when the notice was last shown. If the notice was never
-  // shown, the default timestamp will be returned.
-  std::optional<base::Time> GetNoticeLastShownFromEvents() const;
-
-  // Gets the notice action taken and when it was taken the first time the
-  // notice was shown. If the notice hasn't been shown for the first time, or
-  // there was no action associated, no value is returned. If there are multiple
-  // actions associated, only the last action is returned.
-  std::optional<NoticeEventTimestampPair>
-  GetNoticeActionTakenForFirstShownFromEvents() const;
+  bool operator==(const NoticeStorageData& other) const = default;
 
   static void RegisterJSONConverter(
       base::JSONValueConverter<NoticeStorageData>* converter);
 
- private:
-  int schema_version_ = 0;
-  std::string chrome_version_;
-  std::vector<std::unique_ptr<NoticeEventTimestampPair>> notice_events_;
+  int schema_version = 0;
+  std::string chrome_version;
+  std::vector<std::unique_ptr<NoticeEventTimestampPair>> notice_events;
 };
 
 // Stores pre-migration interactions on a notice in the v1 schema.
@@ -154,6 +128,16 @@
       base::JSONValueConverter<V1MigrationData>* converter);
 };
 
+std::optional<base::Time> GetNoticeFirstShownFromEvents(
+    const NoticeStorageData& notice_data);
+
+std::optional<base::Time> GetNoticeLastShownFromEvents(
+    const NoticeStorageData& notice_data);
+
+std::optional<NoticeEventTimestampPair>
+GetNoticeActionTakenForFirstShownFromEvents(
+    const NoticeStorageData& notice_data);
+
 class NoticeStorage {
  public:
   virtual ~NoticeStorage();
diff --git a/chrome/browser/privacy_sandbox/notice/notice_storage_fuzztest.cc b/chrome/browser/privacy_sandbox/notice/notice_storage_fuzztest.cc
index 74c5931..db996261 100644
--- a/chrome/browser/privacy_sandbox/notice/notice_storage_fuzztest.cc
+++ b/chrome/browser/privacy_sandbox/notice/notice_storage_fuzztest.cc
@@ -25,16 +25,16 @@
   data_v1.notice_action_taken_time = notice_taken_time;
   data_v1.notice_last_shown = notice_last_shown;
   NoticeStorageData data_v2 = PrivacySandboxNoticeStorage::ToV2Schema(data_v1);
-  EXPECT_EQ(data_v2.GetSchemaVersion(), 2);
+  EXPECT_EQ(data_v2.schema_version, 2);
   auto notice_event = PrivacySandboxNoticeStorage::NoticeActionToNoticeEvent(
       notice_action_taken);
   if (notice_event.has_value()) {
-    EXPECT_THAT(data_v2.GetNoticeEvents(),
+    EXPECT_THAT(data_v2.notice_events,
                 IsSupersetOf({Pointee(Eq(NoticeEventTimestampPair(
                     *notice_event, notice_taken_time)))}));
   }
   if (notice_last_shown != base::Time()) {
-    EXPECT_THAT(data_v2.GetNoticeEvents(),
+    EXPECT_THAT(data_v2.notice_events,
                 IsSupersetOf({Pointee(Eq(NoticeEventTimestampPair(
                     PrivacySandboxNoticeEvent::kShown, notice_last_shown)))}));
   }
diff --git a/chrome/browser/privacy_sandbox/notice/notice_storage_unittest.cc b/chrome/browser/privacy_sandbox/notice/notice_storage_unittest.cc
index ecb695a..8d49f09 100644
--- a/chrome/browser/privacy_sandbox/notice/notice_storage_unittest.cc
+++ b/chrome/browser/privacy_sandbox/notice/notice_storage_unittest.cc
@@ -25,8 +25,14 @@
 using notice::mojom::PrivacySandboxNotice;
 using notice::mojom::PrivacySandboxNoticeEvent;
 
+using ::testing::ElementsAre;
+using ::testing::Eq;
+using ::testing::Pointee;
+
 using enum notice::mojom::PrivacySandboxNoticeEvent;
 
+using EventTimePair = NoticeEventTimestampPair;
+
 // Feature providing the storage name for the default notice in the catalog.
 BASE_FEATURE(kTestFeature1,
              "TopicsConsentDesktopModal",
@@ -45,6 +51,10 @@
 constexpr NoticeId kNoticeIdNotInCatalog = {
     PrivacySandboxNotice::kMeasurementNotice, SurfaceType::kClankCustomTab};
 
+base::Time UnixMs(int64_t ms) {
+  return base::Time::FromMillisecondsSinceUnixEpoch(ms);
+}
+
 // TODO(crbug.com/333406690): Make a test notice name list injectable so tests
 // don't have to use actual notice names.
 class PrivacySandboxNoticeStorageTest : public testing::Test {
@@ -141,7 +151,7 @@
                                static_cast<int>(NoticeActionTaken::kAck));
   update.Get().SetByDottedPath(
       "TopicsConsentDesktopModal.notice_action_taken_time",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(200)));
+      base::TimeToValue(UnixMs(200)));
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
 
   notice_storage()->RecordStartupHistograms();
@@ -198,11 +208,9 @@
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(actual.has_value());
 
-  ASSERT_EQ(actual->GetNoticeEvents().size(), 2u);
-  EXPECT_EQ(*(actual->GetNoticeEvents()[0]),
-            (NoticeEventTimestampPair{kShown, t0}));
-  EXPECT_EQ(*(actual->GetNoticeEvents()[1]),
-            (NoticeEventTimestampPair{kAck, t1}));
+  EXPECT_THAT(actual->notice_events,
+              ElementsAre(Pointee(Eq(EventTimePair{kShown, t0})),
+                          Pointee(Eq(EventTimePair{kAck, t1}))));
 
   histogram_tester_.ExpectBucketCount(
       "PrivacySandbox.Notice.NoticeEvent.TopicsConsentDesktopModal", kAck, 1);
@@ -233,9 +241,11 @@
   auto actual = notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(actual.has_value());
 
-  ASSERT_EQ(actual->GetNoticeEvents().size(), 2u);
-  EXPECT_EQ(*(actual->GetNoticeEvents()[1]),
-            (NoticeEventTimestampPair{kSettings, t1}));
+  EXPECT_THAT(
+      actual->notice_events,
+      ElementsAre(
+          Pointee(Eq(EventTimePair{kShown, t1 - base::Milliseconds(100)})),
+          Pointee(Eq(EventTimePair{kSettings, t1}))));
 
   histogram_tester_.ExpectBucketCount(
       "PrivacySandbox.Notice.NoticeAction.TopicsConsentDesktopModal",
@@ -251,9 +261,11 @@
       "TopicsConsentDesktopModal");  // Re-read data after potential change
   ASSERT_TRUE(actual.has_value());
 
-  EXPECT_EQ(actual->GetNoticeEvents().size(), 2u);
-  EXPECT_EQ(*(actual->GetNoticeEvents()[1]),
-            (NoticeEventTimestampPair{kSettings, t1}));
+  EXPECT_THAT(
+      actual->notice_events,
+      ElementsAre(
+          Pointee(Eq(EventTimePair{kShown, t1 - base::Milliseconds(100)})),
+          Pointee(Eq(EventTimePair{kSettings, t1}))));
 
   histogram_tester_.ExpectBucketCount(
       "PrivacySandbox.Notice.NoticeEvent.TopicsConsentDesktopModal", kAck, 0);
@@ -278,8 +290,8 @@
 
   auto actual = notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(actual.has_value());
-  EXPECT_EQ(t0, actual->GetNoticeFirstShownFromEvents());
-  EXPECT_EQ(t0, actual->GetNoticeLastShownFromEvents());
+  EXPECT_EQ(t0, GetNoticeFirstShownFromEvents(*actual));
+  EXPECT_EQ(t0, GetNoticeLastShownFromEvents(*actual));
 
   histogram_tester_.ExpectBucketCount(
       "PrivacySandbox.Notice.NoticeShownForFirstTime.TopicsConsentDesktopModal",
@@ -309,11 +321,11 @@
   notice_storage()->RecordEvent(kNotice1InCatalog, kShown);
   actual = notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(actual.has_value());
-  EXPECT_EQ(t1, actual->GetNoticeLastShownFromEvents());
+  EXPECT_EQ(t1, GetNoticeLastShownFromEvents(*actual));
   histogram_tester_.ExpectBucketCount(
       "PrivacySandbox.Notice.NoticeShownForFirstTime.TopicsConsentDesktopModal",
       false, 1);
-  EXPECT_EQ(t0, actual->GetNoticeFirstShownFromEvents());
+  EXPECT_EQ(t0, GetNoticeFirstShownFromEvents(*actual));
 }
 
 TEST_F(PrivacySandboxNoticeStorageTest, SetMultipleNotices) {
@@ -372,8 +384,7 @@
       1);
 }
 
-using NoticeEvents =
-    base::span<const std::unique_ptr<NoticeEventTimestampPair>>;
+using NoticeEvents = base::span<const std::unique_ptr<EventTimePair>>;
 
 class PrivacySandboxNoticeStorageV2Test
     : public PrivacySandboxNoticeStorageTest {};
@@ -386,77 +397,64 @@
       kPrivacySandboxMigratePrefsToSchemaV2);
   ScopedDictPrefUpdate update(prefs(), "privacy_sandbox.notices");
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.schema_version", 1);
-  update.Get().SetByDottedPath(
-      "TopicsConsentDesktopModal.notice_last_shown",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(100)));
+  update.Get().SetByDottedPath("TopicsConsentDesktopModal.notice_last_shown",
+                               base::TimeToValue(UnixMs(100)));
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.notice_action_taken",
                                static_cast<int>(NoticeActionTaken::kAck));
   update.Get().SetByDottedPath(
       "TopicsConsentDesktopModal.notice_action_taken_time",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(200)));
+      base::TimeToValue(UnixMs(200)));
 
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
 
   auto notice_data =
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(notice_data.has_value());
-  EXPECT_EQ(notice_data->GetSchemaVersion(), 1);
-  NoticeEvents events = notice_data->GetNoticeEvents();
-
-  EXPECT_EQ(events.size(), 0u);
+  EXPECT_EQ(notice_data->schema_version, 1);
+  EXPECT_THAT(notice_data->notice_events, ElementsAre());
 }
 
 TEST_F(PrivacySandboxNoticeStorageV2Test,
        AllEventsPopulatedMigrateSuccessfully) {
   ScopedDictPrefUpdate update(prefs(), "privacy_sandbox.notices");
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.schema_version", 1);
-  update.Get().SetByDottedPath(
-      "TopicsConsentDesktopModal.notice_last_shown",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(100)));
+  update.Get().SetByDottedPath("TopicsConsentDesktopModal.notice_last_shown",
+                               base::TimeToValue(UnixMs(100)));
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.notice_action_taken",
                                static_cast<int>(NoticeActionTaken::kAck));
   update.Get().SetByDottedPath(
       "TopicsConsentDesktopModal.notice_action_taken_time",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(200)));
+      base::TimeToValue(UnixMs(200)));
 
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
 
   auto notice_data =
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(notice_data.has_value());
-  EXPECT_EQ(notice_data->GetSchemaVersion(), 2);
+  EXPECT_EQ(notice_data->schema_version, 2);
 
-  NoticeEvents events = notice_data->GetNoticeEvents();
-  EXPECT_EQ(events.size(), 2u);
-
-  EXPECT_EQ(*(events[0]),
-            (NoticeEventTimestampPair{
-                kShown, base::Time::FromMillisecondsSinceUnixEpoch(100)}));
-  EXPECT_EQ(*(events[1]),
-            (NoticeEventTimestampPair{
-                kAck, base::Time::FromMillisecondsSinceUnixEpoch(200)}));
+  const NoticeEvents& events = notice_data->notice_events;
+  EXPECT_THAT(events,
+              ElementsAre(Pointee(Eq(EventTimePair{kShown, UnixMs(100)})),
+                          Pointee(Eq(EventTimePair{kAck, UnixMs(200)}))));
 }
 
 TEST_F(PrivacySandboxNoticeStorageV2Test,
        NoticeShownPopulatedMigrateSuccessfully) {
   ScopedDictPrefUpdate update(prefs(), "privacy_sandbox.notices");
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.schema_version", 1);
-  update.Get().SetByDottedPath(
-      "TopicsConsentDesktopModal.notice_last_shown",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(500)));
+  update.Get().SetByDottedPath("TopicsConsentDesktopModal.notice_last_shown",
+                               base::TimeToValue(UnixMs(500)));
 
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
 
   auto notice_data =
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(notice_data.has_value());
-  EXPECT_EQ(notice_data->GetSchemaVersion(), 2);
+  EXPECT_EQ(notice_data->schema_version, 2);
 
-  auto events = notice_data->GetNoticeEvents();
-  EXPECT_EQ(events.size(), 1u);
-  EXPECT_EQ(*(events[0]),
-            (NoticeEventTimestampPair{
-                kShown, base::Time::FromMillisecondsSinceUnixEpoch(500)}));
+  EXPECT_THAT(notice_data->notice_events,
+              ElementsAre(Pointee(Eq(EventTimePair{kShown, UnixMs(500)}))));
 }
 
 TEST_F(PrivacySandboxNoticeStorageV2Test, SchemaAlreadyUpToDateDoesNotMigrate) {
@@ -464,10 +462,10 @@
   update.Get().SetByDottedPath("TopicsConsentDesktopModal.schema_version", 2);
 
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
-  NoticeEvents events = notice_storage()
-                            ->ReadNoticeData("TopicsConsentDesktopModal")
-                            ->GetNoticeEvents();
-  EXPECT_EQ(events.size(), 0u);
+  const NoticeEvents& events = notice_storage()
+                                   ->ReadNoticeData("TopicsConsentDesktopModal")
+                                   ->notice_events;
+  EXPECT_THAT(events, ElementsAre());
 }
 
 class PrivacySandboxNoticeStorageV2ActionsTest
@@ -484,24 +482,22 @@
                                static_cast<int>(std::get<0>(GetParam())));
   update.Get().SetByDottedPath(
       "TopicsConsentDesktopModal.notice_action_taken_time",
-      base::TimeToValue(base::Time::FromMillisecondsSinceUnixEpoch(200)));
+      base::TimeToValue(UnixMs(200)));
   PrivacySandboxNoticeStorage::UpdateNoticeSchemaV2(prefs());
 
   auto notice_data =
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(notice_data.has_value());
-  EXPECT_EQ(notice_data->GetSchemaVersion(), 2);
+  EXPECT_EQ(notice_data->schema_version, 2);
 
-  NoticeEvents events = notice_data->GetNoticeEvents();
+  const NoticeEvents& events = notice_data->notice_events;
   auto notice_event = std::get<1>(GetParam());
   if (notice_event) {
-    EXPECT_EQ(events.size(), 1u);
-    EXPECT_EQ(
-        *(events[0]),
-        (NoticeEventTimestampPair{
-            *notice_event, base::Time::FromMillisecondsSinceUnixEpoch(200)}));
+    EXPECT_THAT(
+        events,
+        ElementsAre(Pointee(Eq(EventTimePair{*notice_event, UnixMs(200)}))));
   } else {
-    EXPECT_EQ(events.size(), 0u);
+    EXPECT_THAT(events, ElementsAre());
   }
 }
 
@@ -517,16 +513,16 @@
   auto notice_data =
       notice_storage()->ReadNoticeData("TopicsConsentDesktopModal");
   ASSERT_TRUE(notice_data.has_value());
-  EXPECT_EQ(notice_data->GetSchemaVersion(), 2);
+  EXPECT_EQ(notice_data->schema_version, 2);
 
-  NoticeEvents events = notice_data->GetNoticeEvents();
+  const NoticeEvents& events = notice_data->notice_events;
   auto notice_event = std::get<1>(GetParam());
   if (notice_event) {
-    EXPECT_EQ(events.size(), 1u);
-    EXPECT_EQ(*(events[0]),
-              (NoticeEventTimestampPair{*notice_event, base::Time()}));
+    EXPECT_THAT(
+        events,
+        ElementsAre(Pointee(Eq(EventTimePair{*notice_event, base::Time()}))));
   } else {
-    EXPECT_EQ(events.size(), 0u);
+    EXPECT_THAT(events, ElementsAre());
   }
 }
 
@@ -547,16 +543,14 @@
             {NoticeActionTaken::kUnknownActionPreMigration, std::nullopt},
             {NoticeActionTaken::kTimedOut, std::nullopt}}));
 
-std::vector<std::unique_ptr<NoticeEventTimestampPair>> BuildEvents(
+std::vector<std::unique_ptr<EventTimePair>> BuildEvents(
     std::initializer_list<std::pair<PrivacySandboxNoticeEvent, int64_t>>
         raw_events) {
-  std::vector<std::unique_ptr<NoticeEventTimestampPair>> events;
+  std::vector<std::unique_ptr<EventTimePair>> events;
   events.reserve(raw_events.size());
   for (const auto& raw_event : raw_events) {
-    events.emplace_back(
-        std::make_unique<NoticeEventTimestampPair>(NoticeEventTimestampPair{
-            raw_event.first,
-            base::Time::FromMillisecondsSinceUnixEpoch(raw_event.second)}));
+    events.emplace_back(std::make_unique<EventTimePair>(
+        EventTimePair{raw_event.first, UnixMs(raw_event.second)}));
   }
   return events;
 }
@@ -565,85 +559,81 @@
 
 TEST_F(PrivacySandboxNoticeDataTest, NoPrivacySandboxNoticeDataReturnsNothing) {
   NoticeStorageData data;
-  EXPECT_EQ(data.GetNoticeFirstShownFromEvents(), std::nullopt);
-  EXPECT_EQ(data.GetNoticeLastShownFromEvents(), std::nullopt);
-  EXPECT_EQ(data.GetNoticeActionTakenForFirstShownFromEvents(), std::nullopt);
+  EXPECT_EQ(GetNoticeFirstShownFromEvents(data), std::nullopt);
+  EXPECT_EQ(GetNoticeLastShownFromEvents(data), std::nullopt);
+  EXPECT_EQ(GetNoticeActionTakenForFirstShownFromEvents(data), std::nullopt);
 }
 
 TEST_F(PrivacySandboxNoticeDataTest,
        NoticeShownEvent_AccessorReturnsFirstShownSuccessfully) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kAck, 150},
       {kShown, 200},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeFirstShownFromEvents(),
-            base::Time::FromMillisecondsSinceUnixEpoch(100));
+  EXPECT_EQ(GetNoticeFirstShownFromEvents(data), UnixMs(100));
 }
 
 TEST_F(PrivacySandboxNoticeDataTest,
        NoticeShownEvent_AccessorReturnsLastShownSuccessfully) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kAck, 150},
       {kShown, 200},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeLastShownFromEvents(),
-            base::Time::FromMillisecondsSinceUnixEpoch(200));
+  EXPECT_EQ(GetNoticeLastShownFromEvents(data), UnixMs(200));
 }
 
 TEST_F(PrivacySandboxNoticeDataTest,
        NoNoticeActionTakenEvent_AccessorReturnsNoValue) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kShown, 200},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeActionTakenForFirstShownFromEvents(), std::nullopt);
+  EXPECT_EQ(GetNoticeActionTakenForFirstShownFromEvents(data), std::nullopt);
 }
 
 TEST_F(PrivacySandboxNoticeDataTest,
        NoticeActionTakenEvent_AccessorReturnsActionSuccessfully) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kAck, 120},
       {kShown, 200},
       {kOptIn, 250},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeActionTakenForFirstShownFromEvents(),
-            (NoticeEventTimestampPair{
-                kAck, base::Time::FromMillisecondsSinceUnixEpoch(120)}));
+  EXPECT_EQ(GetNoticeActionTakenForFirstShownFromEvents(data),
+            (EventTimePair{kAck, UnixMs(120)}));
 }
 
 TEST_F(
     PrivacySandboxNoticeDataTest,
     NoticeActionTakenEvent_AccessorReturnsActionSuccessfullyMultipleActions) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kAck, 120},
       {kSettings, 150},
       {kShown, 200},
       {kOptIn, 250},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeActionTakenForFirstShownFromEvents(),
-            (NoticeEventTimestampPair{
-                kSettings, base::Time::FromMillisecondsSinceUnixEpoch(150)}));
+  EXPECT_EQ(GetNoticeActionTakenForFirstShownFromEvents(data),
+            (EventTimePair{kSettings, UnixMs(150)}));
 }
 
 TEST_F(
     PrivacySandboxNoticeDataTest,
     NoticeActionTakenEvent_AccessorReturnsActionSuccessfullyWithMultipleShownValues) {
   NoticeStorageData data;
-  data.SetNoticeEvents(BuildEvents({
+  data.notice_events = BuildEvents({
       {kShown, 100},
       {kShown, 110},
       {kAck, 120},
@@ -651,11 +641,10 @@
       {kShown, 200},
       {kShown, 220},
       {kOptIn, 250},
-  }));
+  });
 
-  EXPECT_EQ(data.GetNoticeActionTakenForFirstShownFromEvents(),
-            (NoticeEventTimestampPair{
-                kSettings, base::Time::FromMillisecondsSinceUnixEpoch(150)}));
+  EXPECT_EQ(GetNoticeActionTakenForFirstShownFromEvents(data),
+            (EventTimePair{kSettings, UnixMs(150)}));
 }
 
 }  // namespace
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_countries.h b/chrome/browser/privacy_sandbox/privacy_sandbox_countries.h
index 861f5ac9..2a242c6 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_countries.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_countries.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_H_
 #define CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_H_
 
+#include "base/memory/raw_ptr.h"
+
 class PrivacySandboxCountries {
  public:
   virtual ~PrivacySandboxCountries() = default;
@@ -19,4 +21,6 @@
   virtual bool IsLatestCountryChina() = 0;
 };
 
+raw_ptr<PrivacySandboxCountries> GetSingletonPrivacySandboxCountries();
+
 #endif  // CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_H_
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_browsertest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_countries_browsertest.cc
index 2cfd53f..7f94922 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_browsertest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_countries_browsertest.cc
@@ -7,7 +7,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/variations/service/variations_service.h"
@@ -30,19 +30,16 @@
 class PrivacySandboxCountriesBrowserTestBase : public InProcessBrowserTest {
  public:
   PrivacySandboxCountriesBrowserTestBase() {
-    privacy_sandbox_countries_ =
-        std::make_unique<PrivacySandboxCountriesImpl>();
+    privacy_sandbox_countries_ = GetSingletonPrivacySandboxCountries();
   }
 
-  void TearDown() override { privacy_sandbox_countries_.reset(); }
-
   PrivacySandboxCountries* privacy_sandbox_countries() {
     return privacy_sandbox_countries_.get();
   }
 
  protected:
   base::test::ScopedFeatureList feature_list_;
-  std::unique_ptr<PrivacySandboxCountriesImpl> privacy_sandbox_countries_;
+  raw_ptr<PrivacySandboxCountries> privacy_sandbox_countries_;
 };
 
 class PrivacySandboxCountriesBrowserTest
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.cc
index 349a018..1feedc6 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.cc
@@ -2,11 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
-
 #include "base/containers/fixed_flat_set.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/variations/service/variations_service.h"
 
@@ -47,28 +46,37 @@
         "se", "si", "sk", "sj", "tf", "va", "wf", "yt",
     });
 
+class PrivacySandboxCountriesImpl : public PrivacySandboxCountries {
+ public:
+  bool IsConsentCountry() override {
+    CHECK(g_browser_process);
+    return kPrivacySandboxConsentCountries.contains(
+        GetStoredPermanentCountry(g_browser_process->variations_service()));
+  }
+
+  bool IsRestOfWorldCountry() override {
+    CHECK(g_browser_process);
+    base::UmaHistogramBoolean(
+        "PrivacySandbox.NoticeRequirement.IsVariationServiceReady",
+        g_browser_process->variations_service() != nullptr);
+    std::string country =
+        GetStoredPermanentCountry(g_browser_process->variations_service());
+    base::UmaHistogramBoolean(
+        "PrivacySandbox.NoticeRequirement.IsVariationCountryEmpty",
+        country.empty());
+    return !country.empty() &&
+           !kPrivacySandboxConsentCountries.contains(country);
+  }
+
+  bool IsLatestCountryChina() override {
+    CHECK(g_browser_process);
+    return GetLatestCountry(g_browser_process->variations_service()) == "cn";
+  }
+};
+
 }  // namespace
 
-bool PrivacySandboxCountriesImpl::IsConsentCountry() {
-  CHECK(g_browser_process);
-  return kPrivacySandboxConsentCountries.contains(
-      GetStoredPermanentCountry(g_browser_process->variations_service()));
-}
-
-bool PrivacySandboxCountriesImpl::IsRestOfWorldCountry() {
-  CHECK(g_browser_process);
-  base::UmaHistogramBoolean(
-      "PrivacySandbox.NoticeRequirement.IsVariationServiceReady",
-      g_browser_process->variations_service() != nullptr);
-  std::string country =
-      GetStoredPermanentCountry(g_browser_process->variations_service());
-  base::UmaHistogramBoolean(
-      "PrivacySandbox.NoticeRequirement.IsVariationCountryEmpty",
-      country.empty());
-  return !country.empty() && !kPrivacySandboxConsentCountries.contains(country);
-}
-
-bool PrivacySandboxCountriesImpl::IsLatestCountryChina() {
-  CHECK(g_browser_process);
-  return GetLatestCountry(g_browser_process->variations_service()) == "cn";
+raw_ptr<PrivacySandboxCountries> GetSingletonPrivacySandboxCountries() {
+  static PrivacySandboxCountriesImpl instance;
+  return &instance;
 }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h b/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h
deleted file mode 100644
index 40fdf1f..0000000
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h
+++ /dev/null
@@ -1,19 +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_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_IMPL_H_
-#define CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_IMPL_H_
-
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-
-class PrivacySandboxCountriesImpl : public PrivacySandboxCountries {
- public:
-  bool IsConsentCountry() override;
-
-  bool IsRestOfWorldCountry() override;
-
-  bool IsLatestCountryChina() override;
-};
-
-#endif  // CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_COUNTRIES_IMPL_H_
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_notice_confirmation.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_notice_confirmation.cc
index 17eafb54..42eea5c 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_notice_confirmation.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_notice_confirmation.cc
@@ -7,18 +7,11 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 
 namespace privacy_sandbox {
-
 namespace {
 
-PrivacySandboxCountries& GetPrivacySandboxCountries() {
-  static base::NoDestructor<PrivacySandboxCountriesImpl> instance;
-  return *instance;
-}
-
 enum class ConfirmationType { Notice, Consent, RestrictedNotice };
 
 bool IsFeatureParamEnabled(ConfirmationType confirmation_type) {
@@ -69,13 +62,13 @@
 
 bool IsConsentRequired() {
   return IsConfirmationRequired(ConfirmationType::Consent, []() {
-    return GetPrivacySandboxCountries().IsConsentCountry();
+    return GetSingletonPrivacySandboxCountries()->IsConsentCountry();
   });
 }
 
 bool IsNoticeRequired() {
   return IsConfirmationRequired(ConfirmationType::Notice, []() {
-    return GetPrivacySandboxCountries().IsRestOfWorldCountry();
+    return GetSingletonPrivacySandboxCountries()->IsRestOfWorldCountry();
   });
 }
 
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
index 2529a94..dc8a704 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/first_party_sets/first_party_sets_policy_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h"
@@ -89,7 +88,6 @@
 PrivacySandboxServiceFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
-  static PrivacySandboxCountriesImpl countries_instance;
   return std::make_unique<PrivacySandboxServiceImpl>(
       profile, PrivacySandboxSettingsFactory::GetForProfile(profile),
       TrackingProtectionSettingsFactory::GetForProfile(profile),
@@ -103,5 +101,5 @@
       browsing_topics::BrowsingTopicsServiceFactory::GetForProfile(profile),
       first_party_sets::FirstPartySetsPolicyServiceFactory::
           GetForBrowserContext(context),
-      &countries_instance);
+      GetSingletonPrivacySandboxCountries());
 }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
index 5c901fa..7566cd94 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/privacy_sandbox/notice/notice_service_factory.h"
 #include "chrome/browser/privacy_sandbox/notice/notice_service_interface.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_notice_confirmation.h"
 #include "chrome/browser/privacy_sandbox/profile_bucket_metrics.h"
 #include "chrome/browser/profiles/profile.h"
@@ -162,6 +161,9 @@
 
 // Returns the text contents of the Topics Consent dialog.
 std::string GetTopicsConfirmationText() {
+  // TODO(crbug.com/413388209): Update the LEARN_MORE_LINK to use a newer
+  // version of the text and remove
+  // `IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_LINK`
   std::vector<int> string_ids = {
       IDS_PRIVACY_SANDBOX_M1_CONSENT_TITLE,
       IDS_PRIVACY_SANDBOX_M1_CONSENT_DESCRIPTION_1,
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
index a14bb802..45c06ac 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
@@ -7,7 +7,6 @@
 
 // clang-format off
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 // clang-format on
 
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
index 73ebfe0..1893234 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
@@ -401,13 +401,9 @@
       static_cast<content_settings::CookieControlsMode>(
           profile_->GetPrefs()->GetInteger(prefs::kCookieControlsMode));
 
-  switch (cookie_controls_mode) {
-    case content_settings::CookieControlsMode::kBlockThirdParty:
-    case content_settings::CookieControlsMode::kLimited:
-      return false;
-    case content_settings::CookieControlsMode::kIncognitoOnly:
-    case content_settings::CookieControlsMode::kOff:
-      break;
+  if (cookie_controls_mode ==
+      content_settings::CookieControlsMode::kBlockThirdParty) {
+    return false;
   }
 
   return true;
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 410f6c0e..2da10ef 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -469,10 +469,6 @@
 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
 #endif
 
-#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS)
-#include "chrome/browser/extensions/desktop_android/desktop_android_extension_system.h"
-#endif
-
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 #include "chrome/browser/signin/dice_response_handler_factory.h"
 #include "chrome/browser/signin/dice_web_signin_interceptor_factory.h"
@@ -640,7 +636,6 @@
   if (extensions::ExtensionsBrowserClient::Get()) {
     extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
   }
-  extensions::DesktopAndroidExtensionSystem::GetFactory();
 #endif
 
   // ---------------------------------------------------------------------------
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index adb60c4b..1d765118 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -29,6 +29,7 @@
 #include "base/test/with_feature_override.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
@@ -2213,7 +2214,8 @@
 
   // Avoid showing What's New.
   PrefService* pref_service = g_browser_process->local_state();
-  pref_service->SetInteger(prefs::kLastWhatsNewVersion, CHROME_VERSION_MAJOR);
+  pref_service->SetInteger(prefs::kLastWhatsNewVersion,
+                           version_info::GetMajorVersionNumberAsInt());
 
   // Create the profiles.
   ProfileAttributesStorage& storage =
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/consumer_update.html b/chrome/browser/resources/chromeos/login/screens/oobe/consumer_update.html
index 67f2042..35a0bfd 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/consumer_update.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/consumer_update.html
@@ -81,7 +81,8 @@
   <h1 slot="title">
     [[i18nDynamic(locale, 'checkingForUpdates')]]
   </h1>
-  <paper-progress slot="progress" id="checking-progress" indeterminate>
+  <paper-progress slot="progress" id="checking-progress" aria-hidden="true"
+    indeterminate>
   </paper-progress>
   <div slot="content" class="flex layout vertical center-justified center">
     <oobe-cr-lottie id="checkingAnimation"
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/update.html b/chrome/browser/resources/chromeos/login/screens/oobe/update.html
index a9ac86b..f77ad103 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/update.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/update.html
@@ -65,7 +65,8 @@
   <h1 slot="title">
     [[i18nDynamic(locale, 'checkingForUpdates')]]
   </h1>
-  <paper-progress slot="progress" id="checking-progress" indeterminate>
+  <paper-progress slot="progress" id="checking-progress" aria-hidden="true"
+    indeterminate>
   </paper-progress>
   <div slot="content" class="flex layout vertical center-justified center">
     <oobe-cr-lottie id="checkingAnimation"
diff --git a/chrome/browser/resources/glic/glic_api/glic_api.ts b/chrome/browser/resources/glic/glic_api/glic_api.ts
index adfc70c..040dae6 100644
--- a/chrome/browser/resources/glic/glic_api/glic_api.ts
+++ b/chrome/browser/resources/glic/glic_api/glic_api.ts
@@ -1068,7 +1068,7 @@
   localProfileName?: string;
   /** The profile email. */
   email: string;
-  /** Whether the profile or the browser is managed. */
+  /** Whether the profile's signed-in account is a managed account. */
   isManaged?: boolean;
 }
 
diff --git a/chrome/browser/resources/new_tab_page/app.css b/chrome/browser/resources/new_tab_page/app.css
index a8c2cf7..39980d7 100644
--- a/chrome/browser/resources/new_tab_page/app.css
+++ b/chrome/browser/resources/new_tab_page/app.css
@@ -327,6 +327,63 @@
   position: fixed;
 }
 
+#backgroundImageAttribution {
+  border-radius: 8px;
+  bottom: 16px;
+  color: var(--color-new-tab-page-attribution-foreground);
+  line-height: 20px;
+  max-width: 50vw;
+  padding: 8px;
+  position: fixed;
+  z-index: -1;
+  background-color: var(--ntp-protected-icon-background-color);
+  text-shadow: none;
+}
+
+#backgroundImageAttribution:hover {
+  background-color: var(--ntp-protected-icon-background-color-hovered);
+  background: rgba(var(--google-grey-900-rgb), .1);
+}
+
+:host-context([dir='ltr']) #backgroundImageAttribution {
+  left: 16px;
+}
+
+:host-context([dir='rtl']) #backgroundImageAttribution {
+  right: 16px;
+}
+
+#backgroundImageAttribution1Container {
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+}
+
+#linkIcon {
+  -webkit-mask-image: url(icons/link.svg);
+  -webkit-mask-repeat: no-repeat;
+  -webkit-mask-size: 100%;
+  background-color: var(--color-new-tab-page-attribution-foreground);
+  height: 16px;
+  margin-inline-end: 8px;
+  width: 16px;
+}
+
+#backgroundImageAttribution1,
+#backgroundImageAttribution2 {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+#backgroundImageAttribution1 {
+  font-size: .875rem;
+}
+
+#backgroundImageAttribution2 {
+  font-size: .75rem;
+}
+
 #contentBottomSpacer {
   flex-shrink: 0;
   height: 32px;
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html
index 1e883e5..f7b589a 100644
--- a/chrome/browser/resources/new_tab_page/app.html
+++ b/chrome/browser/resources/new_tab_page/app.html
@@ -64,9 +64,20 @@
         </ntp-modules-v2>
       `}
     ` : ''}
-    <ntp-footer .theme="${this.theme_}"></ntp-footer>
-    <!-- TODO(crbug.com/394906782): Move customize buttons and
-     theme attribution into the ntp footer. -->
+    <a id="backgroundImageAttribution"
+        href="${this.backgroundImageAttributionUrl_}"
+        ?hidden="${!this.backgroundImageAttribution1_}">
+      <div id="backgroundImageAttribution1Container">
+        <div id="linkIcon" ?hidden="${!this.backgroundImageAttributionUrl_}"></div>
+        <div id="backgroundImageAttribution1">
+          ${this.backgroundImageAttribution1_}
+        </div>
+      </div>
+      <div id="backgroundImageAttribution2"
+          ?hidden="${!this.backgroundImageAttribution2_}">
+        ${this.backgroundImageAttribution2_}
+      </div>
+    </a>
     <div id="customizeButtons">
       ${this.showWallpaperSearchButton_ ? html`
         <cr-button id="wallpaperSearchButton"
diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts
index 89ec4478..b8ebd9c8 100644
--- a/chrome/browser/resources/new_tab_page/app.ts
+++ b/chrome/browser/resources/new_tab_page/app.ts
@@ -4,7 +4,6 @@
 
 import './iframe.js';
 import './logo.js';
-import './footer.js';
 import '/strings.m.js';
 import 'chrome://resources/cr_components/searchbox/searchbox.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
@@ -15,7 +14,7 @@
 import type {ClickInfo} from 'chrome://resources/js/browser_command.mojom-webui.js';
 import {Command} from 'chrome://resources/js/browser_command.mojom-webui.js';
 import {BrowserCommandProxy} from 'chrome://resources/js/browser_command/browser_command_proxy.js';
-import {hexColorToSkColor} from 'chrome://resources/js/color_utils.js';
+import {hexColorToSkColor, skColorToRgba} from 'chrome://resources/js/color_utils.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
@@ -36,7 +35,7 @@
 import {CustomizeChromeSection, IphFeature, NtpBackgroundImageSource} from './new_tab_page.mojom-webui.js';
 import {NewTabPageProxy} from './new_tab_page_proxy.js';
 import type {MicrosoftAuthUntrustedDocumentRemote} from './ntp_microsoft_auth_shared_ui.mojom-webui.js';
-import {$$, rgbaOrInherit} from './utils.js';
+import {$$} from './utils.js';
 import {Action as VoiceAction, recordVoiceAction} from './voice_search_overlay.js';
 import {WindowProxy} from './window_proxy.js';
 
@@ -170,6 +169,9 @@
         type: Boolean,
       },
 
+      backgroundImageAttribution1_: {type: String},
+      backgroundImageAttribution2_: {type: String},
+      backgroundImageAttributionUrl_: {type: String},
       backgroundColor_: {type: Object},
 
       // Used in cr-searchbox component via host-context.
@@ -256,6 +258,9 @@
   private accessor selectedCustomizeDialogPage_: string|null;
   protected accessor showVoiceSearchOverlay_: boolean = false;
   protected accessor showBackgroundImage_: boolean;
+  protected accessor backgroundImageAttribution1_: string;
+  protected accessor backgroundImageAttribution2_: string;
+  protected accessor backgroundImageAttributionUrl_: string;
   protected accessor backgroundColor_: SkColor|null;
   protected accessor colorSourceIsBaseline: boolean;
   protected accessor logoColor_: SkColor|null = null;
@@ -487,6 +492,12 @@
 
     if (changedPrivateProperties.has('theme_')) {
       this.showBackgroundImage_ = this.computeShowBackgroundImage_();
+      this.backgroundImageAttribution1_ =
+          this.computeBackgroundImageAttribution1_();
+      this.backgroundImageAttribution2_ =
+          this.computeBackgroundImageAttribution2_();
+      this.backgroundImageAttributionUrl_ =
+          this.computeBackgroundImageAttributionUrl_();
       this.colorSourceIsBaseline = this.computeColorSourceIsBaseline();
       this.logoColor_ = this.computeLogoColor_();
       this.singleColoredLogo_ = this.computeSingleColoredLogo_();
@@ -524,7 +535,7 @@
 
     if (changedPrivateProperties.has('logoColor_')) {
       this.style.setProperty(
-          '--ntp-logo-color', rgbaOrInherit(this.logoColor_));
+          '--ntp-logo-color', this.rgbaOrInherit_(this.logoColor_));
     }
 
     if (changedPrivateProperties.has('showBackgroundImage_')) {
@@ -561,6 +572,20 @@
     return !this.showBackgroundImage_;
   }
 
+  private computeBackgroundImageAttribution1_(): string {
+    return this.theme_ && this.theme_.backgroundImageAttribution1 || '';
+  }
+
+  private computeBackgroundImageAttribution2_(): string {
+    return this.theme_ && this.theme_.backgroundImageAttribution2 || '';
+  }
+
+  private computeBackgroundImageAttributionUrl_(): string {
+    return this.theme_ && this.theme_.backgroundImageAttributionUrl ?
+        this.theme_.backgroundImageAttributionUrl.url :
+        '';
+  }
+
   private computeRealboxShown_(): boolean {
     // Do not show the realbox if the upload dialog is showing.
     return !!this.theme_ && !this.showLensUploadDialog_;
@@ -666,6 +691,10 @@
     }
   }
 
+  private rgbaOrInherit_(skColor: SkColor|null): string {
+    return skColor ? skColorToRgba(skColor) : 'inherit';
+  }
+
   private computeShowBackgroundImage_(): boolean {
     return !!this.theme_ && !!this.theme_.backgroundImage;
   }
@@ -678,8 +707,11 @@
     if (this.theme_) {
       this.backgroundManager_.setBackgroundColor(this.theme_.backgroundColor);
       this.style.setProperty(
+          '--color-new-tab-page-attribution-foreground',
+          this.rgbaOrInherit_(this.theme_.textColor));
+      this.style.setProperty(
           '--color-new-tab-page-most-visited-foreground',
-          rgbaOrInherit(this.theme_.textColor));
+          this.rgbaOrInherit_(this.theme_.textColor));
     }
     this.updateBackgroundImagePath_();
   }
diff --git a/chrome/browser/resources/new_tab_page/footer.css b/chrome/browser/resources/new_tab_page/footer.css
deleted file mode 100644
index 024c745..0000000
--- a/chrome/browser/resources/new_tab_page/footer.css
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright 2025 The Chromium Authors
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-/* #css_wrapper_metadata_start
- * #type=style-lit
- * #scheme=relative
- * #css_wrapper_metadata_end */
-
-#backgroundImageAttribution {
-  border-radius: 8px;
-  bottom: 16px;
-  color: var(--color-new-tab-page-attribution-foreground);
-  line-height: 20px;
-  max-width: 50vw;
-  padding: 8px;
-  position: fixed;
-  z-index: -1;
-  background-color: var(--ntp-protected-icon-background-color);
-  text-shadow: none;
-}
-
-#backgroundImageAttribution:hover {
-  background-color: var(--ntp-protected-icon-background-color-hovered);
-  background: rgba(var(--google-grey-900-rgb), .1);
-}
-
-:host-context([dir='ltr']) #backgroundImageAttribution {
-  left: 16px;
-}
-
-:host-context([dir='rtl']) #backgroundImageAttribution {
-  right: 16px;
-}
-
-#backgroundImageAttribution1Container {
-  align-items: center;
-  display: flex;
-  flex-direction: row;
-}
-
-#linkIcon {
-  -webkit-mask-image: url(icons/link.svg);
-  -webkit-mask-repeat: no-repeat;
-  -webkit-mask-size: 100%;
-  background-color: var(--color-new-tab-page-attribution-foreground);
-  height: 16px;
-  margin-inline-end: 8px;
-  width: 16px;
-}
-
-#backgroundImageAttribution1,
-#backgroundImageAttribution2 {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-#backgroundImageAttribution1 {
-  font-size: .875rem;
-}
-
-#backgroundImageAttribution2 {
-  font-size: .75rem;
-}
diff --git a/chrome/browser/resources/new_tab_page/footer.html b/chrome/browser/resources/new_tab_page/footer.html
deleted file mode 100644
index 31149776..0000000
--- a/chrome/browser/resources/new_tab_page/footer.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<div id="footerContainer">
-  <a id="backgroundImageAttribution"
-      href="${this.backgroundImageAttributionUrl_}"
-      ?hidden="${!this.backgroundImageAttribution1_}">
-    <div id="backgroundImageAttribution1Container">
-      <div id="linkIcon" ?hidden="${!this.backgroundImageAttributionUrl_}">
-      </div>
-      <div id="backgroundImageAttribution1">
-        ${this.backgroundImageAttribution1_}
-      </div>
-    </div>
-    <div id="backgroundImageAttribution2"
-        ?hidden="${!this.backgroundImageAttribution2_}">
-      ${this.backgroundImageAttribution2_}
-    </div>
-  </a>
-</div>
diff --git a/chrome/browser/resources/new_tab_page/footer.ts b/chrome/browser/resources/new_tab_page/footer.ts
deleted file mode 100644
index cd01fef..0000000
--- a/chrome/browser/resources/new_tab_page/footer.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
-import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
-
-import {getCss} from './footer.css.js';
-import {getHtml} from './footer.html.js';
-import type {Theme} from './new_tab_page.mojom-webui.js';
-import {rgbaOrInherit} from './utils.js';
-
-export interface FooterElement {
-  $: {
-    backgroundImageAttribution: HTMLElement,
-    backgroundImageAttribution1: HTMLElement,
-    backgroundImageAttribution2: HTMLElement,
-    footerContainer: HTMLElement,
-  };
-}
-
-export class FooterElement extends CrLitElement {
-  static get is() {
-    return 'ntp-footer';
-  }
-
-  static override get styles() {
-    return getCss();
-  }
-
-  override render() {
-    return getHtml.bind(this)();
-  }
-
-  static override get properties() {
-    return {
-      theme: {type: Object},
-
-      backgroundImageAttribution1_: {type: String},
-      backgroundImageAttribution2_: {type: String},
-      backgroundImageAttributionUrl_: {type: String},
-    };
-  }
-
-  accessor theme: Theme|null = null;
-  protected accessor backgroundImageAttribution1_: string;
-  protected accessor backgroundImageAttribution2_: string;
-  protected accessor backgroundImageAttributionUrl_: string;
-
-  override willUpdate(changedProperties: PropertyValues<this>) {
-    super.willUpdate(changedProperties);
-    const changedPrivateProperties =
-        changedProperties as Map<PropertyKey, unknown>;
-    if (changedPrivateProperties.has('theme')) {
-      this.backgroundImageAttribution1_ =
-          this.computeBackgroundImageAttribution1_();
-      this.backgroundImageAttribution2_ =
-          this.computeBackgroundImageAttribution2_();
-      this.backgroundImageAttributionUrl_ =
-          this.computeBackgroundImageAttributionUrl_();
-    }
-  }
-
-  override updated(changedProperties: PropertyValues<this>) {
-    super.updated(changedProperties);
-    const changedPrivateProperties =
-        changedProperties as Map<PropertyKey, unknown>;
-    if (changedPrivateProperties.has('theme')) {
-      this.onThemeChange_();
-    }
-  }
-
-  private computeBackgroundImageAttribution1_(): string {
-    return this.theme && this.theme.backgroundImageAttribution1 || '';
-  }
-
-  private computeBackgroundImageAttribution2_(): string {
-    return this.theme && this.theme.backgroundImageAttribution2 || '';
-  }
-
-  private computeBackgroundImageAttributionUrl_(): string {
-    return this.theme && this.theme.backgroundImageAttributionUrl ?
-        this.theme.backgroundImageAttributionUrl.url :
-        '';
-  }
-
-  private onThemeChange_() {
-    if (this.theme) {
-      this.style.setProperty(
-          '--color-new-tab-page-attribution-foreground',
-          rgbaOrInherit(this.theme.textColor));
-      this.style.setProperty(
-          '--color-new-tab-page-most-visited-foreground',
-          rgbaOrInherit(this.theme.textColor));
-    }
-  }
-}
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'ntp-footer': FooterElement;
-  }
-}
-
-customElements.define(FooterElement.is, FooterElement);
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts
index 1144e0d..eeb91963 100644
--- a/chrome/browser/resources/new_tab_page/lazy_load.ts
+++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -16,7 +16,6 @@
 import 'chrome://resources/cr_components/most_visited/most_visited.js';
 
 export {PageImageServiceBrowserProxy} from 'chrome://resources/cr_components/page_image_service/browser_proxy.js';
-export {FooterElement} from './footer.js';
 export {LensErrorType, LensFormElement, LensSubmitType} from './lens_form.js';
 export {LensUploadDialogAction, LensUploadDialogElement, LensUploadDialogError} from './lens_upload_dialog.js';
 export {MiddleSlotPromoElement, PromoDismissAction} from './middle_slot_promo.js';
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page.gni b/chrome/browser/resources/new_tab_page/new_tab_page.gni
index 5407838..6877384 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page.gni
+++ b/chrome/browser/resources/new_tab_page/new_tab_page.gni
@@ -24,7 +24,6 @@
 all_web_component_files = [
                             "app.ts",
                             "doodle_share_dialog.ts",
-                            "footer.ts",
                             "iframe.ts",
                             "lens_form.ts",
                             "lens_upload_dialog.ts",
@@ -37,7 +36,6 @@
 all_css_files = [
                   "app.css",
                   "doodle_share_dialog.css",
-                  "footer.css",
                   "iframe.css",
                   "lens_form.css",
                   "lens_upload_dialog.css",
diff --git a/chrome/browser/resources/new_tab_page/utils.ts b/chrome/browser/resources/new_tab_page/utils.ts
index 616b1c1..facb621 100644
--- a/chrome/browser/resources/new_tab_page/utils.ts
+++ b/chrome/browser/resources/new_tab_page/utils.ts
@@ -3,8 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.js';
-import {skColorToRgba} from 'chrome://resources/js/color_utils.js';
-import type {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
+
 
 /**
  * Queries |selector| on |element|'s shadow root and returns the resulting
@@ -33,10 +32,3 @@
   assert(element && element instanceof type);
   return element;
 }
-
-/**
- * Converts |skColor| to a rgba. Returns 'inherit' if |skColor| is null.
- */
-export function rgbaOrInherit(skColor: SkColor|null): string {
-  return skColor ? skColorToRgba(skColor) : 'inherit';
-}
diff --git a/chrome/browser/resources/settings/glic_page/glic_page.html b/chrome/browser/resources/settings/glic_page/glic_page.html
index fa74686f..23619f4 100644
--- a/chrome/browser/resources/settings/glic_page/glic_page.html
+++ b/chrome/browser/resources/settings/glic_page/glic_page.html
@@ -20,6 +20,10 @@
     display: flex;
     align-items: center;
   }
+
+  #shortcutsLearnMoreLabel[href=''] {
+    display: none;
+  }
 </style>
 
 <settings-animated-pages id="pages" section="glicSection">
@@ -79,11 +83,12 @@
                 <div class="secondary"
                     learn-more-url="$i18n{glicKeyboardShortcutLearnMoreUrl}">
                   $i18n{glicKeyboardShortcutSublabel}
-                  <a href="[[getLearnMoreUrl_(enterprisePref_)]]"
+                  <a id="shortcutsLearnMoreLabel"
+                      href="$i18n{glicKeyboardShortcutLearnMoreUrl}"
                       aria-label="$i18n{glicKeyboardShortcutLearnMoreLabel}"
                       aria-description="$i18n{opensInNewTab}"
                       on-click="onLearnMoreClick_" target="_blank">
-                      $i18n{glicKeyboardShortcutLearnMoreLabel}
+                    $i18n{glicKeyboardShortcutLearnMoreLabel}
                   </a>
                 </div>
               </div>
diff --git a/chrome/browser/resources/settings/glic_page/glic_page.ts b/chrome/browser/resources/settings/glic_page/glic_page.ts
index 24de3304..5d28081 100644
--- a/chrome/browser/resources/settings/glic_page/glic_page.ts
+++ b/chrome/browser/resources/settings/glic_page/glic_page.ts
@@ -17,12 +17,10 @@
 import {HelpBubbleMixin} from 'chrome://resources/cr_components/help_bubble/help_bubble_mixin.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {assert} from 'chrome://resources/js/assert.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {getAiLearnMoreUrl} from '../ai_page/ai_learn_more_url_util.js';
-import {AiEnterpriseFeaturePrefName, AiPageActions} from '../ai_page/constants.js';
+import {AiPageActions} from '../ai_page/constants.js';
 import type {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js';
 import type {MetricsBrowserProxy} from '../metrics_browser_proxy.js';
 import {MetricsBrowserProxyImpl} from '../metrics_browser_proxy.js';
@@ -81,11 +79,6 @@
           value: 0,
         },
       },
-
-      enterprisePref_: {
-        type: Object,
-        computed: `computePref(prefs.${AiEnterpriseFeaturePrefName.COMPARE})`,
-      },
     };
   }
 
@@ -97,7 +90,6 @@
   private metricsBrowserProxy_: MetricsBrowserProxy =
       MetricsBrowserProxyImpl.getInstance();
   declare private tabAccessToggleExpanded_: boolean;
-  declare private enterprisePref_: chrome.settingsPrivate.PrefObject;
 
   override async connectedCallback() {
     super.connectedCallback();
@@ -215,13 +207,6 @@
         this.i18n('glicActivityButtonUrl'));
   }
 
-  private getLearnMoreUrl_(): string {
-    return getAiLearnMoreUrl(
-        this.enterprisePref_,
-        loadTimeData.getString('glicKeyboardShortcutLearnMoreUrl'),
-        loadTimeData.getString('glicKeyboardShortcutLearnMoreManagedUrl'));
-  }
-
   private onLearnMoreClick_() {
     this.metricsBrowserProxy_.recordAction(
         AiPageActions.GLIC_SHORTCUTS_LEARN_MORE_CLICKED);
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_safe_browsing_fragment.html b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_safe_browsing_fragment.html
index c4abe77..22bc36c7 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_safe_browsing_fragment.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_safe_browsing_fragment.html
@@ -18,7 +18,7 @@
         pref="[[prefs.generated.safe_browsing]]"
         name="[[safeBrowsingSettingEnum_.ENHANCED]]"
         label="$i18n{safeBrowsingEnhanced}"
-        sub-label="$i18n{safeBrowsingEnhancedDesc}"
+        sub-label="$i18n{safeBrowsingEnhancedDescUpdated}"
         expand-aria-label="$i18n{safeBrowsingEnhancedExpandA11yLabel}"
         on-click="onSafeBrowsingEnhancedClick_">
           <div slot="collapse" class="settings-columned-section">
@@ -55,13 +55,6 @@
                     $i18n{safeBrowsingEnhancedWhenOnBulFour}
                   </div>
                 </li>
-                <li>
-                  <cr-icon icon="settings20:vpn-key-new" aria-hidden="true">
-                  </cr-icon>
-                  <div class="secondary">
-                    $i18n{safeBrowsingEnhancedWhenOnBulFive}
-                  </div>
-                </li>
               </ul>
             </div>
             <div class="column">
diff --git a/chrome/browser/resources/side_panel/reading_list/reading_list_app.css b/chrome/browser/resources/side_panel/reading_list/reading_list_app.css
index 867a392..6ffa7469 100644
--- a/chrome/browser/resources/side_panel/reading_list/reading_list_app.css
+++ b/chrome/browser/resources/side_panel/reading_list/reading_list_app.css
@@ -6,9 +6,8 @@
  * #type=style-lit
  * #import=chrome://read-later.top-chrome/shared/sp_shared_style_lit.css.js
  * #import=chrome://resources/cr_elements/cr_hidden_style_lit.css.js
- * #import=chrome://resources/cr_elements/mwb_element_shared_style_lit.css.js
  * #scheme=relative
- * #include=mwb-element-shared-style-lit cr-hidden-style-lit sp-shared-style-lit
+ * #include=cr-hidden-style-lit sp-shared-style-lit
  * #css_wrapper_metadata_end */
 
 :host {
@@ -22,7 +21,8 @@
 }
 
 cr-icon-button {
-  cursor: pointer;
+  --cr-icon-button-icon-size: var(--mwb-icon-size);
+  --cr-icon-button-size: calc(var(--mwb-icon-size) * 1.5);
 }
 
 cr-lazy-list {
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index a060e5a7..7b88f06c 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -171,6 +171,8 @@
       "network_context_service_factory.h",
       "notification_content_detection/notification_content_detection_service_factory.cc",
       "notification_content_detection/notification_content_detection_service_factory.h",
+      "notification_content_detection/notification_content_detection_util.cc",
+      "notification_content_detection/notification_content_detection_util.h",
       "notification_telemetry/notification_telemetry_service.cc",
       "notification_telemetry/notification_telemetry_service.h",
       "notification_telemetry/notification_telemetry_service_factory.cc",
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediator.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediator.java
index 39e88f6..4872fdc 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediator.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediator.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.build.NullUtil.assumeNonNull;
 
+import org.chromium.base.shared_preferences.SharedPreferencesManager;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
@@ -19,6 +20,7 @@
 @NullMarked
 public class AdvancedProtectionMediator implements OsAdditionalSecurityPermissionProvider.Observer {
     private WindowAndroid mWindowAndroid;
+    private boolean mShouldShowMessageOnStartup;
 
     public AdvancedProtectionMediator(WindowAndroid windowAndroid) {
         mWindowAndroid = windowAndroid;
@@ -26,6 +28,17 @@
         var provider = OsAdditionalSecurityPermissionUtil.getProviderInstance();
         if (provider != null) {
             provider.addObserver(this);
+
+            boolean cachedAdvancedProtectionSetting =
+                    ChromeSharedPreferences.getInstance()
+                            .readBoolean(
+                                    ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING,
+                                    /* defaultValue= */ false);
+            boolean advancedProtectionSetting = provider.isAdvancedProtectionRequestedByOs();
+            if (cachedAdvancedProtectionSetting != advancedProtectionSetting) {
+                updatePref(provider);
+                mShouldShowMessageOnStartup = advancedProtectionSetting;
+            }
         }
     }
 
@@ -40,17 +53,7 @@
         var provider = OsAdditionalSecurityPermissionUtil.getProviderInstance();
         if (provider == null) return false;
 
-        boolean cachedAdvancedProtectionSetting =
-                ChromeSharedPreferences.getInstance()
-                        .readBoolean(
-                                ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING,
-                                /* defaultValue= */ false);
-        if (cachedAdvancedProtectionSetting == provider.isAdvancedProtectionRequestedByOs()) {
-            return false;
-        }
-
-        updatePref(provider);
-        if (provider.isAdvancedProtectionRequestedByOs()) {
+        if (mShouldShowMessageOnStartup && provider.isAdvancedProtectionRequestedByOs()) {
             enqueueMessage(provider);
         }
         return true;
@@ -82,9 +85,12 @@
     }
 
     private void updatePref(OsAdditionalSecurityPermissionProvider provider) {
-        ChromeSharedPreferences.getInstance()
-                .writeBoolean(
-                        ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING,
-                        provider.isAdvancedProtectionRequestedByOs());
+        SharedPreferencesManager preferences = ChromeSharedPreferences.getInstance();
+        preferences.writeBoolean(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING,
+                provider.isAdvancedProtectionRequestedByOs());
+        preferences.writeLong(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                System.currentTimeMillis());
     }
 }
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
index e189217..d0ae2c24 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.safe_browsing;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -40,6 +41,7 @@
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.lang.ref.WeakReference;
+import java.util.concurrent.TimeUnit;
 
 /** Tests for {@link AdvancedProtectionMediator}. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -154,7 +156,7 @@
     @Test
     public void testDontShowMessagePrefMatches() {
         ChromeSharedPreferences.getInstance()
-                .writeBoolean(ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING, true);
+                .writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
         setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ true);
 
         var coordinator = new AdvancedProtectionCoordinator(mWindowAndroid);
@@ -171,8 +173,7 @@
     @Test
     public void testShowMessagePrefTrueAndDiffers() {
         var sharedPreferences = ChromeSharedPreferences.getInstance();
-        sharedPreferences.writeBoolean(
-                ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING, true);
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
         setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ false);
 
         var coordinator = new AdvancedProtectionCoordinator(mWindowAndroid);
@@ -181,7 +182,7 @@
 
         assertFalse(
                 sharedPreferences.readBoolean(
-                        ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING,
+                        ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING,
                         /* defaultValue= */ false));
 
         coordinator.destroy();
@@ -194,8 +195,7 @@
     @Test
     public void testShowMessagePrefFalseAndDiffers() {
         var sharedPreferences = ChromeSharedPreferences.getInstance();
-        sharedPreferences.writeBoolean(
-                ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING, false);
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, false);
         setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ true);
 
         var coordinator = new AdvancedProtectionCoordinator(mWindowAndroid);
@@ -204,7 +204,7 @@
 
         assertTrue(
                 sharedPreferences.readBoolean(
-                        ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING,
+                        ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING,
                         /* defaultValue= */ false));
 
         coordinator.destroy();
@@ -216,8 +216,7 @@
     @Test
     public void testShowMessageOnStateChange() {
         var sharedPreferences = ChromeSharedPreferences.getInstance();
-        sharedPreferences.writeBoolean(
-                ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING, true);
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
         var provider = setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ false);
 
         var coordinator = new AdvancedProtectionCoordinator(mWindowAndroid);
@@ -234,8 +233,7 @@
     @EnableFeatures({PermissionsAndroidFeatureList.OS_ADDITIONAL_SECURITY_PERMISSION_KILL_SWITCH})
     public void testDontShowMessageKillSwitch() {
         var sharedPreferences = ChromeSharedPreferences.getInstance();
-        sharedPreferences.writeBoolean(
-                ChromePreferenceKeys.DEFAULT_OS_ADVANCED_PROTECTION_SETTING, true);
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
         var provider = setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ false);
 
         var coordinator = new AdvancedProtectionCoordinator(mWindowAndroid);
@@ -246,4 +244,72 @@
 
         coordinator.destroy();
     }
+
+    /**
+     * Test that {@link ChromePreferenceKeys#OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME} is updated
+     * when the advanced-protection setting is changed.
+     */
+    @Test
+    public void testUpdateTimestampOnStateChange() {
+        long yesterdayTimestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
+
+        var sharedPreferences = ChromeSharedPreferences.getInstance();
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
+        sharedPreferences.writeLong(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                yesterdayTimestamp);
+        setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ false);
+
+        new AdvancedProtectionCoordinator(mWindowAndroid);
+        assertTrue(
+                yesterdayTimestamp
+                        < sharedPreferences.readLong(
+                                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                                0));
+    }
+
+    /**
+     * Test that {@link ChromePreferenceKeys#OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME} is not
+     * updated if the advanced-protection setting has not changed since the last Chrome run.
+     */
+    @Test
+    public void testDoNotUpdateTimestamp_SameState() {
+        long yesterdayTimestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
+
+        var sharedPreferences = ChromeSharedPreferences.getInstance();
+        sharedPreferences.writeBoolean(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, true);
+        sharedPreferences.writeLong(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME,
+                yesterdayTimestamp);
+        setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ true);
+
+        new AdvancedProtectionCoordinator(mWindowAndroid);
+        assertEquals(
+                yesterdayTimestamp,
+                sharedPreferences.readLong(
+                        ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME, 0));
+    }
+
+    /**
+     * Test that {@link ChromePreferenceKeys#OS_ADVANCED_PROTECTION_SETTING} and {@link
+     * ChromePreferenceKeys#OS_ADVANCED_PROTECTION_SETTING_UPDATE_TIME} are set by the {@link
+     * AdvancedProtectionCoordinator} constructor if they are not set.
+     */
+    @Test
+    public void testUpdateTimestamp_FirstRun() {
+        var sharedPreferences = ChromeSharedPreferences.getInstance();
+        sharedPreferences.removeKey(ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING);
+        sharedPreferences.removeKey(
+                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME);
+        setPermissionProvider(/* isAdvancedProtectionRequestedByOs= */ true);
+
+        new AdvancedProtectionCoordinator(mWindowAndroid);
+        assertTrue(
+                sharedPreferences.readBoolean(
+                        ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING, false));
+        assertTrue(
+                sharedPreferences.readLong(
+                                ChromePreferenceKeys.OS_ADVANCED_PROTECTION_SETTING_UPDATED_TIME, 0)
+                        != 0);
+    }
 }
diff --git a/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_service_browsertest.cc b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_service_browsertest.cc
index 59606e4..df9a51e28 100644
--- a/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_service_browsertest.cc
@@ -5,8 +5,10 @@
 #include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_service.h"
 
 #include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/test_future.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/notifications/notification_display_service_impl.h"
@@ -24,15 +26,20 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/optimization_guide/core/model_quality/test_model_quality_logs_uploader_service.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/test_model_info_builder.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_constants.h"
 #include "components/safe_browsing/core/browser/db/fake_database_manager.h"
 #include "components/ukm/test_ukm_recorder.h"
+#include "content/public/browser/notification_database_data.h"
+#include "content/public/browser/platform_notification_context.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/test/browser_test.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "third_party/blink/public/common/notifications/platform_notification_data.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
 
 namespace safe_browsing {
 
@@ -651,4 +658,230 @@
   EXPECT_EQ(GetDisplayedPersistentNotifications().size(), 1U);
 }
 
+class NotificationContentDetectionLoggingEnabledBrowserTest
+    : public NotificationContentDetectionBrowserTest {
+ public:
+  NotificationContentDetectionLoggingEnabledBrowserTest() = default;
+
+  void SetUp() override {
+    // Disable the `kPreventLongRunningPredictionModels` feature to prevent
+    // flaky test failures, since these tests may prompt models and obtaining
+    // the result can take a long time.
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        /*enabled_features=*/
+        {{safe_browsing::kOnDeviceNotificationContentDetectionModel,
+          {{"OnDeviceNotificationContentDetectionModelAllowlistSamplingRate",
+            "100"}}},
+         {safe_browsing::kShowWarningsForSuspiciousNotifications,
+          {{"ShowWarningsForSuspiciousNotificationsScoreThreshold", "0"}}},
+         {safe_browsing::kReportNotificationContentDetectionData, {}}},
+        /*disabled_features=*/{
+            optimization_guide::features::kPreventLongRunningPredictionModels});
+
+    NotificationContentDetectionBrowserTestBase::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    // Mock the `ModelQualityLogsUploaderService`.
+    auto logs_uploader = std::make_unique<
+        optimization_guide::TestModelQualityLogsUploaderService>(
+        g_browser_process->local_state());
+    OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+        ->SetModelQualityLogsUploaderServiceForTesting(
+            std::move(logs_uploader));
+
+    NotificationContentDetectionBrowserTest::SetUpOnMainThread();
+  }
+
+  void DisplayPersistentNotification(bool is_allowlisted) {
+    blink::PlatformNotificationData data =
+        CreateNotificationData(base::UTF8ToUTF16(notification_title),
+                               base::UTF8ToUTF16(notification_message), {});
+    GURL origin =
+        (is_allowlisted ? GURL(kAllowlistedUrl) : GURL(kNonAllowlistedUrl));
+
+    // Store notification data in `NotificationDatabase`.
+    content::NotificationDatabaseData notification_database_data;
+    notification_database_data.notification_data.title =
+        base::UTF8ToUTF16(notification_title);
+    notification_database_data.notification_data.body =
+        base::UTF8ToUTF16(notification_message);
+    notification_database_data.origin = origin;
+    browser()
+        ->profile()
+        ->GetStoragePartitionForUrl(origin)
+        ->GetPlatformNotificationContext()
+        ->WriteNotificationData(notification_id,
+                                kFakeServiceWorkerRegistrationId, origin,
+                                notification_database_data, base::DoNothing());
+    base::RunLoop().RunUntilIdle();
+
+    service()->DisplayPersistentNotification(
+        GetNotificationId(/*is_allowlisted=*/true),
+        origin /* service_worker_scope */, origin, data,
+        blink::NotificationResources());
+    optimization_guide::RetryForHistogramUntilCountReached(
+        &histogram_tester(),
+        "OptimizationGuide.ModelExecutor.ExecutionStatus."
+        "NotificationContentDetection",
+        1);
+  }
+
+  optimization_guide::TestModelQualityLogsUploaderService* logs_uploader() {
+    return static_cast<
+        optimization_guide::TestModelQualityLogsUploaderService*>(
+        OptimizationGuideKeyedServiceFactory::GetForProfile(
+            browser()->profile())
+            ->GetModelQualityLogsUploaderService());
+  }
+
+  const std::vector<
+      std::unique_ptr<optimization_guide::proto::LogAiDataRequest>>&
+  uploaded_logs() {
+    return logs_uploader()->uploaded_logs();
+  }
+
+  void VerifyUniqueQualityLog(
+      bool did_user_always_allow_url,
+      bool is_url_on_allowlist,
+      bool was_user_shown_warning,
+      bool did_user_unsubscribe,
+      optimization_guide::proto::SiteEngagementScore site_engagement_score) {
+    const auto& logs = uploaded_logs();
+    ASSERT_EQ(1u, logs.size());
+    auto* const notification_content_detection =
+        logs[0]->mutable_notification_content_detection();
+    ASSERT_TRUE(notification_content_detection->has_request());
+    ASSERT_TRUE(notification_content_detection->has_response());
+    ASSERT_TRUE(notification_content_detection->has_quality());
+    // Verify notification contents get logged.
+    EXPECT_EQ(notification_title, notification_content_detection->request()
+                                      .notification_contents()
+                                      .notification_title());
+    EXPECT_EQ(notification_message, notification_content_detection->request()
+                                        .notification_contents()
+                                        .notification_message());
+    EXPECT_EQ(((did_user_always_allow_url || is_url_on_allowlist)
+                   ? kAllowlistedUrl
+                   : kNonAllowlistedUrl),
+              notification_content_detection->request()
+                  .notification_contents()
+                  .url());
+    // Verify suspicious score between 0 and 100 gets logged.
+    EXPECT_GE(notification_content_detection->response().suspicious_score(), 0);
+    EXPECT_LE(notification_content_detection->response().suspicious_score(),
+              100);
+    // Verify metadata gets logged.
+    EXPECT_EQ(
+        did_user_always_allow_url,
+        notification_content_detection->quality().did_user_always_allow_url());
+    EXPECT_EQ(is_url_on_allowlist,
+              notification_content_detection->quality().is_url_on_allowlist());
+    EXPECT_EQ(
+        was_user_shown_warning,
+        notification_content_detection->quality().was_user_shown_warning());
+    EXPECT_EQ(did_user_unsubscribe,
+              notification_content_detection->quality().did_user_unsubscribe());
+    EXPECT_EQ(
+        site_engagement_score,
+        notification_content_detection->quality().site_engagement_score());
+  }
+
+  std::string GetNotificationId(bool is_allowlisted) {
+    return "p#" +
+           std::string(is_allowlisted ? kAllowlistedUrl : kNonAllowlistedUrl) +
+           "#0" + base::NumberToString(notification_id);
+  }
+
+ private:
+  std::string notification_title = "Title";
+  std::string notification_message = "Message";
+  const int64_t kFakeServiceWorkerRegistrationId = 42;
+  int notification_id = 1;
+};
+
+IN_PROC_BROWSER_TEST_F(NotificationContentDetectionLoggingEnabledBrowserTest,
+                       ReportUnwarnedNotificationAsSpam) {
+  // Display notification with no warning.
+  UpdateNotificationContentDetectionModel();
+  DisplayPersistentNotification(/*is_allowlisted=*/true);
+  EXPECT_EQ(GetDisplayedPersistentNotifications().size(), 1U);
+  bool did_show_warning =
+      IsNotificationSuspicious(GetDisplayedPersistentNotifications()[0]);
+  EXPECT_FALSE(did_show_warning);
+
+  // Report notification as spam and verify MQLS log.
+  bool did_user_unsubscribe = true;
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportUnwarnedNotificationAsSpam(
+      GetNotificationId(/*is_allowlisted=*/true), GURL(kAllowlistedUrl),
+      browser()->profile());
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  VerifyUniqueQualityLog(
+      /*did_user_always_allow_url=*/false,
+      /*is_url_on_allowlist=*/true, did_show_warning, did_user_unsubscribe,
+      /*site_engagement_score=*/
+      optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_NONE);
+}
+
+IN_PROC_BROWSER_TEST_F(NotificationContentDetectionLoggingEnabledBrowserTest,
+                       ReportWarnedNotificationAsSpam) {
+  // Display notification with warning.
+  UpdateNotificationContentDetectionModel();
+  DisplayPersistentNotification(/*is_allowlisted=*/false);
+  EXPECT_EQ(GetDisplayedPersistentNotifications().size(), 1U);
+  bool did_show_warning =
+      IsNotificationSuspicious(GetDisplayedPersistentNotifications()[0]);
+  EXPECT_TRUE(did_show_warning);
+
+  // Report notification as spam and verify MQLS log.
+  bool did_user_unsubscribe = true;
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportWarnedNotificationAsSpam(
+      GetNotificationId(/*is_allowlisted=*/false), GURL(kNonAllowlistedUrl),
+      browser()->profile());
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  VerifyUniqueQualityLog(
+      /*did_user_always_allow_url=*/false,
+      /*is_url_on_allowlist=*/false, did_show_warning, did_user_unsubscribe,
+      /*site_engagement_score=*/
+      optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_NONE);
+}
+
+IN_PROC_BROWSER_TEST_F(NotificationContentDetectionLoggingEnabledBrowserTest,
+                       ReportNotificationAsSafe) {
+  // Display notification with warning.
+  UpdateNotificationContentDetectionModel();
+  DisplayPersistentNotification(/*is_allowlisted=*/false);
+  EXPECT_EQ(GetDisplayedPersistentNotifications().size(), 1U);
+  bool did_show_warning =
+      IsNotificationSuspicious(GetDisplayedPersistentNotifications()[0]);
+  EXPECT_TRUE(did_show_warning);
+
+  // Report notification as safe and verify MQLS log.
+  bool did_user_unsubscribe = false;
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  std::unique_ptr<NotificationHandler> handler =
+      std::make_unique<PersistentNotificationHandler>();
+  handler->ReportNotificationAsSafe(GetNotificationId(/*is_allowlisted=*/false),
+                                    GURL(kNonAllowlistedUrl),
+                                    browser()->profile());
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+  VerifyUniqueQualityLog(
+      /*did_user_always_allow_url=*/false,
+      /*is_url_on_allowlist=*/false, did_show_warning, did_user_unsubscribe,
+      /*site_engagement_score=*/
+      optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_NONE);
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.cc b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.cc
new file mode 100644
index 0000000..31368c7
--- /dev/null
+++ b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.cc
@@ -0,0 +1,141 @@
+// Copyright 2025 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/safe_browsing/notification_content_detection/notification_content_detection_util.h"
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/optimization_guide/core/model_quality/model_quality_log_entry.h"
+#include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_constants.h"
+#include "content/public/browser/notification_database_data.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
+
+namespace {
+
+optimization_guide::proto::SiteEngagementScore EngagementLevelToProtoScore(
+    blink::mojom::EngagementLevel engagement_level) {
+  switch (engagement_level) {
+    case blink::mojom::EngagementLevel::NONE:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_NONE;
+    case blink::mojom::EngagementLevel::MINIMAL:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_MINIMAL;
+    case blink::mojom::EngagementLevel::LOW:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_LOW;
+    case blink::mojom::EngagementLevel::MEDIUM:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_MEDIUM;
+    case blink::mojom::EngagementLevel::HIGH:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_HIGH;
+    case blink::mojom::EngagementLevel::MAX:
+      return optimization_guide::proto::SiteEngagementScore::
+          SITE_ENGAGEMENT_SCORE_MAX;
+  }
+  NOTREACHED();
+}
+
+}  // namespace
+
+namespace safe_browsing {
+
+NotificationContentDetectionMQLSMetadata::
+    NotificationContentDetectionMQLSMetadata(
+        bool did_show_warning,
+        bool did_user_unsubscribe,
+        blink::mojom::EngagementLevel site_engagement_score)
+    : did_show_warning_(did_show_warning),
+      did_user_unsubscribe_(did_user_unsubscribe),
+      site_engagement_score_(site_engagement_score) {}
+
+void SendNotificationContentDetectionDataToMQLSServer(
+    base::WeakPtr<optimization_guide::ModelQualityLogsUploaderService>
+        logs_uploader_service,
+    NotificationContentDetectionMQLSMetadata mqls_metadata,
+    bool success,
+    const content::NotificationDatabaseData& notification_database_data) {
+  if (!success) {
+    return;
+  }
+  // Create `NotificationContents`, for logging.
+  auto notification_contents =
+      std::make_unique<optimization_guide::proto::NotificationContents>();
+  notification_contents->set_notification_title(
+      base::UTF16ToUTF8(notification_database_data.notification_data.title));
+  notification_contents->set_notification_message(
+      base::UTF16ToUTF8(notification_database_data.notification_data.body));
+  for (const auto& action :
+       notification_database_data.notification_data.actions) {
+    notification_contents->add_notification_action_labels(
+        base::UTF16ToUTF8(action->title));
+  }
+  notification_contents->set_url(notification_database_data.origin.spec());
+
+  // Create `NotificationContentDetectionRequest`,
+  // `NotificationContentDetectionResponse`, and
+  // `NotificationContentDetectionQuality`, for logging.
+  auto ncd_request = std::make_unique<
+      optimization_guide::proto::NotificationContentDetectionRequest>();
+  *ncd_request->mutable_notification_contents() = *notification_contents;
+  auto ncd_response = std::make_unique<
+      optimization_guide::proto::NotificationContentDetectionResponse>();
+  auto ncd_quality = std::make_unique<
+      optimization_guide::proto::NotificationContentDetectionQuality>();
+
+  // Add metadata to log if it's defined in the `notification_database_data`.
+  if (notification_database_data.serialized_metadata.contains(
+          safe_browsing::kMetadataDictionaryKey)) {
+    JSONStringValueDeserializer deserializer(
+        notification_database_data.serialized_metadata.at(
+            safe_browsing::kMetadataDictionaryKey));
+    std::unique_ptr<base::Value> metadata =
+        deserializer.Deserialize(nullptr, nullptr);
+    if (!metadata.get() || !metadata->is_dict()) {
+      DVLOG(1) << "Failed to parse metadata.";
+    } else {
+      auto metadata_dict = std::move(*metadata).TakeDict();
+      if (metadata_dict.FindBool(kMetadataIsOriginAllowlistedByUserKey)
+              .has_value()) {
+        ncd_quality->set_did_user_always_allow_url(
+            metadata_dict.FindBool(kMetadataIsOriginAllowlistedByUserKey)
+                .value());
+      }
+      if (metadata_dict.FindBool(kMetadataIsOriginOnGlobalCacheListKey)
+              .has_value()) {
+        ncd_quality->set_is_url_on_allowlist(
+            metadata_dict.FindBool(kMetadataIsOriginOnGlobalCacheListKey)
+                .value());
+      }
+      if (metadata_dict.FindDouble(kMetadataSuspiciousKey).has_value()) {
+        ncd_response->set_suspicious_score(
+            metadata_dict.FindDouble(kMetadataSuspiciousKey).value());
+      }
+    }
+  }
+  ncd_quality->set_was_user_shown_warning(mqls_metadata.did_show_warning_);
+  ncd_quality->set_did_user_unsubscribe(mqls_metadata.did_user_unsubscribe_);
+  ncd_quality->set_site_engagement_score(
+      EngagementLevelToProtoScore(mqls_metadata.site_engagement_score_));
+
+  // Create `NotificationContentDetectionLoggingData`, for uploading the log.
+  std::unique_ptr<
+      optimization_guide::proto::NotificationContentDetectionLoggingData>
+      logging_data = std::make_unique<
+          optimization_guide::proto::NotificationContentDetectionLoggingData>();
+  *logging_data->mutable_request() = *ncd_request;
+  *logging_data->mutable_response() = *ncd_response;
+  *logging_data->mutable_quality() = *ncd_quality;
+
+  // Upload log.
+  auto log_entry = std::make_unique<optimization_guide::ModelQualityLogEntry>(
+      logs_uploader_service);
+  *log_entry->log_ai_data_request()->mutable_notification_content_detection() =
+      *logging_data;
+  optimization_guide::ModelQualityLogEntry::Upload(std::move(log_entry));
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.h b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.h
new file mode 100644
index 0000000..bf69bbf
--- /dev/null
+++ b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util.h
@@ -0,0 +1,42 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Utilities for the SafeBrowsing notification content detection code.
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_NOTIFICATION_CONTENT_DETECTION_NOTIFICATION_CONTENT_DETECTION_UTIL_H_
+#define CHROME_BROWSER_SAFE_BROWSING_NOTIFICATION_CONTENT_DETECTION_NOTIFICATION_CONTENT_DETECTION_UTIL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom-forward.h"
+
+namespace content {
+struct NotificationDatabaseData;
+}  // namespace content
+
+namespace optimization_guide {
+class ModelQualityLogsUploaderService;
+}  // namespace optimization_guide
+
+namespace safe_browsing {
+
+struct NotificationContentDetectionMQLSMetadata {
+  NotificationContentDetectionMQLSMetadata(
+      bool did_show_warning,
+      bool did_user_unsubscribe,
+      blink::mojom::EngagementLevel site_engagement_score);
+  bool did_show_warning_;
+  bool did_user_unsubscribe_;
+  blink::mojom::EngagementLevel site_engagement_score_;
+};
+
+void SendNotificationContentDetectionDataToMQLSServer(
+    base::WeakPtr<optimization_guide::ModelQualityLogsUploaderService>
+        logs_uploader_service,
+    NotificationContentDetectionMQLSMetadata metadata,
+    bool success,
+    const content::NotificationDatabaseData& notification_database_data);
+
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_NOTIFICATION_CONTENT_DETECTION_NOTIFICATION_CONTENT_DETECTION_UTIL_H_
diff --git a/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util_unittest.cc b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util_unittest.cc
new file mode 100644
index 0000000..b666f80
--- /dev/null
+++ b/chrome/browser/safe_browsing/notification_content_detection/notification_content_detection_util_unittest.cc
@@ -0,0 +1,247 @@
+// Copyright 2025 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/safe_browsing/notification_content_detection/notification_content_detection_util.h"
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/test/test_future.h"
+#include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "components/optimization_guide/core/model_quality/test_model_quality_logs_uploader_service.h"
+#include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_constants.h"
+#include "components/safe_browsing/content/browser/notification_content_detection/notification_content_detection_model.h"
+#include "content/public/browser/notification_database_data.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
+
+namespace safe_browsing {
+
+class NotificationContentDetectionUtilTest : public testing::Test {
+ public:
+  NotificationContentDetectionUtilTest()
+      : manager_(TestingBrowserProcess::GetGlobal()) {}
+
+  void SetUp() override {
+    ASSERT_TRUE(manager_.SetUp());
+
+    profile_ = manager_.CreateTestingProfile("foo");
+    mock_optimization_guide_keyed_service_ = static_cast<
+        MockOptimizationGuideKeyedService*>(
+        OptimizationGuideKeyedServiceFactory::GetInstance()
+            ->SetTestingFactoryAndUse(
+                profile_,
+                base::BindRepeating([](content::BrowserContext* context)
+                                        -> std::unique_ptr<KeyedService> {
+                  return std::make_unique<MockOptimizationGuideKeyedService>();
+                })));
+    auto logs_uploader = std::make_unique<
+        optimization_guide::TestModelQualityLogsUploaderService>(
+        manager_.local_state()->Get());
+    mock_optimization_guide_keyed_service_
+        ->SetModelQualityLogsUploaderServiceForTesting(
+            std::move(logs_uploader));
+  }
+
+  optimization_guide::TestModelQualityLogsUploaderService* logs_uploader() {
+    return static_cast<
+        optimization_guide::TestModelQualityLogsUploaderService*>(
+        mock_optimization_guide_keyed_service_
+            ->GetModelQualityLogsUploaderService());
+  }
+
+  const std::vector<
+      std::unique_ptr<optimization_guide::proto::LogAiDataRequest>>&
+  uploaded_logs() {
+    return logs_uploader()->uploaded_logs();
+  }
+
+  void CheckLoggedNotificationContents(
+      optimization_guide::proto::NotificationContents
+          logged_notification_contents,
+      std::string expected_title,
+      std::string expected_body,
+      std::string expected_origin_str) {
+    ASSERT_EQ(expected_title,
+              logged_notification_contents.notification_title());
+    ASSERT_EQ(expected_body,
+              logged_notification_contents.notification_message());
+    ASSERT_EQ(expected_origin_str, logged_notification_contents.url());
+  }
+
+ private:
+  // NOTE: The initialization order of these members matters.
+  content::BrowserTaskEnvironment task_environment_;
+  TestingProfileManager manager_;
+  raw_ptr<TestingProfile> profile_;
+  raw_ptr<MockOptimizationGuideKeyedService>
+      mock_optimization_guide_keyed_service_;
+};
+
+TEST_F(NotificationContentDetectionUtilTest, TestLoggingWithValidMetadata) {
+  std::u16string title = u"Notification title";
+  std::u16string body = u"Notification body";
+  GURL origin = GURL("example.com");
+  float suspicious_score = 70.0;
+
+  content::NotificationDatabaseData database_data;
+  database_data.notification_data.title = title;
+  database_data.notification_data.body = body;
+  database_data.origin = origin;
+  database_data.serialized_metadata[safe_browsing::kMetadataDictionaryKey] =
+      NotificationContentDetectionModel::GetSerializedMetadata(
+          false, false, suspicious_score);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  SendNotificationContentDetectionDataToMQLSServer(
+      logs_uploader()->GetWeakPtr(),
+      NotificationContentDetectionMQLSMetadata(
+          true, true, blink::mojom::EngagementLevel::MEDIUM),
+      /*success=*/true, database_data);
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  CheckLoggedNotificationContents(
+      notification_content_detection->request().notification_contents(),
+      base::UTF16ToUTF8(title), base::UTF16ToUTF8(body), origin.spec());
+
+  // Check logged metadata.
+  ASSERT_EQ(suspicious_score,
+            notification_content_detection->response().suspicious_score());
+  ASSERT_FALSE(notification_content_detection->quality().is_url_on_allowlist());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_always_allow_url());
+  ASSERT_TRUE(
+      notification_content_detection->quality().was_user_shown_warning());
+  ASSERT_TRUE(notification_content_detection->quality().did_user_unsubscribe());
+  ASSERT_EQ(optimization_guide::proto::SiteEngagementScore::
+                SITE_ENGAGEMENT_SCORE_MEDIUM,
+            notification_content_detection->quality().site_engagement_score());
+}
+
+TEST_F(NotificationContentDetectionUtilTest,
+       TestLoggingWithValidMetadataNoSuspiciousScore) {
+  std::u16string title = u"Notification title";
+  std::u16string body = u"Notification body";
+  GURL origin = GURL("example.com");
+
+  content::NotificationDatabaseData database_data;
+  database_data.notification_data.title = title;
+  database_data.notification_data.body = body;
+  database_data.origin = origin;
+  database_data.serialized_metadata[safe_browsing::kMetadataDictionaryKey] =
+      NotificationContentDetectionModel::GetSerializedMetadata(false, false,
+                                                               std::nullopt);
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  SendNotificationContentDetectionDataToMQLSServer(
+      logs_uploader()->GetWeakPtr(),
+      NotificationContentDetectionMQLSMetadata(
+          true, true, blink::mojom::EngagementLevel::MEDIUM),
+      /*success=*/true, database_data);
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+
+  // Check logged metadata.
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  ASSERT_FALSE(notification_content_detection->quality().is_url_on_allowlist());
+  ASSERT_FALSE(
+      notification_content_detection->quality().did_user_always_allow_url());
+}
+
+TEST_F(NotificationContentDetectionUtilTest,
+       TestLoggingWithNullSerializedMetadata) {
+  std::u16string title = u"Notification title";
+  std::u16string body = u"Notification body";
+  GURL origin = GURL("example.com");
+
+  content::NotificationDatabaseData database_data;
+  database_data.notification_data.title = title;
+  database_data.notification_data.body = body;
+  database_data.origin = origin;
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  SendNotificationContentDetectionDataToMQLSServer(
+      logs_uploader()->GetWeakPtr(),
+      NotificationContentDetectionMQLSMetadata(
+          true, false, blink::mojom::EngagementLevel::NONE),
+      /*success=*/true, database_data);
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  CheckLoggedNotificationContents(
+      notification_content_detection->request().notification_contents(),
+      base::UTF16ToUTF8(title), base::UTF16ToUTF8(body), origin.spec());
+}
+
+TEST_F(NotificationContentDetectionUtilTest,
+       TestLoggingWithInvalidSerializedMetadata) {
+  std::u16string title = u"Notification title";
+  std::u16string body = u"Notification body";
+  GURL origin = GURL("example.com");
+
+  content::NotificationDatabaseData database_data;
+  database_data.notification_data.title = title;
+  database_data.notification_data.body = body;
+  database_data.origin = origin;
+  database_data.serialized_metadata[safe_browsing::kMetadataDictionaryKey] =
+      "Invalid";
+
+  base::test::TestFuture<void> log_uploaded_signal;
+  logs_uploader()->WaitForLogUpload(log_uploaded_signal.GetCallback());
+  SendNotificationContentDetectionDataToMQLSServer(
+      logs_uploader()->GetWeakPtr(),
+      NotificationContentDetectionMQLSMetadata(
+          false, true, blink::mojom::EngagementLevel::HIGH),
+      /*success=*/true, database_data);
+  ASSERT_TRUE(log_uploaded_signal.Wait());
+
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(1u, logs.size());
+  auto* const notification_content_detection =
+      logs[0]->mutable_notification_content_detection();
+  CheckLoggedNotificationContents(
+      notification_content_detection->request().notification_contents(),
+      base::UTF16ToUTF8(title), base::UTF16ToUTF8(body), origin.spec());
+}
+
+TEST_F(NotificationContentDetectionUtilTest, TestNoLoggingWhenSuccessFalse) {
+  std::u16string title = u"Notification title";
+  std::u16string body = u"Notification body";
+  GURL origin = GURL("example.com");
+  float suspicious_score = 70.0;
+
+  content::NotificationDatabaseData database_data;
+  database_data.notification_data.title = title;
+  database_data.notification_data.body = body;
+  database_data.origin = origin;
+  database_data.serialized_metadata[safe_browsing::kMetadataDictionaryKey] =
+      NotificationContentDetectionModel::GetSerializedMetadata(
+          false, false, suspicious_score);
+
+  SendNotificationContentDetectionDataToMQLSServer(
+      logs_uploader()->GetWeakPtr(),
+      NotificationContentDetectionMQLSMetadata(
+          true, true, blink::mojom::EngagementLevel::MEDIUM),
+      /*success=*/false, database_data);
+  const auto& logs = uploaded_logs();
+  ASSERT_EQ(0u, logs.size());
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java
index b500841..bbffe5af 100644
--- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java
+++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java
@@ -6,7 +6,9 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.text.SpannableString;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
@@ -18,18 +20,20 @@
 import androidx.annotation.Nullable;
 import androidx.preference.PreferenceViewHolder;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.components.browser_ui.settings.ChromeBasePreference;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.ui.widget.ButtonCompat;
 import org.chromium.ui.widget.CheckableImageView;
 
+@NullMarked
 public class SafetyHubExpandablePreference extends ChromeBasePreference {
-    private String mPrimaryButtonText;
-    private String mSecondaryButtonText;
-    private View.OnClickListener mPrimaryButtonClickListener;
-    private View.OnClickListener mSecondaryButtonClickListener;
+    private @Nullable String mPrimaryButtonText;
+    private @Nullable String mSecondaryButtonText;
+    private @Nullable View.OnClickListener mPrimaryButtonClickListener;
+    private @Nullable View.OnClickListener mSecondaryButtonClickListener;
     private boolean mExpanded = true;
-    private Drawable mDrawable;
+    private @Nullable Drawable mDrawable;
     private boolean mHasProgressBar;
 
     public SafetyHubExpandablePreference(Context context, AttributeSet attrs) {
@@ -92,7 +96,12 @@
 
         TextView summary = (TextView) holder.findViewById(android.R.id.summary);
         assert summary != null;
-        summary.setVisibility(getSummary() != null && isExpanded() ? View.VISIBLE : View.GONE);
+        CharSequence summaryStr = getSummary();
+        summary.setVisibility(summaryStr != null && isExpanded() ? View.VISIBLE : View.GONE);
+
+        if (summaryStr instanceof SpannableString) {
+            summary.setMovementMethod(LinkMovementMethod.getInstance());
+        }
 
         updatePreferenceContentDescription(holder.itemView);
     }
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubModuleProperties.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubModuleProperties.java
index bf0e3b5..00eab24 100644
--- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubModuleProperties.java
+++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubModuleProperties.java
@@ -7,10 +7,12 @@
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** List of properties to designate information about Safety Hub modules. */
+@NullMarked
 public class SafetyHubModuleProperties {
     public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
             new PropertyModel.WritableBooleanPropertyKey();
@@ -22,7 +24,7 @@
             new PropertyModel.WritableObjectPropertyKey<>();
     public static final PropertyModel.WritableObjectPropertyKey<String> TITLE =
             new PropertyModel.WritableObjectPropertyKey<>();
-    public static final PropertyModel.WritableObjectPropertyKey<String> SUMMARY =
+    public static final PropertyModel.WritableObjectPropertyKey<CharSequence> SUMMARY =
             new PropertyModel.WritableObjectPropertyKey<>();
     public static final PropertyModel.WritableObjectPropertyKey<String> PRIMARY_BUTTON_TEXT =
             new PropertyModel.WritableObjectPropertyKey<>();
diff --git a/chrome/browser/speech/speech_recognition_client_browser_interface.cc b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
index 64b31999..c33a3eeb 100644
--- a/chrome/browser/speech/speech_recognition_client_browser_interface.cc
+++ b/chrome/browser/speech/speech_recognition_client_browser_interface.cc
@@ -10,6 +10,7 @@
 #include "base/functional/bind.h"
 #include "base/notimplemented.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/live_caption/caption_util.h"
 #include "components/live_caption/pref_names.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
@@ -36,12 +37,14 @@
                               OnLiveCaptionAvailabilityChanged,
                           base::Unretained(this)));
   // Reuse the same callback, since it does the same thing regardless of which
-  // pref changed.
-  pref_change_registrar_->Add(
-      prefs::kHeadlessCaptionEnabled,
-      base::BindRepeating(&SpeechRecognitionClientBrowserInterface::
-                              OnLiveCaptionAvailabilityChanged,
-                          base::Unretained(this)));
+  // pref changed.  Ignore the pref if the feature is off, though.
+  if (captions::IsHeadlessCaptionFeatureSupported()) {
+    pref_change_registrar_->Add(
+        prefs::kHeadlessCaptionEnabled,
+        base::BindRepeating(&SpeechRecognitionClientBrowserInterface::
+                                OnLiveCaptionAvailabilityChanged,
+                            base::Unretained(this)));
+  }
   pref_change_registrar_->Add(
       prefs::kLiveCaptionLanguageCode,
       base::BindRepeating(&SpeechRecognitionClientBrowserInterface::
@@ -130,9 +133,10 @@
   }
 
   // Captioning is enabled if either Live Caption or Headless Caption.
-  const bool enabled =
-      profile_prefs_->GetBoolean(prefs::kLiveCaptionEnabled) ||
-      profile_prefs_->GetBoolean(prefs::kHeadlessCaptionEnabled);
+  bool enabled = profile_prefs_->GetBoolean(prefs::kLiveCaptionEnabled);
+  if (captions::IsHeadlessCaptionFeatureSupported()) {
+    enabled |= profile_prefs_->GetBoolean(prefs::kHeadlessCaptionEnabled);
+  }
 
   for (auto& observer : live_caption_availibility_observers_) {
     observer->SpeechRecognitionAvailabilityChanged(enabled);
diff --git a/chrome/browser/supervised_user/desktop/supervised_user_extension_browsertest.cc b/chrome/browser/supervised_user/desktop/supervised_user_extension_browsertest.cc
index 54ee43d..70653f80 100644
--- a/chrome/browser/supervised_user/desktop/supervised_user_extension_browsertest.cc
+++ b/chrome/browser/supervised_user/desktop/supervised_user_extension_browsertest.cc
@@ -5,7 +5,6 @@
 #include "base/files/file_path.h"
 #include "base/functional/callback_forward.h"
 #include "base/test/gtest_util.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h"
@@ -17,7 +16,6 @@
 #include "chrome/test/supervised_user/supervision_mixin.h"
 #include "components/supervised_user/core/browser/supervised_user_preferences.h"
 #include "components/supervised_user/core/browser/supervised_user_utils.h"
-#include "components/supervised_user/core/common/features.h"
 #include "components/supervised_user/core/common/pref_names.h"
 #include "components/supervised_user/core/common/supervised_user_constants.h"
 #include "content/public/browser/web_contents.h"
@@ -38,83 +36,19 @@
 
 namespace {
 constexpr char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
-
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-constexpr char kSimpleWithIconCrxId[] = "dehdlahnlebladnfleagmjdapdjdcnlp";
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 }  // namespace
 
 namespace extensions {
 
-enum class ExtensionsParentalControlState : int { kEnabled = 0, kDisabled };
-
-enum class ExtensionManagementSwitch : int {
-  kManagedByExtensions = 0,
-  kManagedByPermissions = 1
-};
-
-std::string CreateTestSuffixFromParam(const auto& info) {
-  return std::string(std::get<0>(info.param) ==
-                             ExtensionsParentalControlState::kEnabled
-                         ? "WithParentalControlsOnExtensions"
-                         : "WithoutParentalControlsOnExtensions") +
-         std::string(std::get<1>(info.param) ==
-                             ExtensionManagementSwitch::kManagedByExtensions
-                         ? "ManagedByExtensions"
-                         : "ManagedByPermissions");
-}
-
 using SupervisionMixinSigninModeCallback =
     base::RepeatingCallback<supervised_user::SupervisionMixin::SignInMode()>;
 
 // Tests interaction between supervised users and extensions.
 class SupervisionExtensionTestBase
     : public InProcessBrowserTestMixinHostSupport<ExtensionBrowserTest>,
-      public ::testing::WithParamInterface<
-          std::tuple<ExtensionsParentalControlState,
-                     ExtensionManagementSwitch,
-                     SupervisionMixinSigninModeCallback>> {
+      public ::testing::WithParamInterface<SupervisionMixinSigninModeCallback> {
  public:
-  SupervisionExtensionTestBase() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-
-    if (ApplyParentalControlsOnExtensions()) {
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-      enabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-      if (GetExtensionManagementSwitch() ==
-          ExtensionManagementSwitch::kManagedByExtensions) {
-        // Managed by preference `SkipParentApprovalToInstallExtensions` (new
-        // flow).
-        enabled_features.push_back(
-            supervised_user::
-                kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-      } else {
-        disabled_features.push_back(
-            supervised_user::
-                kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-      }
-    } else {
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-      disabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-#else
-    // For ChromeOS, the parental controls should always apply to extensions
-    // and this case should not be reached. See the instantiation of the test suite.
-    NOTREACHED();
-#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-    }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  ~SupervisionExtensionTestBase() override { scoped_feature_list_.Reset(); }
+  SupervisionExtensionTestBase() = default;
 
  protected:
   bool IsDisabledForCustodianApproval(const std::string& extension_id) {
@@ -143,20 +77,11 @@
               should_be_enabled);
   }
 
-  bool ApplyParentalControlsOnExtensions() {
-    return std::get<0>(GetParam()) == ExtensionsParentalControlState::kEnabled;
-  }
-
-  ExtensionManagementSwitch GetExtensionManagementSwitch() {
-    return std::get<1>(GetParam());
-  }
-
   supervised_user::SupervisionMixin::SignInMode GetMixinSigninMode() {
-    return std::get<2>(GetParam()).Run();
+    return GetParam().Run();
   }
 
  private:
-  base::test::ScopedFeatureList scoped_feature_list_;
   supervised_user::SupervisionMixin supervision_mixin_{
       mixin_host_,
       this,
@@ -166,57 +91,28 @@
 
 // Tests interaction between supervised users and extensions after the optional
 // supervision is removed from the account.
-class SupervisionRemovalExtensionTest : public SupervisionExtensionTestBase {
- public:
-  SupervisionRemovalExtensionTest() = default;
-};
+class SupervisionRemovalExtensionTest : public SupervisionExtensionTestBase {};
 
-// If extension restrictions apply to supervised users, removing supervision
-// should also remove associated disable reasons, such as
-// DISABLE_CUSTODIAN_APPROVAL_REQUIRED. Extensions should become enabled again
-// after removing supervision. Prevents a regression to crbug/1045625.
-// If extension restrictions are disabled, removing supervision leaves the
-// extension unchanged and enabled.
+// Tests that removing supervision should also remove associated disable
+// reasons, such as DISABLE_CUSTODIAN_APPROVAL_REQUIRED. Extensions should
+// become enabled again after removing supervision. Prevents a regression to
+// crbug.com/1045625.
 IN_PROC_BROWSER_TEST_P(SupervisionRemovalExtensionTest,
                        PRE_RemoveCustodianApprovalRequirement) {
   ASSERT_TRUE(profile()->IsChild());
-  // Set the preference that manages the extensions to the value,
-  // that allows installations (pending approval), if extensions are subject
-  // to parental controls.
-  if (ApplyParentalControlsOnExtensions()) {
-    if (GetExtensionManagementSwitch() ==
-        ExtensionManagementSwitch::kManagedByExtensions) {
-      // Note: Setting to true would have the same effect as the extension
-      // will be installed disabled (pending approval) by `LoadExtension`,
-      // as `LoadExtension` does not reach the point where we grant the parent
-      // approval on installation success in this mode (in WebstorePrivateApi).
-      supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
-          profile(), false);
-    } else {
-      supervised_user_test_util::
-          SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
-    }
-  }
 
   base::FilePath path = test_data_dir_.AppendASCII("good.crx");
-  bool extension_should_be_loaded = !ApplyParentalControlsOnExtensions();
+  bool extension_should_be_loaded = false;
   EXPECT_EQ(LoadExtension(path) != nullptr, extension_should_be_loaded);
   const Extension* extension =
       extension_registry()->GetInstalledExtension(kGoodCrxId);
   EXPECT_TRUE(extension);
 
-  if (ApplyParentalControlsOnExtensions()) {
     // This extension is a supervised user initiated install and should remain
     // disabled.
     EXPECT_TRUE(
         extension_registry()->disabled_extensions().Contains(kGoodCrxId));
     EXPECT_TRUE(IsDisabledForCustodianApproval(kGoodCrxId));
-  } else {
-    // When extension permissions are disabled, the extension is installed and
-    // enabled.
-    EXPECT_TRUE(
-        extension_registry()->enabled_extensions().Contains(kGoodCrxId));
-  }
 }
 
 IN_PROC_BROWSER_TEST_P(SupervisionRemovalExtensionTest,
@@ -240,25 +136,13 @@
 INSTANTIATE_TEST_SUITE_P(
     All,
     SupervisionRemovalExtensionTest,
-    testing::Combine(
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(ExtensionsParentalControlState::kDisabled,
-                        ExtensionsParentalControlState::kEnabled),
-#else
-        // Extensions parental controls always enabled on ChromeOS.
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                        ExtensionManagementSwitch::kManagedByPermissions),
-        testing::Values(base::BindRepeating([]() {
-          // The test covers the removal of supervision. Pre-test should start with a
-          // supervised profile, main test with a regular profile.
-          return content::IsPreTest()
-                     ? supervised_user::SupervisionMixin::SignInMode::
-                           kSupervised
-                     : supervised_user::SupervisionMixin::SignInMode::kRegular;
-        }))),
-    [](const auto& info) { return CreateTestSuffixFromParam(info); });
+    testing::Values(base::BindRepeating([]() {
+      // The test covers the removal of supervision. Pre-test should start with
+      // a supervised profile, main test with a regular profile.
+      return content::IsPreTest()
+                 ? supervised_user::SupervisionMixin::SignInMode::kSupervised
+                 : supervised_user::SupervisionMixin::SignInMode::kRegular;
+    })));
 
 // Tests interaction between supervised users and extensions after the optional
 // supervision is added to an the account.
@@ -291,34 +175,20 @@
   EXPECT_TRUE(extension);
 
   // The extension should be disabled, pending parent approval.
-  EXPECT_EQ(ApplyParentalControlsOnExtensions(),
-            extension_registry()->disabled_extensions().Contains(kGoodCrxId));
-  EXPECT_EQ(ApplyParentalControlsOnExtensions(),
-            IsDisabledForCustodianApproval(kGoodCrxId));
+  EXPECT_TRUE(extension_registry()->disabled_extensions().Contains(kGoodCrxId));
+  EXPECT_TRUE(IsDisabledForCustodianApproval(kGoodCrxId));
 }
 
 INSTANTIATE_TEST_SUITE_P(
     All,
     UserGellerizationExtensionTest,
-    testing::Combine(
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(ExtensionsParentalControlState::kDisabled,
-                        ExtensionsParentalControlState::kEnabled),
-#else
-        // Extensions parental controls always enabled on ChromeOS.
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                        ExtensionManagementSwitch::kManagedByPermissions),
-        testing::Values(base::BindRepeating([]() {
-          //  Pre-test should start with a regular
-          //  profile, main test with a supervised profile.
-          return content::IsPreTest()
-                     ? supervised_user::SupervisionMixin::SignInMode::kRegular
-                     : supervised_user::SupervisionMixin::SignInMode::
-                           kSupervised;
-        }))),
-    [](const auto& info) { return CreateTestSuffixFromParam(info); });
+    testing::Values(base::BindRepeating([]() {
+      //  Pre-test should start with a regular
+      //  profile, main test with a supervised profile.
+      return content::IsPreTest()
+                 ? supervised_user::SupervisionMixin::SignInMode::kRegular
+                 : supervised_user::SupervisionMixin::SignInMode::kSupervised;
+    })));
 
 // Tests the parental controls applied on extensions for supervised users
 // under different values of the Family Link Extensions Switch
@@ -338,10 +208,8 @@
   // installations.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), false);
-  // If parental controls apply the extensions should be disabled, pending
-  // approval.
-  bool should_be_loaded = !ApplyParentalControlsOnExtensions();
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions();
+  bool should_be_loaded = false;
+  bool should_be_enabled = false;
   InstallExtensionAndCheckStatus(should_be_loaded, should_be_enabled);
 }
 
@@ -353,21 +221,14 @@
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
 
-  // If extensions are managed by the Extensions
-  // Family Link switch, the extension should become enabled and
-  // parent-approved.
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions() ||
-                           GetExtensionManagementSwitch() ==
-                               ExtensionManagementSwitch::kManagedByExtensions;
-  EXPECT_EQ(should_be_enabled,
-            extension_registry()->enabled_extensions().Contains(kGoodCrxId));
+  // The extension should become enabled and parent-approved.
+  EXPECT_TRUE(extension_registry()->enabled_extensions().Contains(kGoodCrxId));
 
   // Flip the Extensions preference to OFF.
   // The previously approved and enabled extensions should remain enabled.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), false);
-  EXPECT_EQ(should_be_enabled,
-            extension_registry()->enabled_extensions().Contains(kGoodCrxId));
+  EXPECT_TRUE(extension_registry()->enabled_extensions().Contains(kGoodCrxId));
 }
 
 IN_PROC_BROWSER_TEST_P(
@@ -376,14 +237,7 @@
   // Set the Extensions preference to ON.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
-
-  // If parental controls apply and the extensions are managed by the Permission
-  // switch, they should be disabled, pending approval. IF not parental controls
-  // apply, or the extensions are managed by the Extensions switch, it will be
-  // installed enabled with parent approval.
-  bool should_be_loaded = !ApplyParentalControlsOnExtensions() ||
-                          GetExtensionManagementSwitch() ==
-                              ExtensionManagementSwitch::kManagedByExtensions;
+  bool should_be_loaded = true;
   bool should_be_enabled = should_be_loaded;
   InstallExtensionAndCheckStatus(should_be_loaded, should_be_enabled);
 
@@ -395,28 +249,12 @@
             extension_registry()->enabled_extensions().Contains(kGoodCrxId));
 }
 
-// TODO(b/321240025): Add test case on permission increase.
-// TODO(b/321240025): Add test case on an extension trying to change settings of
-// a website.
-
 INSTANTIATE_TEST_SUITE_P(
     All,
     ParentApprovalHandlingByExtensionSwitchTest,
-    testing::Combine(
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(ExtensionsParentalControlState::kDisabled,
-                        ExtensionsParentalControlState::kEnabled),
-#else
-        // Extensions parental controls always enabled on ChromeOS.
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                        ExtensionManagementSwitch::kManagedByPermissions),
-        testing::Values(base::BindRepeating([]() {
-          return supervised_user::SupervisionMixin::SignInMode::kSupervised;
-        }))),
-    [](const auto& info) { return CreateTestSuffixFromParam(info); });
+    testing::Values(base::BindRepeating([]() {
+      return supervised_user::SupervisionMixin::SignInMode::kSupervised;
+    })));
 
 class ParentApprovalRequestTest
     : public SupervisionExtensionTestBase,
@@ -477,8 +315,6 @@
 IN_PROC_BROWSER_TEST_P(ParentApprovalRequestTest,
                        RequestToInstallExtensionMissingCustodianInfo) {
   // Set the preferences to the default values from Family Link.
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), false);
 
@@ -549,89 +385,8 @@
 INSTANTIATE_TEST_SUITE_P(
     All,
     ParentApprovalRequestTest,
-    testing::Combine(
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                        ExtensionManagementSwitch::kManagedByPermissions),
-        testing::Values(base::BindRepeating([]() {
-          return supervised_user::SupervisionMixin::SignInMode::kSupervised;
-        }))),
-    [](const auto& info) { return CreateTestSuffixFromParam(info); });
-
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-// Tests the behavior of existing and new extensions for a supervised user
-// on the release of the `SkipParentalApproval` feature.
-class SupervisedUserSkipParentalApprovalModeReleaseTest
-    : public SupervisionExtensionTestBase {
- public:
-  SupervisedUserSkipParentalApprovalModeReleaseTest() {
-    // Over-writes any feature enabling of the parent class.
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-
-    if (content::IsPreTest()) {
-      // Start with inactive features on Pre-test.
-      disabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      // Simulate feature release on Main test.
-      enabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  ~SupervisedUserSkipParentalApprovalModeReleaseTest() override {
-    scoped_feature_list_.Reset();
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_P(SupervisedUserSkipParentalApprovalModeReleaseTest,
-                       PRE_OnFeatureReleaseForSupervisedUserWithExtensions) {
-  ASSERT_TRUE(profile()->IsChild());
-  // Before the release of features `SkipParentalApprovalToInstallExtensions`
-  // and `EnableExtensionsPermissionsForSupervisedUsersOnDesktop` no parental
-  // controls apply.
-  InstallExtensionAndCheckStatus(/*should_be_loaded=*/true,
-                                 /*should_be_enabled=*/true);
-}
-
-IN_PROC_BROWSER_TEST_P(SupervisedUserSkipParentalApprovalModeReleaseTest,
-                       OnFeatureReleaseForSupervisedUserWithExtensions) {
-  ASSERT_TRUE(profile()->IsChild());
-  // On feature release the extensions are enabled (due to the local parent
-  // approval migration).
-  EXPECT_TRUE(extension_registry()->enabled_extensions().Contains(kGoodCrxId));
-
-  // Extensions installed after the feature release (i.e. local installation,
-  // synced extensions) are disabled and pending approval.
-  InstallExtensionAndCheckStatus(/*should_be_loaded=*/false,
-                                 /*should_be_enabled=*/false,
-                                 kSimpleWithIconCrxId, "simple_with_icon.crx");
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    SupervisedUserSkipParentalApprovalModeReleaseTest,
-    testing::Combine(
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions),
-        testing::Values(base::BindRepeating([]() {
-          return supervised_user::SupervisionMixin::SignInMode::kSupervised;
-        }))),
-    [](const auto& info) { return CreateTestSuffixFromParam(info); });
-
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
+    testing::Values(base::BindRepeating([]() {
+      return supervised_user::SupervisionMixin::SignInMode::kSupervised;
+    })));
 
 }  // namespace extensions
diff --git a/chrome/browser/supervised_user/supervised_user_extension_unittest.cc b/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
index c2eb0c16..95a9ed0 100644
--- a/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_extension_unittest.cc
@@ -54,14 +54,9 @@
   }
 
   ExtensionServiceTestWithInstall::InstallState GetDefaultInstalledState() {
-    // Default behavior:
-    // When parental controls are enabled the extensions will be installed
-    // but disabled until custodian approvals are performed in the offered
-    // default modes.
-    // When parental controls are disabled the extensions will be installed
-    // and enabled.
-    return ApplyParentalControlsOnExtensions() ? INSTALL_WITHOUT_LOAD
-                                               : INSTALL_NEW;
+    // Extensions will be installed but disabled until custodian approvals
+    // are performed in the default extensions parental control mode.
+    return INSTALL_WITHOUT_LOAD;
   }
 
   const Extension* InstallPermissionsTestExtension(
@@ -130,9 +125,7 @@
   const Extension* CheckDisabledForPermissionsIncrease(
       const std::string& extension_id) {
     EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
-    if (ApplyParentalControlsOnExtensions()) {
-      EXPECT_TRUE(IsPendingCustodianApproval(extension_id));
-    }
+    EXPECT_TRUE(IsPendingCustodianApproval(extension_id));
     ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
     EXPECT_TRUE(extension_prefs->HasDisableReason(
         extension_id, disable_reason::DISABLE_PERMISSIONS_INCREASE));
@@ -153,7 +146,7 @@
     // The extension must now be installed.
     EXPECT_TRUE(extension);
     EXPECT_EQ(extension->id(), id);
-    if (ApplyParentalControlsOnExtensions() && install_state != INSTALL_NEW) {
+    if (install_state != INSTALL_NEW) {
       CheckDisabledForCustodianApproval(id);
     } else {
       CheckEnabled(id);
@@ -163,17 +156,10 @@
   }
 
   void SetDefaultParentalControlSettings() {
-    supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
-        profile(), false);
     supervised_user_test_util::
         SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
   }
 
-  // Returns whether parental controls should be enabled for this platform.
-  // Should always be true for ChromeOS, and depends of enabling certain
-  // features on Win/Linux/Mac.
-  virtual bool ApplyParentalControlsOnExtensions() = 0;
-
  private:
   // Returns true if the extension has disable reason permissions_increase or
   // custodian_approval_required. Tests the Webstore Private Api.
@@ -200,73 +186,10 @@
       supervised_user_extensions_delegate_;
 };
 
-enum class ExtensionsParentalControlState : int { kEnabled = 0, kDisabled = 1 };
-
-enum class ExtensionManagementSwitch : int {
-  kManagedByExtensions = 0,
-  kManagedByPermissions = 1
-};
-
-class SupervisedUserExtensionTest
-    : public SupervisedUserExtensionTestBase,
-      public ::testing::WithParamInterface<
-          std::tuple<ExtensionsParentalControlState,
-                     ExtensionManagementSwitch>> {
- public:
-  SupervisedUserExtensionTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-    // Parental restrictions on the extensions installations for supervised
-    // users on Desktop apply when the feature
-    // kEnableExtensionsPermissionsForSupervisedUsersOnDesktop is enabled.
-    // Extension parental controls for supervised users are already enabled on
-    // ChromeOS by default.
-    if (ApplyParentalControlsOnExtensions()) {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-      enabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-      if (GetExtensionManagementSwitch() ==
-          ExtensionManagementSwitch::kManagedByExtensions) {
-        // Managed by preference `SkipParentApprovalToInstallExtensions` (new
-        // flow).
-        enabled_features.push_back(
-            supervised_user::
-                kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-      } else {
-        disabled_features.push_back(
-            supervised_user::
-                kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-      }
-    } else {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-      disabled_features.push_back(
-          supervised_user::
-              kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    }
-
-    feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  bool ApplyParentalControlsOnExtensions() override {
-    return std::get<0>(GetParam()) == ExtensionsParentalControlState::kEnabled;
-  }
-
-  ExtensionManagementSwitch GetExtensionManagementSwitch() {
-    return std::get<1>(GetParam());
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
+class SupervisedUserExtensionTest : public SupervisedUserExtensionTestBase {};
 
 // Tests that regular users are not affecting supervised user UMA metrics.
-TEST_P(SupervisedUserExtensionTest,
+TEST_F(SupervisedUserExtensionTest,
        RegularUsersNotAffectingSupervisedUserMetrics) {
   InitServices(/*profile_is_supervised=*/false);
 
@@ -290,7 +213,7 @@
 
 // Tests that simulating custodian approval for regular users doesn't cause any
 // unexpected behavior.
-TEST_P(SupervisedUserExtensionTest,
+TEST_F(SupervisedUserExtensionTest,
        CustodianApprovalDoesNotAffectRegularUsers) {
   InitServices(/*profile_is_supervised=*/false);
   supervised_user_test_util::
@@ -312,10 +235,9 @@
   CheckEnabled(id);
 }
 
-// Tests that if the extension parental controls are enabled, adding supervision
-// to a regular account (Gellerization) disables previously installed
-// extensions. Otherwise the extension remains enabled.
-TEST_P(SupervisedUserExtensionTest, ExtensionsStateAfterGellerization) {
+// Tests that adding supervision to a regular account (Gellerization)
+// disables previously installed extensions.
+TEST_F(SupervisedUserExtensionTest, ExtensionsStateAfterGellerization) {
   InitServices(/*profile_is_supervised=*/false);
   SetDefaultParentalControlSettings();
 
@@ -329,7 +251,6 @@
   // Now make the profile supervised.
   profile()->AsTestingProfile()->SetIsSupervisedProfile();
 
-  if (ApplyParentalControlsOnExtensions()) {
     // The extension should be disabled now pending custodian approval.
     CheckDisabledForCustodianApproval(id);
 
@@ -344,37 +265,24 @@
 
     // The extension should be disabled again now.
     CheckDisabledForCustodianApproval(id);
-  } else {
-    // The extension should still be enabled.
-    CheckEnabled(id);
-  }
 }
 
 // Tests that extensions that are disabled pending parent approval
 // for supervised users, become re-enabled if the user becomes unsupervised.
-TEST_P(SupervisedUserExtensionTest, ExtensionsStateAfterGraduation) {
+TEST_F(SupervisedUserExtensionTest, ExtensionsStateAfterGraduation) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
-  // When extension parental controls are enabled on the current platform the
-  // extensions will be installed but disabled until the custodian approval.
-  // When extension parental controls are disabled the extensions will be
-  // installed and enabled.
-  auto install_state =
-      ApplyParentalControlsOnExtensions() ? INSTALL_WITHOUT_LOAD : INSTALL_NEW;
+  // The extensions will be installed, but will be disabled until the custodian
+  // approval.
+  auto install_state = INSTALL_WITHOUT_LOAD;
   base::FilePath path = data_dir().AppendASCII("good.crx");
   const Extension* extension = InstallCRX(path, install_state);
   ASSERT_TRUE(extension);
   std::string id = extension->id();
-
-  if (ApplyParentalControlsOnExtensions()) {
     // This extension is a supervised user initiated install and should remain
     // disabled.
     CheckDisabledForCustodianApproval(id);
-  } else {
-    // The new installed extension should be enabled.
-    CheckEnabled(id);
-  }
 
   // Make the profile un-supervised.
   profile()->AsTestingProfile()->SetIsSupervisedProfile(false);
@@ -384,11 +292,9 @@
 }
 
 // Tests that a child user is allowed to install extensions under the default
-// values of the Family Link "Permissions" and "Extensions" toggles.
-// If the extension parental controls apply the newly-installed extensions
-// are disabled until approved by the parent.
-// Otherwise the newly-installed extensions are enabled.
-TEST_P(SupervisedUserExtensionTest, InstallAllowedForSupervisedUser) {
+// value of the Family Link "Extensions" toggles.
+// The newly-installed extensions are disabled until approved by the parent.
+TEST_F(SupervisedUserExtensionTest, InstallAllowedForSupervisedUser) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
@@ -398,7 +304,6 @@
   ASSERT_TRUE(extension);
   std::string id = extension->id();
 
-  if (ApplyParentalControlsOnExtensions()) {
     // This extension is a supervised user initiated install and should remain
     // disabled.
     CheckDisabledForCustodianApproval(id);
@@ -413,18 +318,11 @@
 
     // The extension should be disabled again now.
     CheckDisabledForCustodianApproval(id);
-  } else {
-    // The new installed extension should be enabled.
-    CheckEnabled(id);
-  }
 }
 
 // Tests that supervised users may approve permission updates without parent
-// approval under the default values of the Family Link "Permissions" and
-// "Extensions" toggles, when parental controls apply to extensions.
-// If parental controls do not apply, the child can approve permission
-// updates by default.
-TEST_P(SupervisedUserExtensionTest, UpdateWithPermissionsIncrease) {
+// approval under the default values of the Family Link "Extensions" toggle.
+TEST_F(SupervisedUserExtensionTest, UpdateWithPermissionsIncrease) {
   InitServices(true);
   SetDefaultParentalControlSettings();
 
@@ -444,7 +342,6 @@
 
   std::string id =
       InstallPermissionsTestExtension(GetDefaultInstalledState())->id();
-  if (ApplyParentalControlsOnExtensions()) {
     // Simulate parent approval.
     supervised_user_extensions_delegate()->AddExtensionApproval(
         *registry()->GetInstalledExtension(id));
@@ -460,7 +357,6 @@
     EXPECT_EQ(1, user_action_tester.GetActionCount(
                      SupervisedUserExtensionsMetricsRecorder::
                          kApprovalGrantedActionName));
-  }
   // The extension should be enabled.
   CheckEnabled(id);
 
@@ -476,7 +372,6 @@
   // The extension should be enabled.
   CheckEnabled(id);
 
-  if (ApplyParentalControlsOnExtensions()) {
     // Remove extension approval.
     supervised_user_extensions_delegate()->RemoveExtensionApproval(
         *registry()->GetInstalledExtension(id));
@@ -495,80 +390,11 @@
 
     // The extension should be disabled now.
     CheckDisabledForCustodianApproval(id);
-  }
-}
-
-// Tests that when extensions are managed by the "Permissions" Family Link
-// switch, if the toggle is disabled, then:
-// If the extension parental controls are enabled, child users cannot approve
-// permission updates, otherwise they can approve permission updates.
-// When extensions are managed by the "Extensions" Family Link switch,
-// toggling the "Permissions" switch has no effect.
-TEST_P(SupervisedUserExtensionTest,
-       ChildUserCannotApproveAdditionalPermissions) {
-  InitServices(/*profile_is_supervised=*/true);
-  // Default settings allow to install the extension.
-  SetDefaultParentalControlSettings();
-
-  base::HistogramTester histogram_tester;
-
-  std::string id =
-      InstallPermissionsTestExtension(GetDefaultInstalledState())->id();
-  const Extension* extension1 = nullptr;
-  if (ApplyParentalControlsOnExtensions()) {
-    extension1 = CheckDisabledForCustodianApproval(id);
-    ASSERT_TRUE(extension1);
-
-    // Simulate parent granting approval for the initial version.
-    supervised_user_extensions_delegate()->AddExtensionApproval(*extension1);
-    // The extension should be enabled now.
-    CheckEnabled(id);
-
-    // Should see 1 kApprovalGranted metric count.
-    histogram_tester.ExpectUniqueSample(
-        SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
-        SupervisedUserExtensionsMetricsRecorder::UmaExtensionState::
-            kApprovalGranted,
-        1);
-    histogram_tester.ExpectTotalCount(
-        SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName, 1);
-  } else {
-    // The extension is installed as enabled.
-    extension1 = CheckEnabled(id);
-    ASSERT_TRUE(extension1);
-  }
-
-  // Update to a new version with increased permissions.
-  std::string version2("2");
-  UpdatePermissionsTestExtension(id, version2, DISABLED);
-  const Extension* extension2 = CheckDisabledForPermissionsIncrease(id);
-  ASSERT_TRUE(extension2);
-
-  // Flip the Permissions toggle to off.
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
-  // Now the extension is blocked since it requires additional permissions.
-  // Simulate child granting approval for the new permissions.
-  registrar()->GrantPermissionsAndEnableExtension(*extension2);
-
-  if (ApplyParentalControlsOnExtensions() &&
-      GetExtensionManagementSwitch() ==
-          ExtensionManagementSwitch::kManagedByPermissions) {
-    // If the extensions are managed by the Permissions Family Link switch, then
-    // the extension is still disabled because the child cannot grant additional
-    // permissions.
-    CheckDisabledForPermissionsIncrease(id);
-  } else {
-    // The extension should now be enabled and the version number increased.
-    extension2 = CheckEnabled(id);
-    EXPECT_TRUE(extension2);
-    EXPECT_EQ(extension2->version(), base::Version(version2));
-  }
 }
 
 // Tests that if an approved extension is updated to a newer version that
 // doesn't require additional permissions, it is still enabled.
-TEST_P(SupervisedUserExtensionTest, UpdateWithoutPermissionIncrease) {
+TEST_F(SupervisedUserExtensionTest, UpdateWithoutPermissionIncrease) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
@@ -601,7 +427,6 @@
   // The version should have changed again.
   EXPECT_EQ(base::Version(version3), extension2->version());
 
-  if (ApplyParentalControlsOnExtensions()) {
     // Check that the approved extension id has been updated in the prefs as
     // well. Prefs are updated via sync.
     PrefService* pref_service = profile()->GetPrefs();
@@ -609,18 +434,11 @@
     const base::Value::Dict& approved_extensions =
         pref_service->GetDict(prefs::kSupervisedUserApprovedExtensions);
     EXPECT_TRUE(approved_extensions.FindString(id));
-  }
 }
 
-// Tests that when extensions are managed by the "Permissions" Family Link
-// toggle, if the "Permissions" toggle is disabled, then:
-// - If extension parental controls are enabled child users cannot install new
-// extensions.
-// - If extension parental controls are disabled child users can install new
-// extensions.
-// When extensions are managed by the "Extensions" Family Link toggle,
-// toggling the "Permissions" switch has no effect to the installation.
-TEST_P(SupervisedUserExtensionTest,
+// Tests that toggling the "Permissions" switch has no longer effect on the
+// extensions' installation.
+TEST_F(SupervisedUserExtensionTest,
        SupervisedUserCannotInstallExtensionUnderPermissionsToggle) {
   InitServices(/*profile_is_supervised=*/true);
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
@@ -629,33 +447,16 @@
       SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
 
   base::FilePath path = data_dir().AppendASCII("good.crx");
-  // When extension parental controls are enabled the extensions will fail
-  // installation. When extension parental control are disabled the extensions
-  // will be installed and enabled.
-  if (ApplyParentalControlsOnExtensions()) {
-    if (GetExtensionManagementSwitch() ==
-        ExtensionManagementSwitch::kManagedByPermissions) {
-      // Installation has failed.
-      const Extension* extension = InstallCRX(path, INSTALL_FAILED);
-      EXPECT_FALSE(extension);
-    } else if (GetExtensionManagementSwitch() ==
-               ExtensionManagementSwitch::kManagedByExtensions) {
-      // Installation is successful. The extension is installed disabled in the
-      // default mode.
-      const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
-      EXPECT_TRUE(extension);
-      CheckDisabledForCustodianApproval(extension->id());
-    }
-  } else {
-    const Extension* extension = InstallCRX(path, INSTALL_NEW);
-    EXPECT_TRUE(extension);
-    CheckEnabled(extension->id());
-  }
+  // Installation is successful. The extension is installed disabled in the
+  // default mode.
+  const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
+  EXPECT_TRUE(extension);
+  CheckDisabledForCustodianApproval(extension->id());
 }
 
-// Tests that disabling the "Permissions" Family Link toggle,
+// Tests that disabling the "Permissions" Family Link toggle
 // has no effect on regular users.
-TEST_P(SupervisedUserExtensionTest, RegularUserCanInstallExtension) {
+TEST_F(SupervisedUserExtensionTest, RegularUserCanInstallExtension) {
   InitServices(/*profile_is_supervised=*/false);
   supervised_user_test_util::
       SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
@@ -670,12 +471,15 @@
   CheckEnabled(extension->id());
 }
 
-// Tests that if the "Permissions" Family Link toggle becomes disabled,
+// Tests that if the "Permissions" Family Link toggle becomes disabled
 // previously approved extensions are still enabled.
-TEST_P(SupervisedUserExtensionTest,
+TEST_F(SupervisedUserExtensionTest,
        PermissionsToggleOffDoesNotAffectAlreadyEnabled) {
   InitServices(/*profile_is_supervised=*/true);
-  SetDefaultParentalControlSettings();
+  supervised_user_test_util::
+      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), false);
+  supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
+      profile(), false);
 
   // The installation helper function checks that the extension is initially
   // disabled.
@@ -683,10 +487,8 @@
       InstallNoPermissionsTestExtension(GetDefaultInstalledState());
   std::string id = extension->id();
 
-  if (ApplyParentalControlsOnExtensions()) {
-    // Now approve the extension.
-    supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
-  }
+  // Now approve the extension.
+  supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
 
   // The extension should be enabled now.
   CheckEnabled(id);
@@ -700,79 +502,49 @@
 }
 
 // Tests that extensions installed when the "Extensions" Family Link toggle
-// applies and is enabled, are installed enabled and have been granted parent
-// approval.
-TEST_P(SupervisedUserExtensionTest,
+// is "On" are installed enabled and are granted parent approval.
+TEST_F(SupervisedUserExtensionTest,
        ExtensionsToggleOnGrantsParentApprovalOnInstallation) {
   InitServices(/*profile_is_supervised=*/true);
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
   // Set the "Extensions" toggle to true, allowing installation without parental
   // approval.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
-
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions() ||
-                           GetExtensionManagementSwitch() ==
-                               ExtensionManagementSwitch::kManagedByExtensions;
-
-  // If the Extensions toggle applies, the extension is installed and enabled.
-  auto install_state =
-      should_be_enabled ? INSTALL_NEW : GetDefaultInstalledState();
-  const Extension* extension = InstallNoPermissionsTestExtension(install_state);
+  const Extension* extension = InstallNoPermissionsTestExtension(INSTALL_NEW);
   std::string id = extension->id();
 
-  if (should_be_enabled) {
     // The extension has already been granted approval on its installation.
     CheckEnabled(id);
-  } else {
-    CheckDisabledForCustodianApproval(id);
-  }
 }
 
-// Tests that for extensions installed under the enabled "Extensions" Family
-// Link toggle the approval remains on installed extensions if the switch is
-// toggled to false.
-TEST_P(SupervisedUserExtensionTest,
+// Tests that installed extensions remain parent-approved and enabled
+// if the "Extensions" switch is toggled to false.
+TEST_F(SupervisedUserExtensionTest,
        ExtensionsToggleOffDoesNotAffectAlreadyEnabled) {
   InitServices(/*profile_is_supervised=*/true);
-  supervised_user_test_util::
-      SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);
   // Set the "Extensions" toggle to true, allowing installation without parental
   // approval.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
 
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions() ||
-                           GetExtensionManagementSwitch() ==
-                               ExtensionManagementSwitch::kManagedByExtensions;
-
   // If the Extensions toggle applies, the extension is installed and enabled.
-  auto install_state =
-      should_be_enabled ? INSTALL_NEW : GetDefaultInstalledState();
-  const Extension* extension = InstallNoPermissionsTestExtension(install_state);
+  const Extension* extension = InstallNoPermissionsTestExtension(INSTALL_NEW);
   std::string id = extension->id();
 
-  if (should_be_enabled) {
     // The extension has already been granted approval on its installation.
     CheckEnabled(id);
-  } else {
-    CheckDisabledForCustodianApproval(id);
-  }
 
   // Custodian sets the "Extensions" toggle to false.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), false);
 
   // Already installed and enabled extensions should remain that way.
-  if (should_be_enabled) {
     CheckEnabled(id);
-  }
 }
 
-// Tests that for extensions installed under the enabled "Extensions" Family
-// Link, toggling the switch from false to true grants parental approval.
-TEST_P(SupervisedUserExtensionTest,
+// Tests toggling the "Extensions" Family Link switch from false to true grants
+// parental approval.
+TEST_F(SupervisedUserExtensionTest,
        ExtensionsToggleOnGrantsMissingParentalApproval) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
@@ -781,41 +553,26 @@
       InstallNoPermissionsTestExtension(GetDefaultInstalledState());
   std::string id = extension->id();
 
-  if (ApplyParentalControlsOnExtensions()) {
     CheckDisabledForCustodianApproval(id);
-  } else {
-    CheckEnabled(id);
-  }
-
   // Custodian sets the "Extensions" toggle to True.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
 
-  if (!ApplyParentalControlsOnExtensions() ||
-      GetExtensionManagementSwitch() ==
-          ExtensionManagementSwitch::kManagedByExtensions) {
-    // If the "Extensions" toggle manages the extensions, the extension has been
-    // granted approval and becomes enabled on toggling the switch.
-    CheckEnabled(id);
-  } else {
-    // If the "Permissions" toggle manages the extensions, toggling the
-    // "Extensions" switch has no effect.
-    CheckDisabledForCustodianApproval(id);
-  }
+  // The extension has been
+  // granted approval and becomes enabled on toggling the switch.
+  CheckEnabled(id);
 }
 
 // Tests the case when the extension approval arrives through sync before the
 // extension itself is installed.
-TEST_P(SupervisedUserExtensionTest, ExtensionApprovalBeforeInstallation) {
+TEST_F(SupervisedUserExtensionTest, ExtensionApprovalBeforeInstallation) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
   scoped_refptr<const Extension> extension =
       ExtensionBuilder(good_crx).SetID(good_crx).SetVersion("0").Build();
-  if (ApplyParentalControlsOnExtensions()) {
-    // Now approve the extension.
-    supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
-  }
+  // Approve the extension.
+  supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
 
   // Now install an extension, it should be enabled upon installation.
   base::FilePath path = data_dir().AppendASCII("good.crx");
@@ -825,10 +582,9 @@
   CheckEnabled(good_crx);
 }
 
-// Tests that when the `SkipParentApprovalToInstallExtensions` feature is first
-// released (so Extensions are managed by Family Link "Extensions" toggle),
-// existing extensions remain enabled on Desktop. On ChromeOS they are disabled.
-TEST_P(SupervisedUserExtensionTest,
+// Tests that when the parental controls start applying on Desktop (solution
+// release), existing extensions remain enabled. On ChromeOS they are disabled.
+TEST_F(SupervisedUserExtensionTest,
        ExtensionsOnDesktopRemainEnabledOnSkipParentApprovalRelease) {
   ExtensionServiceInitParams params;
   params.profile_is_supervised = true;
@@ -849,31 +605,23 @@
   CreateExtensionManager();
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions() ||
-                           GetExtensionManagementSwitch() ==
-                               ExtensionManagementSwitch::kManagedByExtensions;
+  // On Desktop, before the release of parental controls the extensions would be
+  // installed and enabled by default.
+  CheckEnabled(good_crx);
 #else
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions();
+  CheckDisabledForCustodianApproval(good_crx);
 #endif
-  if (should_be_enabled) {
-    CheckEnabled(good_crx);
-  } else {
-    CheckDisabledForCustodianApproval(good_crx);
-  }
 
-  if (ApplyParentalControlsOnExtensions()) {
-    // Parent approval can be granted even if the extension behaves already as
-    // parent-approved on Win/Linux/Mac.
-    supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
-  }
+  // Parent approval can be granted even if the extension behaves already as
+  // parent-approved on Win/Linux/Mac.
+  supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
   CheckEnabled(good_crx);
 }
 
-// Tests when the `SkipParentApprovalToInstallExtensions` feature is firstly
-// released (so Extensions are managed by Family Link "Extensions" toggle)
-// existing extensions that have been marked parent-approved on Desktop by
-// default can be upgraded without further parental approval.
-TEST_P(SupervisedUserExtensionTest,
+// Tests that when the parental controls start applying on Desktop (solution
+// release), existing extensions that have been marked parent-approved on
+// Desktop by default can be upgraded without further parental approval.
+TEST_F(SupervisedUserExtensionTest,
        ExtensionsEnabledOnSkipParentApprovalReleaseCanBeUpgraded) {
   ExtensionServiceInitParams params;
   params.profile_is_supervised = true;
@@ -894,17 +642,12 @@
   CreateExtensionManager();
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions() ||
-                           GetExtensionManagementSwitch() ==
-                               ExtensionManagementSwitch::kManagedByExtensions;
+  // On Desktop, before the release of parental controls the extensions would be
+  // installed and enabled by default.
+  CheckEnabled(extension_id);
 #else
-  bool should_be_enabled = !ApplyParentalControlsOnExtensions();
+  CheckDisabledForCustodianApproval(extension_id);
 #endif
-  if (should_be_enabled) {
-    CheckEnabled(extension_id);
-  } else {
-    CheckDisabledForCustodianApproval(extension_id);
-  }
 
   // Update to a new version with increased permissions.
   UpdatePermissionsTestExtension(extension_id, "2", DISABLED);
@@ -914,22 +657,19 @@
 
   // Grant the upgraded permissions.
   registrar()->GrantPermissionsAndEnableExtension(*extension2);
-  if (should_be_enabled) {
-    // When no parental controls apply, or when Managed by the Extensions
-    // switch, the extensions becomes enabled upon granting the increased
-    // permission. The parental approval granted at SU Extension manager
-    // creation remains.
-    CheckEnabled(extension_id);
-  } else {
-    // When managed by the Permissions switch the extension is still disabled
-    // as parent approval was never granted.
-    CheckDisabledForCustodianApproval(extension_id);
-  }
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+  // The parental approval granted at SU Extension manager still applies.
+  CheckEnabled(extension_id);
+#else
+  // In ChromeOS the extension is still disabled as parent approval was never
+  // granted.
+  CheckDisabledForCustodianApproval(extension_id);
+#endif
 }
 
 // Tests that uninstalling a parent-approved extension removes the parental
 // approval.
-TEST_P(SupervisedUserExtensionTest, UnistallingRevokesParentApproval) {
+TEST_F(SupervisedUserExtensionTest, UnistallingRevokesParentApproval) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
@@ -937,18 +677,15 @@
       InstallNoPermissionsTestExtension(GetDefaultInstalledState());
   std::string extension_id = extension->id();
 
-  if (ApplyParentalControlsOnExtensions()) {
     CheckDisabledForCustodianApproval(extension_id);
     // Simulate parent approval.
     supervised_user_extensions_delegate()->AddExtensionApproval(*extension);
-  }
 
   CheckEnabled(extension_id);
-  EXPECT_EQ(ApplyParentalControlsOnExtensions(),
-            profile()
-                ->GetPrefs()
-                ->GetDict(prefs::kSupervisedUserApprovedExtensions)
-                .contains(extension_id));
+  EXPECT_TRUE(profile()
+                  ->GetPrefs()
+                  ->GetDict(prefs::kSupervisedUserApprovedExtensions)
+                  .contains(extension_id));
 
   // Uninstall the extension.
   std::u16string error;
@@ -960,79 +697,9 @@
                    .contains(extension_id));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    SupervisedUserExtensionTest,
-    testing::Combine(
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-        testing::Values(ExtensionsParentalControlState::kDisabled,
-                        ExtensionsParentalControlState::kEnabled),
-#else
-        // On ChromeOS the extension parental controls are on by default.
-        testing::Values(ExtensionsParentalControlState::kEnabled),
-#endif
-        testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                        ExtensionManagementSwitch::kManagedByPermissions)),
-    [](const auto& info) {
-      return std::string(std::get<0>(info.param) ==
-                                 ExtensionsParentalControlState::kEnabled
-                             ? "WithParentalControlsOnExtensions"
-                             : "WithoutParentalControlsOnExtensions") +
-             std::string(std::get<1>(info.param) ==
-                                 ExtensionManagementSwitch::kManagedByExtensions
-                             ? "ManagedByExtensionsSwitch"
-                             : "ManagedByPermissionsSwitch");
-    });
-
-// Test class for cases that apply only when extension parental controls are
-// enabled.
-class SupervisedUserWithEnabledExtensionParentalControlsTest
-    : public SupervisedUserExtensionTestBase,
-      public ::testing::WithParamInterface<ExtensionManagementSwitch> {
- public:
-  SupervisedUserWithEnabledExtensionParentalControlsTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-    // Parental controls on the extensions for supervised users
-    // on Desktop apply when the feature
-    // kEnableExtensionsPermissionsForSupervisedUsersOnDesktop is enabled.
-    // Extension parental controls for supervised users are already enabled on
-    // ChromeOS by default.
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
-    if (GetExtensionManagementSwitch() ==
-        ExtensionManagementSwitch::kManagedByExtensions) {
-      // Managed by preference `SkipParentApprovalToInstallExtensions` (new
-      // flow).
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  // SupervisedUserExtensionTestBase implementation:
-  bool ApplyParentalControlsOnExtensions() override { return true; }
-
-  ExtensionManagementSwitch GetExtensionManagementSwitch() {
-    return (GetParam());
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
 // Tests that the kApprovalGranted UMA metric only increments once without
 // duplication for the same extension id.
-TEST_P(SupervisedUserWithEnabledExtensionParentalControlsTest,
-       DontTriggerMetricsIfAlreadyApproved) {
+TEST_F(SupervisedUserExtensionTest, DontTriggerMetricsIfAlreadyApproved) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
@@ -1089,8 +756,7 @@
 // Tests that parent approval is necessary but not sufficient to enable
 // extensions when both disable reasons custodian_approval_required and
 // permissions_increase are present.
-TEST_P(SupervisedUserWithEnabledExtensionParentalControlsTest,
-       ParentApprovalNecessaryButNotSufficient) {
+TEST_F(SupervisedUserExtensionTest, ParentApprovalNecessaryButNotSufficient) {
   InitServices(/*profile_is_supervised=*/true);
   SetDefaultParentalControlSettings();
 
@@ -1121,17 +787,4 @@
   // The extension should be enabled.
   CheckEnabled(id);
 }
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    SupervisedUserWithEnabledExtensionParentalControlsTest,
-    testing::Values(ExtensionManagementSwitch::kManagedByExtensions,
-                    ExtensionManagementSwitch::kManagedByPermissions),
-    [](const auto& info) {
-      return std::string(info.param ==
-                                 ExtensionManagementSwitch::kManagedByExtensions
-                             ? "ManagedByExtensionsSwitch"
-                             : "ManagedByPermissionsSwitch");
-    });
-
 }  // namespace extensions
diff --git a/chrome/browser/supervised_user/supervised_user_extensions_manager_unittest.cc b/chrome/browser/supervised_user/supervised_user_extensions_manager_unittest.cc
index df20302..49e3edde 100644
--- a/chrome/browser/supervised_user/supervised_user_extensions_manager_unittest.cc
+++ b/chrome/browser/supervised_user/supervised_user_extensions_manager_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/test/gtest_util.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_service_test_base.h"
@@ -19,7 +18,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
 #include "components/supervised_user/core/browser/supervised_user_utils.h"
-#include "components/supervised_user/core/common/features.h"
 #include "components/supervised_user/core/common/pref_names.h"
 #include "components/version_info/version_info.h"
 #include "extensions/browser/extension_registrar.h"
@@ -29,15 +27,6 @@
 #include "extensions/common/manifest_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-enum class ExtensionsManagingToggle : int {
-  /* Extensions are managed by the
-     "Permissions for sites, apps and extensions" FL button. */
-  kPermissions = 0,
-  /* Extensions are managed by the dedicated
-    "Skip parent approval to install extensions" FL button. */
-  kExtensions = 1
-};
-
 using extensions::Extension;
 
 class SupervisedUserExtensionsManagerTestBase
@@ -103,39 +92,9 @@
 };
 
 class SupervisedUserExtensionsManagerTest
-    : public SupervisedUserExtensionsManagerTestBase,
-      public ::testing::WithParamInterface<ExtensionsManagingToggle> {
- public:
-  SupervisedUserExtensionsManagerTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
+    : public SupervisedUserExtensionsManagerTestBase {};
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
-    if (GetExtensionsManagingToggle() ==
-        ExtensionsManagingToggle::kExtensions) {
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  ExtensionsManagingToggle GetExtensionsManagingToggle() { return GetParam(); }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_P(SupervisedUserExtensionsManagerTest,
+TEST_F(SupervisedUserExtensionsManagerTest,
        ExtensionManagementPolicyProviderWithoutSUInitiatedInstalls) {
   MakeSupervisedUserExtensionsManager();
   supervised_user_test_util::
@@ -158,51 +117,31 @@
   }
 
   scoped_refptr<const extensions::Extension> extension = MakeExtension();
-  if (GetExtensionsManagingToggle() == ExtensionsManagingToggle::kPermissions) {
-    // Now check a different kind of extension; the supervised user should not
-    // be able to load it. It should also not need to remain installed.
-    std::u16string error_1;
-    EXPECT_FALSE(manager_->UserMayLoad(extension.get(), &error_1));
-    EXPECT_FALSE(error_1.empty());
+  // Installations are always allowed.
+  std::u16string error_1;
+  EXPECT_TRUE(manager_->UserMayLoad(extension.get(), &error_1));
+  EXPECT_TRUE(error_1.empty());
 
-    std::u16string error_2;
-    EXPECT_FALSE(manager_->UserMayInstall(extension.get(), &error_2));
-    EXPECT_FALSE(error_2.empty());
-  } else {
-    // Under the "Extensions" switch, installation are always allowed.
-    std::u16string error_1;
-    EXPECT_TRUE(manager_->UserMayLoad(extension.get(), &error_1));
-    EXPECT_TRUE(error_1.empty());
+  std::u16string error_2;
+  EXPECT_TRUE(manager_->UserMayInstall(extension.get(), &error_2));
+  EXPECT_TRUE(error_2.empty());
 
-    std::u16string error_2;
-    EXPECT_TRUE(manager_->UserMayInstall(extension.get(), &error_2));
-    EXPECT_TRUE(error_2.empty());
-  }
-
-    std::u16string error_3;
-    EXPECT_FALSE(manager_->MustRemainInstalled(extension.get(), &error_3));
-    EXPECT_TRUE(error_3.empty());
+  std::u16string error_3;
+  EXPECT_FALSE(manager_->MustRemainInstalled(extension.get(), &error_3));
+  EXPECT_TRUE(error_3.empty());
 
 #if DCHECK_IS_ON()
   EXPECT_FALSE(manager_->GetDebugPolicyProviderName().empty());
 #endif
 }
 
-TEST_P(SupervisedUserExtensionsManagerTest,
+TEST_F(SupervisedUserExtensionsManagerTest,
        ExtensionManagementPolicyProviderWithSUInitiatedInstalls) {
   MakeSupervisedUserExtensionsManager();
-  if (GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions) {
     // Enable child users to initiate extension installs by simulating the
     // toggling of "Skip parent approval to install extensions" to disabled.
     supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
         profile(), false);
-  } else {
-    // Enable child users to initiate extension installs by simulating the
-    // toggling of "Permissions for sites, apps and extensions" to enabled.
-    supervised_user_test_util::
-        SetSupervisedUserExtensionsMayRequestPermissionsPref(profile_.get(),
-                                                             true);
-  }
 
   ASSERT_TRUE(profile_->IsChild());
 
@@ -239,11 +178,10 @@
 #endif
 }
 
-// Tests that on Desktop (Win/Linux/Mac) platforms, when the feature
-// `kEnableSupervisedUserSkipParentApprovalToInstallExtensions` is first
-// enabled, present extensions will be marked as locally parent-approved
+// Tests that on Desktop (Win/Linux/Mac) platforms,
+// present extensions will be marked as locally parent-approved
 // when the SupervisedUserExtensionsManager is created for a supervised user.
-TEST_P(SupervisedUserExtensionsManagerTest,
+TEST_F(SupervisedUserExtensionsManagerTest,
        MigrateExtensionsToLocallyApproved) {
   ASSERT_TRUE(profile_->IsChild());
   base::HistogramTester histogram_tester;
@@ -271,14 +209,8 @@
   bool has_local_approval_migration_run = false;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   auto expected_migration_state =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions
-          ? supervised_user::LocallyParentApprovedExtensionsMigrationState::
-                kComplete
-          : supervised_user::LocallyParentApprovedExtensionsMigrationState::
-                kNeedToRun;
-  has_local_approval_migration_run =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions;
-
+      supervised_user::LocallyParentApprovedExtensionsMigrationState::kComplete;
+  has_local_approval_migration_run = true;
   EXPECT_EQ(
       static_cast<int>(expected_migration_state),
       prefs->GetInteger(prefs::kLocallyParentApprovedExtensionsMigrationState));
@@ -310,10 +242,8 @@
 }
 
 // Tests that extensions missing parent approval are granted parent approval
-// on their installation, when the extensions are managed by the Extensions
-// toggle and the toggle is ON. If extensions are managed by the Permissions
-// toggle, the extensions remain disabled and pending approval.
-TEST_P(SupervisedUserExtensionsManagerTest,
+// on their installation, when the "Extensions" Family Link toggle is ON.
+TEST_F(SupervisedUserExtensionsManagerTest,
        GrantParentApprovalOnInstallationWhenExtensionsToggleOn) {
   ASSERT_TRUE(profile_->IsChild());
   base::HistogramTester histogram_tester;
@@ -352,17 +282,13 @@
   histogram_tester.ExpectTotalCount(
       extensions::kExtensionApprovalsCountOnExtensionToggleHistogramName, 0);
   // Set the Extensions switch to ON. Install another extension which should be
-  // granted parental approval by the end of the installation, if the Extensions
-  // switch manages them.
+  // granted parental approval by the end of the installation.
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
 
-  // Toggling the extensions results in granting approval to the existing
-  // extension if the Extensions switch manages them.
-  int approved_extensions_count =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions
-          ? 1
-          : 0;
+  // Toggling the "Extensions" results in granting approval to the existing
+  // extension.
+  int approved_extensions_count = 1;
   histogram_tester.ExpectBucketCount(
       SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
       SupervisedUserExtensionsMetricsRecorder::UmaExtensionState::
@@ -376,7 +302,7 @@
           ImplicitExtensionApprovalEntryPoint::
               kOnExtensionsSwitchFlippedToEnabled,
       approved_extensions_count);
-  // The number of auto-approved extensions is reco
+  // The number of auto-approved extensions is recorded.
   histogram_tester.ExpectTotalCount(
       extensions::kExtensionApprovalsCountOnExtensionToggleHistogramName,
       approved_extensions_count);
@@ -387,23 +313,19 @@
   registrar()->OnExtensionInstalled(extn_with_switch_on.get(),
                                     /*page_ordinal=*/syncer::StringOrdinal());
 
-  bool is_extension_approved =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions;
-  EXPECT_EQ(is_extension_approved,
-            manager_->IsExtensionAllowed(*extn_with_switch_on.get()));
-  EXPECT_EQ(is_extension_approved,
-            !manager_->MustRemainDisabled(extn_with_switch_on.get(), &reason));
-  EXPECT_EQ(is_extension_approved,
-            profile()
-                ->GetPrefs()
-                ->GetDict(prefs::kSupervisedUserApprovedExtensions)
-                .contains(extn_with_switch_on->id()));
+  EXPECT_TRUE(manager_->IsExtensionAllowed(*extn_with_switch_on.get()));
+  EXPECT_TRUE(
+      !manager_->MustRemainDisabled(extn_with_switch_on.get(), &reason));
+  EXPECT_TRUE(profile()
+                  ->GetPrefs()
+                  ->GetDict(prefs::kSupervisedUserApprovedExtensions)
+                  .contains(extn_with_switch_on->id()));
 
   histogram_tester.ExpectBucketCount(
       SupervisedUserExtensionsMetricsRecorder::kExtensionsHistogramName,
       SupervisedUserExtensionsMetricsRecorder::UmaExtensionState::
           kApprovalGrantedByDefault,
-      approved_extensions_count + (is_extension_approved ? 1 : 0));
+      approved_extensions_count + 1);
   // The migration to locally approved extensions has occurred before we
   // installed any extensions, so not local approvals have been granted.
   histogram_tester.ExpectBucketCount(
@@ -421,19 +343,16 @@
       SupervisedUserExtensionsMetricsRecorder::
           ImplicitExtensionApprovalEntryPoint::
               OnExtensionInstallationWithExtensionsSwitchEnabled,
-      is_extension_approved ? 1 : 0);
+      1);
   histogram_tester.ExpectTotalCount(
       SupervisedUserExtensionsMetricsRecorder::
           kImplicitParentApprovalGrantEntryPointHistogramName,
-      approved_extensions_count + (is_extension_approved ? 1 : 0));
+      approved_extensions_count + 1);
 }
 
 // Tests that extensions missing parent approval are granted parent approval
-// when the extensions are managed by the Extensions toggle and the toggle is
-// flipped to ON.
-// If extensions are managed by the Permissions toggle, the extensions remain
-// disabled and pending approval.
-TEST_P(SupervisedUserExtensionsManagerTest,
+// when the "Extensions" toggle is flipped to ON.
+TEST_F(SupervisedUserExtensionsManagerTest,
        GrantParentApprovalOnExtensionsWhenExtensionsToggleSetToOn) {
   ASSERT_TRUE(profile_->IsChild());
 
@@ -474,22 +393,18 @@
   supervised_user_test_util::SetSkipParentApprovalToInstallExtensionsPref(
       profile(), true);
 
-  bool is_extension_approved =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions;
-  EXPECT_EQ(is_extension_approved,
-            manager_->IsExtensionAllowed(*extn_with_switch_off.get()));
-  EXPECT_EQ(is_extension_approved,
-            !manager_->MustRemainDisabled(extn_with_switch_off.get(), &reason));
-  EXPECT_EQ(is_extension_approved,
-            profile()
-                ->GetPrefs()
-                ->GetDict(prefs::kSupervisedUserApprovedExtensions)
-                .contains(extn_with_switch_off->id()));
+  EXPECT_TRUE(manager_->IsExtensionAllowed(*extn_with_switch_off.get()));
+  EXPECT_TRUE(
+      !manager_->MustRemainDisabled(extn_with_switch_off.get(), &reason));
+  EXPECT_TRUE(profile()
+                  ->GetPrefs()
+                  ->GetDict(prefs::kSupervisedUserApprovedExtensions)
+                  .contains(extn_with_switch_off->id()));
 }
 
 // Tests the local approval is revoked on uninstalling the extension or
 // when the extension gains normal parental approval.
-TEST_P(SupervisedUserExtensionsManagerTest, RevokeLocalApproval) {
+TEST_F(SupervisedUserExtensionsManagerTest, RevokeLocalApproval) {
   ASSERT_TRUE(profile_->IsChild());
 
   scoped_refptr<const Extension> locally_approved_extn1 =
@@ -504,8 +419,7 @@
 
   bool has_local_approval_migration_run = false;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-  has_local_approval_migration_run =
-      GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions;
+  has_local_approval_migration_run = true;
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 
   auto* prefs = profile()->GetPrefs();
@@ -534,18 +448,6 @@
   EXPECT_TRUE(manager_->IsExtensionAllowed(*locally_approved_extn2));
 }
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         SupervisedUserExtensionsManagerTest,
-                         testing::Values(ExtensionsManagingToggle::kPermissions,
-                                         ExtensionsManagingToggle::kExtensions),
-                         [](const auto& info) {
-                           return std::string(
-                               info.param ==
-                                       ExtensionsManagingToggle::kExtensions
-                                   ? "ManagedByExtensions"
-                                   : "ManagedByPermissions");
-                         });
-
 // Whether the local approval extension migration for
 // Win/Mac/Linux platforms has already run at the beginning of
 // each test case.
@@ -556,50 +458,21 @@
 
 // Tests the managed extensions' state when an existing profile becomes
 // supervised.
-class AddingSupervisionTest
-    : public SupervisedUserExtensionsManagerTestBase,
-      public ::testing::WithParamInterface<
-          std::tuple<ExtensionsManagingToggle,
-                     LocalApprovalMigrationForDesktopState>> {
+class AddingSupervisionTest : public SupervisedUserExtensionsManagerTestBase,
+                              public ::testing::WithParamInterface<
+                                  LocalApprovalMigrationForDesktopState> {
  public:
-  AddingSupervisionTest() {
-    std::vector<base::test::FeatureRef> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-    enabled_features.push_back(
-        supervised_user::
-            kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
-#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-
-    if (GetExtensionsManagingToggle() ==
-        ExtensionsManagingToggle::kExtensions) {
-      enabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    } else {
-      disabled_features.push_back(
-          supervised_user::
-              kEnableSupervisedUserSkipParentApprovalToInstallExtensions);
-    }
-    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
-  }
-
-  ExtensionsManagingToggle GetExtensionsManagingToggle() {
-    return std::get<0>(GetParam());
-  }
+  AddingSupervisionTest() = default;
 
   LocalApprovalMigrationForDesktopState
   GetInitialLocalApprovalMigrationForDesktopState() {
-    return std::get<1>(GetParam());
+    return GetParam();
   }
 
   void MaybeMarkLocalApprovalMigrationDone() {
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
     if (GetInitialLocalApprovalMigrationForDesktopState() ==
-            LocalApprovalMigrationForDesktopState::kExecuted &&
-        GetExtensionsManagingToggle() ==
-            ExtensionsManagingToggle::kExtensions) {
+        LocalApprovalMigrationForDesktopState::kExecuted) {
       auto* prefs = profile()->GetPrefs();
       CHECK(prefs);
       prefs->SetInteger(
@@ -610,16 +483,13 @@
     }
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
   }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 // Tests that on Desktop (Win/Linux/Mac) platforms, when:
-// 1) the feature `kEnableSupervisedUserSkipParentApprovalToInstallExtensions`
-// is first enabled and
+// 1) parental controls on extensions apply for the first time (solution
+// release) and
 // 2) a supervised user sings-in on an existing unsupervised profile or
-//    the existing profile becomes supervised (Gellerized) then
+// the existing profile becomes supervised (Gellerized) then
 // the existing extensions remain disabled and pending approval.
 // The states of the present extensions should not be impacted by the local
 // extension approval migration that is executed on feature release for Desktop
@@ -637,9 +507,8 @@
   supervised_user::LocallyParentApprovedExtensionsMigrationState
       expected_migragtion_state = supervised_user::
           LocallyParentApprovedExtensionsMigrationState::kNeedToRun;
-  if (GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions &&
-      GetInitialLocalApprovalMigrationForDesktopState() ==
-          LocalApprovalMigrationForDesktopState::kExecuted) {
+  if (GetInitialLocalApprovalMigrationForDesktopState() ==
+      LocalApprovalMigrationForDesktopState::kExecuted) {
     expected_migragtion_state = supervised_user::
         LocallyParentApprovedExtensionsMigrationState::kComplete;
   }
@@ -648,10 +517,8 @@
   // Create the object under test.
   MakeSupervisedUserExtensionsManager();
 
-  if (GetExtensionsManagingToggle() == ExtensionsManagingToggle::kExtensions) {
-    expected_migragtion_state = supervised_user::
-        LocallyParentApprovedExtensionsMigrationState::kComplete;
-  }
+  expected_migragtion_state =
+      supervised_user::LocallyParentApprovedExtensionsMigrationState::kComplete;
   CheckLocalApprovalMigrationForDesktopState(expected_migragtion_state);
 
   auto* prefs = profile()->GetPrefs();
@@ -682,26 +549,18 @@
 INSTANTIATE_TEST_SUITE_P(
     All,
     AddingSupervisionTest,
-    testing::Combine(
-        testing::Values(ExtensionsManagingToggle::kPermissions,
-                        ExtensionsManagingToggle::kExtensions),
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
-        testing::Values(LocalApprovalMigrationForDesktopState::kExecuted,
-                        LocalApprovalMigrationForDesktopState::kPending)),
+    testing::Values(LocalApprovalMigrationForDesktopState::kExecuted,
+                    LocalApprovalMigrationForDesktopState::kPending),
 #else   // ChromeOS case
         // The local approval migration is not applicable for ChromeOS.
         // The test just needs to be executed once, the value of
         // LocalApprovalMigrationForDesktopState does not matter.
-        testing::Values(LocalApprovalMigrationForDesktopState::kExecuted)),
+    testing::Values(LocalApprovalMigrationForDesktopState::kExecuted),
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
     [](const auto& info) {
-      return std::string(std::get<0>(info.param) ==
-                                 ExtensionsManagingToggle::kExtensions
-                             ? "ManagedByExtensions"
-                             : "ManagedByPermissions") +
-             std::string(
-                 std::get<1>(info.param) ==
-                         LocalApprovalMigrationForDesktopState::kExecuted
-                     ? "PostReleaseSkipParentApprovalFeature"
-                     : "PreReleaseSkipParentApprovalFeature");
+      return std::string(
+          info.param == LocalApprovalMigrationForDesktopState::kExecuted
+              ? "PostReleaseSkipParentApprovalFeature"
+              : "PreReleaseSkipParentApprovalFeature");
     });
diff --git a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
index 9aaf71f..04968cb 100644
--- a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
+++ b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
@@ -1709,4 +1709,9 @@
       std::inserter(syncable_prefs, syncable_prefs.end()));
   return syncable_prefs;
 }
+
+bool ChromeSyncablePrefsDatabase::IsPreferenceAlwaysSyncing(
+    std::string_view pref_name) const {
+  return common_syncable_prefs_database_.IsPreferenceAlwaysSyncing(pref_name);
+}
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.h b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.h
index 3ae6e999..8d172d6 100644
--- a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.h
+++ b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.h
@@ -24,6 +24,8 @@
   std::map<std::string_view, sync_preferences::SyncablePrefMetadata>
   GetAllSyncablePrefsForTest() const;
 
+  bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const override;
+
  private:
   // This defines the list of preferences that are syncable across all
   // platforms.
diff --git a/chrome/browser/sync/prefs/chrome_syncable_prefs_database_unittest.cc b/chrome/browser/sync/prefs/chrome_syncable_prefs_database_unittest.cc
index 66e13b1..89d754b 100644
--- a/chrome/browser/sync/prefs/chrome_syncable_prefs_database_unittest.cc
+++ b/chrome/browser/sync/prefs/chrome_syncable_prefs_database_unittest.cc
@@ -7,6 +7,8 @@
 #include <string_view>
 
 #include "base/test/metrics/histogram_enum_reader.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/sync/base/features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -30,4 +32,23 @@
   }
 }
 
+TEST(ChromeSyncablePrefsDatabaseTest, IsPreferenceAlwaysSyncing) {
+  base::test::ScopedFeatureList scoped_feature_list(
+      syncer::kSyncSupportAlwaysSyncingPriorityPreferences);
+  browser_sync::ChromeSyncablePrefsDatabase db;
+  EXPECT_TRUE(db.IsPreferenceAlwaysSyncing(
+      sync_preferences::kSyncableAlwaysSyncingPriorityPrefForTesting));
+  EXPECT_FALSE(db.IsPreferenceAlwaysSyncing(
+      sync_preferences::kSyncablePriorityPrefForTesting));
+
+  // Currently, only priority preferences are allowed in the allowlist.
+  const std::map<std::string_view, sync_preferences::SyncablePrefMetadata>
+      syncable_prefs = db.GetAllSyncablePrefsForTest();
+  for (const auto& [pref_name, metadata] : syncable_prefs) {
+    if (db.IsPreferenceAlwaysSyncing(pref_name)) {
+      EXPECT_EQ(metadata.data_type(), syncer::PRIORITY_PREFERENCES);
+    }
+  }
+}
+
 }  // namespace
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
index e450679..21f09d3 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
@@ -13,7 +13,7 @@
  * A read only list of {@link Tab}s. This list understands the concept of an incognito list as well
  * as a currently selected tab (see {@link #index}).
  */
-@MockedInTests
+@MockedInTests // Needed due to R8's computeDelayedInterfaceMethodSyntheticBridges. b/147584922
 @NullMarked
 public interface TabList {
     // Keep this in sync with chrome/browser/ui/android/tab_model/tab_model.cc
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index d718597f..9426966 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -1029,12 +1029,13 @@
 IN_PROC_BROWSER_TEST_P(TaskManagerOOPIFBrowserTest, KillSubframe) {
   ShowTaskManager();
 
+  // Navigate to a page A(B,C).
   content::TestNavigationObserver navigation_observer(
       browser()->tab_strip_model()->GetActiveWebContents());
   GURL main_url(embedded_test_server()->GetURL(
       "/cross-site/a.com/iframe_cross_site.html"));
   int expected_c_subframes = 1;
-  if (content::IsIsolatedOriginRequiredToGuaranteeDedicatedProcess()) {
+  if (!content::AreAllSitesIsolatedForTesting()) {
     // Isolate b.com so that it will be forced into a separate process. This
     // will prevent the main frame and c.com subframe from being placed in the
     // the process that gets killed by this test.
diff --git a/chrome/browser/tpcd/metadata/manager_browsertest.cc b/chrome/browser/tpcd/metadata/manager_browsertest.cc
index 71f1411d..c4a9bd23d 100644
--- a/chrome/browser/tpcd/metadata/manager_browsertest.cc
+++ b/chrome/browser/tpcd/metadata/manager_browsertest.cc
@@ -1070,8 +1070,7 @@
  public:
   CookieControlsModePrefManagerBrowserTest() {
     scoped_feature_list_.InitWithFeatureStates(
-        {{privacy_sandbox::kAddLimit3pcsSetting, true},
-         {net::features::kForceThirdPartyCookieBlocking, false},
+        {{net::features::kForceThirdPartyCookieBlocking, false},
          {net::features::kThirdPartyStoragePartitioning, false},
          {net::features::kThirdPartyPartitionedStorageAllowedByDefault, true},
          {content_settings::features::kTrackingProtection3pcd, false}});
@@ -1097,30 +1096,6 @@
 };
 
 IN_PROC_BROWSER_TEST_F(CookieControlsModePrefManagerBrowserTest,
-                       EnablesMitigationsWhenThirdPartyCookiesLimited) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  GURL first_party_url = https_server()->GetURL(kFirstPartyHost, "/");
-  GURL third_party_url = https_server()->GetURL(kThirdPartyHost1, "/");
-
-  browser()->profile()->GetPrefs()->SetInteger(
-      prefs::kCookieControlsMode,
-      static_cast<int>(content_settings::CookieControlsMode::kLimited));
-  AddWildcardMetadataGrant();
-
-  EXPECT_TRUE(GetCookieSettings()->MitigationsEnabledFor3pcd());
-  EXPECT_EQ(GetCookieSettings()->GetCookieSetting(
-                third_party_url, net::SiteForCookies(), first_party_url,
-                net::CookieSettingOverrides()),
-            ContentSetting::CONTENT_SETTING_ALLOW);
-
-  NavigateToPageWithFrame(kFirstPartyHost);
-  NavigateFrameTo(kThirdPartyHost1, "/browsing_data/site_data.html");
-  ExpectCookie(GetFrame(), /*expected=*/true);
-  ExpectStorage(GetFrame(), /*expected=*/true, /*setting_source_user=*/false,
-                /*is_3psp_enabled=*/false);
-}
-
-IN_PROC_BROWSER_TEST_F(CookieControlsModePrefManagerBrowserTest,
                        DisablesMitigationsWhenThirdPartyCookiesBlocked) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   GURL first_party_url = https_server()->GetURL(kFirstPartyHost, "/");
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 17d00f0..6371b50d 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1696,6 +1696,7 @@
       "//chrome/browser/background:background",
       "//chrome/browser/browsing_data:constants",
       "//chrome/browser/contextual_cueing",
+      "//chrome/browser/first_party_sets",
       "//chrome/browser/lifetime:termination_notification",
       "//chrome/browser/privacy_sandbox",
 
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
index f7d6c28a..53b1a2f 100644
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
@@ -169,14 +169,15 @@
      *     other app menu items if necessary.
      * @param headerResourceId The resource id for a view to add as the first item in menu list. Can
      *     be null if no such view is required. See {@link ListView#addHeaderView(View)}.
+     * @param groupDividerResourceId The resource id of divider menu items. This will be used to
+     *     determine the number of dividers that appear in the menu.
      * @param highlightedItemId The resource id of the menu item that should be highlighted. Can be
      *     {@code null} if no item should be highlighted. Note that {@code 0} is dedicated to custom
      *     menu items and can be declared by external apps.
-     * @param groupDividerResourceId The resource id of divider menu items. This will be used to
-     *     determine the number of dividers that appear in the menu.
      * @param customViewBinders See {@link AppMenuPropertiesDelegate#getCustomViewBinders()}.
      * @param isMenuIconAtStart Whether the menu is being shown from a menu icon positioned at the
      *     start.
+     * @param addTopPaddingBeforeFirstRow Whether top padding is needed above the first row.
      */
     void show(
             Context context,
@@ -190,7 +191,8 @@
             @Nullable Integer highlightedItemId,
             @Nullable List<CustomViewBinder> customViewBinders,
             boolean isMenuIconAtStart,
-            @ControlsPosition int controlsPosition) {
+            @ControlsPosition int controlsPosition,
+            boolean addTopPaddingBeforeFirstRow) {
         mPopup = new PopupWindow(context);
         mPopup.setFocusable(true);
         mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
@@ -253,9 +255,7 @@
             heightList.add(getMenuItemHeight(itemId, context, customViewBinders));
         }
 
-        ViewGroup contentView =
-                (ViewGroup) LayoutInflater.from(context).inflate(R.layout.app_menu_layout, null);
-        contentView.setBackgroundResource(R.drawable.app_menu_bottom_padding_bg);
+        View contentView = createAppMenuContentView(context, addTopPaddingBeforeFirstRow);
 
         if (SysUtils.isLowEndDevice()) {
             var sharedDrawable = AppCompatResources.getDrawable(context, R.drawable.popup_bg_8dp);
@@ -709,6 +709,17 @@
         mMenuItemEnterAnimator.start();
     }
 
+    private View createAppMenuContentView(Context context, boolean addTopPaddingBeforeFirstRow) {
+        ViewGroup contentView =
+                (ViewGroup) LayoutInflater.from(context).inflate(R.layout.app_menu_layout, null);
+        if (addTopPaddingBeforeFirstRow) {
+            contentView.setBackgroundResource(R.drawable.default_popup_menu_bg);
+        } else {
+            contentView.setBackgroundResource(R.drawable.app_menu_bottom_padding_bg);
+        }
+        return contentView;
+    }
+
     private int inflateFooter(int footerResourceId, View contentView, int menuWidth) {
         if (footerResourceId == 0) {
             mFooterView = null;
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
index c5fda80..0d5d4b7 100644
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
@@ -603,6 +603,7 @@
         if (mDelegate.shouldShowHeader(appRect.height())) {
             headerResourceId = mDelegate.getHeaderResourceId();
         }
+
         mAppMenu.show(
                 wrapper,
                 anchorView,
@@ -615,11 +616,17 @@
                 mHighlightMenuId,
                 customViewBinders,
                 mDelegate.isMenuIconAtStart(),
-                mBrowserControlsStateProvider.getControlsPosition());
+                mBrowserControlsStateProvider.getControlsPosition(),
+                addTopPaddingBeforeFirstRow());
         assumeNonNull(mAppMenuDragHelper);
         mAppMenuDragHelper.onShow(startDragging);
         clearMenuHighlight();
         RecordUserAction.record("MobileMenuShow");
         mDelegate.onMenuShown();
     }
+
+    private boolean addTopPaddingBeforeFirstRow() {
+        if (mModelList == null || mModelList.isEmpty()) return false;
+        return mModelList.get(0).type != AppMenuItemType.BUTTON_ROW;
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
index b58dc7e7..8449f13 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
@@ -16,7 +16,6 @@
 import androidx.appcompat.widget.AppCompatImageView;
 
 import org.chromium.build.annotations.CheckDiscard;
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
@@ -32,7 +31,6 @@
  *
  * @param <T> The type of View being wrapped by this container.
  */
-@MockedInTests
 @NullMarked
 public class BaseSuggestionView<T extends View> extends SuggestionLayout {
     public final ImageView decorationIcon;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecoration.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecoration.java
index 0c4ac14..c9107e69 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecoration.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecoration.java
@@ -7,7 +7,6 @@
 import androidx.annotation.Px;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 
 /**
@@ -19,7 +18,6 @@
  *
  * <p>Note: currently dynamic spacing is activated in portrait mode only.
  */
-@MockedInTests
 @NullMarked
 public class DynamicSpacingRecyclerViewItemDecoration extends SpacingRecyclerViewItemDecoration {
     private final @Px int mMinElementSpace;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
index 1fd4a657..61d4658 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
@@ -13,7 +13,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.build.annotations.CheckDiscard;
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.suggestions.RecyclerViewSelectionController;
@@ -22,7 +21,6 @@
 import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
 
 /** View for Carousel Suggestions. */
-@MockedInTests
 @NullMarked
 public class BaseCarouselSuggestionView extends RecyclerView {
     private RecyclerViewSelectionController mSelectionController;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
index a2e61a0..3c1fc6f 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
@@ -25,7 +25,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
@@ -47,7 +46,6 @@
 import java.util.List;
 
 /** Class containing functionality related to voice search. */
-@MockedInTests
 @NullMarked
 public class VoiceRecognitionHandler {
     private static final String TAG = "VoiceRecognition";
diff --git a/chrome/browser/ui/android/signin/java/res/layout/signout_button_view.xml b/chrome/browser/ui/android/signin/java/res/layout/signout_button_view.xml
index 64da1fa..a3018fe5 100644
--- a/chrome/browser/ui/android/signin/java/res/layout/signout_button_view.xml
+++ b/chrome/browser/ui/android/signin/java/res/layout/signout_button_view.xml
@@ -11,7 +11,8 @@
     style="@style/PreferenceLayout"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="8dp">
+    android:layout_marginBottom="8dp"
+    android:descendantFocusability="afterDescendants">
 
     <org.chromium.ui.widget.ButtonCompat
         android:id="@+id/sign_out_button"
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index c25a305..e44859e 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4174,6 +4174,9 @@
       <message name="IDS_BUTTON_NEW_TAB" desc="Button name for opening a new tab.">
         New tab
       </message>
+      <message name="IDS_BUTTON_NEW_TAB_GROUP" desc="Button name for opening a new tab group.">
+        New tab group
+      </message>
       <message name="IDS_BUTTON_NEW_INCOGNITO_TAB" desc="Tooltip for the button to open a new Incognito browser tab.">
         New Incognito tab
       </message>
@@ -5585,6 +5588,15 @@
       <message name="IDS_KEYBOARD_SHORTCUT_HISTORY_MANAGER" desc="A text label that appears next to the keyboard shorcut that will open up the history page. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR_LIMIT=55]">
         Open the history page
       </message>
+      <message name="IDS_KEYBOARD_SHORTCUT_HISTORY_GO_BACK" desc="A text label that appears next to the keyboard shorcut that will go to the previous page in your browser History. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR_LIMIT=55]">
+        Go to the previous page in History
+      </message>
+      <message name="IDS_KEYBOARD_SHORTCUT_HISTORY_GO_FORWARD" desc="A text label that appears next to the keyboard shorcut that will go to the next page in your browser History. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR_LIMIT=55]">
+        Go to the next page in History
+      </message>
+      <message name="IDS_KEYBOARD_SHORTCUT_SAVE_PAGE" desc="A text label that appears next to the keyboard shortcut that will save the page. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR_LIMIT=55]">
+        Open options to save page
+      </message>
       <message name="IDS_KEYBOARD_SHORTCUT_PRINT_PAGE" desc="A text label that appears next to the keyboard shortcut that will open the print page. The shortcut description is shown in a system dialog along with all other supported shortcuts. [CHAR_LIMIT=55]">
         Open options to print page
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_BUTTON_NEW_TAB_GROUP.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_BUTTON_NEW_TAB_GROUP.png.sha1
new file mode 100644
index 0000000..716d35a
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_BUTTON_NEW_TAB_GROUP.png.sha1
@@ -0,0 +1 @@
+5dee7f4aeef690ab608bce4f5a3adec80ccf07fa
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_BACK.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_BACK.png.sha1
new file mode 100644
index 0000000..123ddb73
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_BACK.png.sha1
@@ -0,0 +1 @@
+9da68aa340606478b2fe99168eda5b7966d0bca4
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_FORWARD.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_FORWARD.png.sha1
new file mode 100644
index 0000000..123ddb73
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_HISTORY_GO_FORWARD.png.sha1
@@ -0,0 +1 @@
+9da68aa340606478b2fe99168eda5b7966d0bca4
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_SAVE_PAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_SAVE_PAGE.png.sha1
new file mode 100644
index 0000000..123ddb73
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_KEYBOARD_SHORTCUT_SAVE_PAGE.png.sha1
@@ -0,0 +1 @@
+9da68aa340606478b2fe99168eda5b7966d0bca4
\ No newline at end of file
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer.cc b/chrome/browser/ui/android/tab_model/tab_model_observer.cc
index 14a2ff98..9e203f8 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_observer.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model_observer.cc
@@ -16,7 +16,7 @@
 
 void TabModelObserver::WillCloseTab(TabAndroid* tab) {}
 
-void TabModelObserver::OnFinishingTabClosure(int tab_id, bool incognito) {}
+void TabModelObserver::OnFinishingTabClosure(TabAndroid* tab) {}
 
 void TabModelObserver::OnFinishingMultipleTabClosure(
     const std::vector<raw_ptr<TabAndroid, VectorExperimental>>& tabs,
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer.h b/chrome/browser/ui/android/tab_model/tab_model_observer.h
index 365cc00..0afc1356 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_observer.h
+++ b/chrome/browser/ui/android/tab_model/tab_model_observer.h
@@ -31,7 +31,7 @@
   virtual void WillCloseTab(TabAndroid* tab);
 
   // Called right before a |tab| has been destroyed.
-  virtual void OnFinishingTabClosure(int tab_id, bool incognito);
+  virtual void OnFinishingTabClosure(TabAndroid* tab);
 
   // Called right before all |tabs| are destroyed.
   virtual void OnFinishingMultipleTabClosure(
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc
index d1140f3..f9a6a47 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc
@@ -75,10 +75,11 @@
 void TabModelObserverJniBridge::OnFinishingTabClosure(
     JNIEnv* env,
     const JavaParamRef<jobject>& jobj,
-    int tab_id,
-    bool incognito) {
+    const JavaParamRef<jobject>& jtab) {
+  TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
+  CHECK(tab);
   for (auto& observer : observers_) {
-    observer.OnFinishingTabClosure(tab_id, incognito);
+    observer.OnFinishingTabClosure(tab);
   }
 }
 
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h
index dfd29546..c494f5d9 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h
+++ b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h
@@ -42,8 +42,7 @@
 
   void OnFinishingTabClosure(JNIEnv* env,
                              const base::android::JavaParamRef<jobject>& jobj,
-                             int tab_id,
-                             bool incognito);
+                             const base::android::JavaParamRef<jobject>& jtab);
 
   void OnFinishingMultipleTabClosure(
       JNIEnv* env,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java
index 03dd02a..855b981 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java
@@ -7,20 +7,20 @@
 import android.os.Handler;
 import android.os.Looper;
 
-import androidx.annotation.NonNull;
-
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
 
 /**
- * Watches a constraints supplier for the next time the browser controls are unlocked,
- * and then tells the {@link ViewResourceAdapter} to generate a resource.
+ * Watches a constraints supplier for the next time the browser controls are unlocked, and then
+ * tells the {@link ViewResourceAdapter} to generate a resource.
  */
+@NullMarked
 public class ConstraintsChecker implements Callback<Integer> {
-    @NonNull private final ViewResourceAdapter mViewResourceAdapter;
-    @NonNull private final ObservableSupplier<Integer> mConstraintsSupplier;
-    @NonNull private final Handler mHandler;
+    private final ViewResourceAdapter mViewResourceAdapter;
+    private final ObservableSupplier<Integer> mConstraintsSupplier;
+    private final Handler mHandler;
 
     /**
      * @param viewResourceAdapter The target to notify when a capture is needed.
@@ -28,9 +28,9 @@
      * @param looper Message loop to post deferred tasks to.
      */
     public ConstraintsChecker(
-            @NonNull ViewResourceAdapter viewResourceAdapter,
-            @NonNull ObservableSupplier<Integer> constraintsSupplier,
-            @NonNull Looper looper) {
+            ViewResourceAdapter viewResourceAdapter,
+            ObservableSupplier<Integer> constraintsSupplier,
+            Looper looper) {
         mViewResourceAdapter = viewResourceAdapter;
         mConstraintsSupplier = constraintsSupplier;
         mHandler = new Handler(looper);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ControlContainer.java
index efa382e..5712359 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ControlContainer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ControlContainer.java
@@ -9,18 +9,21 @@
 
 import androidx.coordinatorlayout.widget.CoordinatorLayout;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.SwipeHandler;
 import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
 
 /**
  * Interface that defines the responsibilities of the layout container for the browser controls.
- * <p>
- * Concrete implementations of this class must extend ViewGroup.
+ *
+ * <p>Concrete implementations of this class must extend ViewGroup.
  */
+@NullMarked
 public interface ControlContainer {
     /**
      * Initialize the control container with the specified toolbar.
+     *
      * @param toolbarLayoutId The ID of the toolbar layout to use.
      */
     void initWithToolbar(int toolbarLayoutId);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/FormFieldFocusedSupplier.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/FormFieldFocusedSupplier.java
index fff11038..1c9f090 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/FormFieldFocusedSupplier.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/FormFieldFocusedSupplier.java
@@ -4,9 +4,9 @@
 
 package org.chromium.chrome.browser.toolbar;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.content_public.browser.ImeAdapter;
 import org.chromium.content_public.browser.ImeEventObserver;
 import org.chromium.content_public.browser.WebContents;
@@ -16,9 +16,10 @@
  * WebContents. Changes to the WebContents considered active must be reflected with calls to
  * onWebContentsChanged; this class does not attempt to track these changes.
  */
+@NullMarked
 class FormFieldFocusedSupplier extends ObservableSupplierImpl<Boolean> implements ImeEventObserver {
-    private WebContents mWebContents;
-    private ImeAdapter mImeAdapter;
+    private @Nullable WebContents mWebContents;
+    private @Nullable ImeAdapter mImeAdapter;
 
     public FormFieldFocusedSupplier() {
         super(false);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
index 989a00f9..b9108e5 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
@@ -9,6 +9,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.components.browser_ui.widget.scrim.ScrimManager;
@@ -18,6 +19,7 @@
 import org.chromium.ui.util.ColorUtils;
 
 /** Handles showing and hiding a scrim when url bar focus changes. */
+@NullMarked
 public class LocationBarFocusScrimHandler implements UrlFocusChangeListener {
     /** The params used to control how the scrim behaves when shown for the omnibox. */
     private PropertyModel mScrimModel;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
index d6d2d02..f7d21e3 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -12,8 +14,6 @@
 import androidx.annotation.ColorInt;
 import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
 
@@ -22,6 +22,9 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.base.TraceEvent;
+import org.chromium.build.annotations.EnsuresNonNullIf;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
 import org.chromium.chrome.browser.omnibox.NewTabPageDelegate;
@@ -52,12 +55,13 @@
 import java.util.Objects;
 
 /** Provides a way of accessing toolbar data and state. */
+@NullMarked
 public class LocationBarModel implements ToolbarDataProvider, LocationBarDataProvider {
     private static final int LRU_CACHE_SIZE = 10;
 
     static class SpannableDisplayTextCacheKey {
-        @NonNull private final String mUrl;
-        @NonNull private final String mDisplayText;
+        private final String mUrl;
+        private final String mDisplayText;
         private final int mSecurityLevel;
         private final int mNonEmphasizedColor;
         private final int mEmphasizedColor;
@@ -65,8 +69,8 @@
         private final int mSecureColor;
 
         private SpannableDisplayTextCacheKey(
-                @NonNull String url,
-                @NonNull String displayText,
+                String url,
+                String displayText,
                 int securityLevel,
                 int nonEmphasizedColor,
                 int emphasizedColor,
@@ -133,20 +137,19 @@
 
     private final Context mContext;
     private final NewTabPageDelegate mNtpDelegate;
-    private final @NonNull UrlFormatter mUrlFormatter;
-    private final @NonNull OfflineStatus mOfflineStatus;
+    private final UrlFormatter mUrlFormatter;
+    private final OfflineStatus mOfflineStatus;
     // Always null if optimizations are disabled. Otherwise, non-null and unchanging following
     // native init. Always tied to the original profile which is safe because no underlying
     // services have an incognito-specific instance.
-    @Nullable private AutocompleteSchemeClassifier mChromeAutocompleteSchemeClassifier;
-    @Nullable private Profile mProfile;
+    private @Nullable AutocompleteSchemeClassifier mChromeAutocompleteSchemeClassifier;
+    private @Nullable Profile mProfile;
     private boolean mInitializedProfileDependentFeatures;
 
-    @Nullable
-    private LruCache<SpannableDisplayTextCacheKey, SpannableStringBuilder>
+    private @Nullable LruCache<SpannableDisplayTextCacheKey, SpannableStringBuilder>
             mSpannableDisplayTextCache;
 
-    private Tab mTab;
+    private @Nullable Tab mTab;
     private int mPrimaryColor;
 
     private boolean mIsIncognitoBranded;
@@ -182,8 +185,8 @@
     public LocationBarModel(
             Context context,
             NewTabPageDelegate newTabPageDelegate,
-            @NonNull UrlFormatter urlFormatter,
-            @NonNull OfflineStatus offlineStatus) {
+            UrlFormatter urlFormatter,
+            OfflineStatus offlineStatus) {
         mContext = context;
         mNtpDelegate = newTabPageDelegate;
         mUrlFormatter = urlFormatter;
@@ -204,12 +207,14 @@
         assert mProfile != null;
         mInitializedProfileDependentFeatures = true;
 
+        assumeNonNull(getProfile());
         mChromeAutocompleteSchemeClassifier =
                 new ChromeAutocompleteSchemeClassifier(getProfile().getOriginalProfile());
         recalculateFormattedUrls();
     }
 
     /** Destroys the native LocationBarModel. */
+    @SuppressWarnings("NullAway")
     public void destroy() {
         if (mChromeAutocompleteSchemeClassifier != null) {
             mChromeAutocompleteSchemeClassifier.destroy();
@@ -224,7 +229,7 @@
      * @return The currently active WebContents being used by the Toolbar.
      */
     @CalledByNative
-    private WebContents getActiveWebContents() {
+    private @Nullable WebContents getActiveWebContents() {
         if (!hasTab()) return null;
         return mTab.getWebContents();
     }
@@ -236,7 +241,7 @@
      * @param profile The profile associated with the currently selected model, which must match the
      *     passed in tab if non-null.
      */
-    public void setTab(@Nullable Tab tab, @NonNull Profile profile) {
+    public void setTab(@Nullable Tab tab, Profile profile) {
         assert tab == null || tab.getProfile() == profile;
         assert profile != null;
 
@@ -261,11 +266,12 @@
     }
 
     @Override
-    public Tab getTab() {
+    public @Nullable Tab getTab() {
         return hasTab() ? mTab : null;
     }
 
     @Override
+    @EnsuresNonNullIf("mTab")
     public boolean hasTab() {
         // TODO(crbug.com/40730536): Remove the isInitialized() and isDestroyed checks when
         // we no longer wait for TAB_CLOSED events to remove this tab.  Otherwise there is a chance
@@ -447,10 +453,12 @@
                         emphasizedColor,
                         dangerColor,
                         secureColor);
+        assumeNonNull(mSpannableDisplayTextCache);
         SpannableStringBuilder cachedSpannableDisplayText =
                 mSpannableDisplayTextCache.get(cacheKey);
 
         if (cachedSpannableDisplayText == null) {
+            assumeNonNull(mChromeAutocompleteSchemeClassifier);
             cachedSpannableDisplayText = new SpannableStringBuilder(displayText);
             OmniboxUrlEmphasizer.emphasizeUrl(
                     cachedSpannableDisplayText,
@@ -478,7 +486,7 @@
         return TrustedCdn.getPublisherUrl(mTab) == null;
     }
 
-    LruCache<SpannableDisplayTextCacheKey, SpannableStringBuilder> getCacheForTesting() {
+    @Nullable LruCache<SpannableDisplayTextCacheKey, SpannableStringBuilder> getCacheForTesting() {
         return mSpannableDisplayTextCache;
     }
 
@@ -492,9 +500,10 @@
 
     @Override
     public String getTitle() {
-        if (!hasTab()) return "";
+        Tab tab = getTab();
+        if (tab == null) return "";
 
-        String title = getTab().getTitle();
+        String title = tab.getTitle();
         return TextUtils.isEmpty(title) ? title : title.trim();
     }
 
@@ -530,7 +539,7 @@
     }
 
     @Override
-    public Profile getProfile() {
+    public @Nullable Profile getProfile() {
         return mProfile;
     }
 
@@ -571,11 +580,13 @@
     }
 
     @Override
+    @EnsuresNonNullIf("mTab")
     public boolean isOfflinePage() {
         return hasTab() && mOfflineStatus.isOfflinePage(mTab);
     }
 
     @Override
+    @EnsuresNonNullIf("mTab")
     public boolean isPaintPreview() {
         return hasTab() && TabbedPaintPreview.get(mTab).isShowing();
     }
@@ -618,7 +629,7 @@
 
     @VisibleForTesting
     @ConnectionSecurityLevel
-    int getSecurityLevel(Tab tab, boolean isOfflinePage) {
+    int getSecurityLevel(@Nullable Tab tab, boolean isOfflinePage) {
         if (tab == null || isOfflinePage) {
             return ConnectionSecurityLevel.NONE;
         }
@@ -637,7 +648,7 @@
 
     @VisibleForTesting
     @ConnectionSecurityLevel
-    int getSecurityLevelFromStateModel(WebContents webContents) {
+    int getSecurityLevelFromStateModel(@Nullable WebContents webContents) {
         int securityLevel = SecurityStateModel.getSecurityLevelForWebContents(webContents);
         return securityLevel;
     }
@@ -779,6 +790,7 @@
                 .getURLForDisplay(mNativeLocationBarModelAndroid, LocationBarModel.this);
     }
 
+    @SuppressWarnings("NullAway")
     protected GURL getUrlOfVisibleNavigationEntry() {
         if (mNativeLocationBarModelAndroid == 0) return GURL.emptyGURL();
         if (mNtpDelegate.isCurrentlyVisible()) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MenuBuilderHelper.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MenuBuilderHelper.java
index feb40fe..90e1991 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MenuBuilderHelper.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MenuBuilderHelper.java
@@ -6,10 +6,12 @@
 
 import android.view.View;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.widget.RectProvider;
 import org.chromium.ui.widget.ViewRectProvider;
 
 /** A helper class for sharing common code for building a list menu button. */
+@NullMarked
 public class MenuBuilderHelper {
     public static RectProvider getRectProvider(View anchorView) {
         ViewRectProvider rectProvider = new ViewRectProvider(anchorView);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ProgressAnimationSmooth.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ProgressAnimationSmooth.java
index d77a4b8..37c3d41 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ProgressAnimationSmooth.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ProgressAnimationSmooth.java
@@ -4,11 +4,14 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import org.chromium.build.annotations.NullMarked;
+
 /**
  * Progress bar animation logic that smoothly accelerates in the beginning and smoothly decelerates
  * towards the end. The model is applying a constant acceleration followed by a constant
  * deceleration.
  */
+@NullMarked
 class ProgressAnimationSmooth implements ToolbarProgressBar.AnimationLogic {
     // The (de)acceleration unit is progress per second squared where 0 <= progress <= 1.
     private static final float FINISHING_ACCELERATION = 7.0f;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/SettableThemeColorProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/SettableThemeColorProvider.java
index 8f4a5ea..03ebea21 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/SettableThemeColorProvider.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/SettableThemeColorProvider.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.theme.ThemeColorProvider;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 
@@ -15,6 +16,7 @@
  * tracking logic; to function properly, setPrimaryColor must be called each time the color changes.
  */
 @Deprecated
+@NullMarked
 class SettableThemeColorProvider extends ThemeColorProvider {
     /**
      * @param context The {@link Context} that is used to retrieve color related resources.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
index 5f10273..7b82415 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
@@ -9,6 +9,8 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.theme.ThemeColorProvider;
 import org.chromium.chrome.browser.theme.ThemeColorProvider.TintObserver;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
@@ -19,24 +21,26 @@
  * The controller for the tab switcher button. This class handles all interactions that the tab
  * switcher button has with the outside world.
  */
+@NullMarked
 public class TabSwitcherButtonCoordinator {
     /**
-     *  The model that handles events from outside the tab switcher button. Normally the coordinator
-     *  should acces the mediator which then updates the model. Since this component is very simple
-     *  the mediator is omitted.
+     * The model that handles events from outside the tab switcher button. Normally the coordinator
+     * should acces the mediator which then updates the model. Since this component is very simple
+     * the mediator is omitted.
      */
     private final PropertyModel mTabSwitcherButtonModel =
             new PropertyModel(TabSwitcherButtonProperties.ALL_KEYS);
 
     private final Callback<Integer> mTabCountObserver;
 
-    private ThemeColorProvider mThemeColorProvider;
-    private TintObserver mTintObserver;
+    private @Nullable ThemeColorProvider mThemeColorProvider;
+    private @Nullable TintObserver mTintObserver;
 
-    private ObservableSupplier<Integer> mTabCountSupplier;
+    private @Nullable ObservableSupplier<Integer> mTabCountSupplier;
 
     /**
      * Build the controller that manages the tab switcher button.
+     *
      * @param view The {@link TabSwitcherButtonView} the controller manages.
      */
     public TabSwitcherButtonCoordinator(TabSwitcherButtonView view) {
@@ -63,8 +67,8 @@
                 new TintObserver() {
                     @Override
                     public void onTintChanged(
-                            ColorStateList tint,
-                            ColorStateList activityFocusTint,
+                            @Nullable ColorStateList tint,
+                            @Nullable ColorStateList activityFocusTint,
                             @BrandedColorScheme int brandedColorScheme) {
                         mTabSwitcherButtonModel.set(TabSwitcherButtonProperties.TINT, tint);
                     }
@@ -80,6 +84,7 @@
         mTabCountSupplier.addObserver(mTabCountObserver);
     }
 
+    @SuppressWarnings("NullAway")
     public void destroy() {
         if (mThemeColorProvider != null) {
             mThemeColorProvider.removeTintObserver(mTintObserver);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java
index b4b7d2c..a12f5fc 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java
@@ -8,12 +8,14 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnLongClickListener;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 /** The properties needed to render the tab switcher button. */
+@NullMarked
 public interface TabSwitcherButtonProperties {
     /** The current number of tabs. */
     public static final WritableIntPropertyKey NUMBER_OF_TABS = new WritableIntPropertyKey();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
index c11344d..cc33413 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
@@ -8,6 +8,7 @@
 import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable.TabSwitcherDrawableLocation;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 import org.chromium.ui.listmenu.ListMenuButton;
@@ -16,6 +17,7 @@
  * The Button used for switching tabs. Currently this class is only being used for the bottom
  * toolbar tab switcher button.
  */
+@NullMarked
 public class TabSwitcherButtonView extends ListMenuButton {
     /** A drawable for the tab switcher icon. */
     private TabSwitcherDrawable mTabSwitcherButtonDrawable;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java
index 90c6d4b..bd7fc67 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
@@ -13,6 +14,7 @@
  * updates are pulled from the {@link TabSwitcherModel} when a notification of an update is
  * received.
  */
+@NullMarked
 public class TabSwitcherButtonViewBinder
         implements PropertyModelChangeProcessor.ViewBinder<
                 PropertyModel, TabSwitcherButtonView, PropertyKey> {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
index 35c2bd1..3a278a2 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
@@ -21,6 +21,8 @@
 import androidx.annotation.IntDef;
 
 import org.chromium.base.ObserverList;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.theme.ThemeUtils;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
@@ -31,6 +33,7 @@
 import java.util.Locale;
 
 /** A drawable for the tab switcher icon. */
+@NullMarked
 public class TabSwitcherDrawable extends TintedDrawable {
     @IntDef({
         TabSwitcherDrawableLocation.TAB_TOOLBAR,
@@ -63,7 +66,7 @@
     // Tab Count Label
     private int mTabCount;
     private boolean mIncognito;
-    private String mTextRenderedForTesting;
+    private @Nullable String mTextRenderedForTesting;
     private Canvas mIconCanvas;
     private Bitmap mIconBitmap;
     private boolean mShouldShowNotificationIcon;
@@ -280,7 +283,7 @@
                 && mTabSwitcherDrawableLocation == TabSwitcherDrawableLocation.TAB_TOOLBAR);
     }
 
-    public String getTextRenderedForTesting() {
+    public @Nullable String getTextRenderedForTesting() {
         return mTextRenderedForTesting;
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarCaptureType.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarCaptureType.java
index 00664f8..ce5ddfb 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarCaptureType.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarCaptureType.java
@@ -6,6 +6,8 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -20,6 +22,7 @@
     ToolbarCaptureType.NUM_ENTRIES
 })
 @Retention(RetentionPolicy.SOURCE)
+@NullMarked
 public @interface ToolbarCaptureType {
     int UNKNOWN = 0;
     int TOP = 1;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
index a787fe0..f3cf95b8 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
@@ -6,9 +6,9 @@
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.NewTabPageDelegate;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -16,6 +16,7 @@
 import org.chromium.url.GURL;
 
 /** Defines the data that is exposed to properly render the Toolbar. */
+@NullMarked
 public interface ToolbarDataProvider {
     /** Observer interface for consumers who wish to subscribe to updates of ToolbarData. */
     interface Observer {
@@ -31,22 +32,18 @@
     /**
      * @return The tab that contains the information currently displayed in the toolbar.
      */
-    @Nullable
-    Tab getTab();
+    @Nullable Tab getTab();
 
     /** Returns The url of the current tab. Returns empty string when there is no tab. */
-    @NonNull
     String getCurrentUrl();
 
     /**
      * Returns The url of the current tab, represented as a GURL. Returns an empty GURL when there
      * is no tab.
      */
-    @NonNull
     GURL getCurrentGurl();
 
     /** Returns the delegate for the NewTabPage shown for the current tab. */
-    @NonNull
     NewTabPageDelegate getNewTabPageDelegate();
 
     /**
@@ -75,7 +72,7 @@
     /**
      * @return The current {@link Profile}.
      */
-    Profile getProfile();
+    @Nullable Profile getProfile();
 
     /**
      * @return The contents of the {@link org.chromium.chrome.browser.omnibox.UrlBar}.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java
index 8efaede..1994477 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java
@@ -9,12 +9,15 @@
 
 import org.chromium.base.DeviceInfo;
 import org.chromium.base.ResettersForTesting;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 
 /** Utility class for toolbar code interacting with features and params. */
+@NullMarked
 public final class ToolbarFeatures {
 
-    private static Boolean sTabStripLayoutOptimizationEnabledForTesting;
+    private static @Nullable Boolean sTabStripLayoutOptimizationEnabledForTesting;
 
     /** Private constructor to avoid instantiation. */
     private ToolbarFeatures() {}
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarIntentMetadata.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarIntentMetadata.java
index 7661286..8ff01b5 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarIntentMetadata.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarIntentMetadata.java
@@ -4,7 +4,10 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import org.chromium.build.annotations.NullMarked;
+
 /** Simple collection of information about the original intent. */
+@NullMarked
 public class ToolbarIntentMetadata {
     private final boolean mIsMainIntentFromLauncher;
     private final boolean mIsIntentWithEffect;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
index c8eb81d..9dd19ce 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Color;
@@ -17,12 +19,12 @@
 import android.widget.PopupWindow;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.shared_preferences.SharedPreferencesManager;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
@@ -48,6 +50,7 @@
 import java.util.function.Supplier;
 
 /** The handler for the toolbar long press menu. */
+@NullMarked
 public class ToolbarLongPressMenuHandler implements ConfigurationChangedObserver {
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({MenuItemType.MOVE_ADDRESS_BAR_TO, MenuItemType.COPY_LINK})
@@ -56,22 +59,22 @@
         int COPY_LINK = 1;
     }
 
-    private PopupWindow mPopupMenu;
+    private @Nullable PopupWindow mPopupMenu;
     private final int mAppMenuShadowLength;
     private final int mAdditonalHorizontalPadding;
     private final int mEdgeToTextDistance;
     private final int mUrlBarMargin;
     private final int mMenuOmniboxOverlap;
     private int mScreenWidthDp;
-    @NonNull private final Context mContext;
-    @NonNull private final ObservableSupplier<Profile> mProfileSupplier;
-    @NonNull private final ObservableSupplier<Boolean> mOmniboxFocusStateSupplier;
-    @NonNull private final Supplier<String> mUrlBarTextSupplier;
-    @NonNull private final Supplier<ViewRectProvider> mUrlBarViewRectProviderSupplier;
-    @Nullable private final OnLongClickListener mOnLongClickListener;
-    @NonNull private final SharedPreferencesManager mSharedPreferencesManager;
-    @NonNull private final WindowAndroid mWindowAndroid;
-    @NonNull private final ActivityLifecycleDispatcher mLifecycleDispatcher;
+    private final Context mContext;
+    private final ObservableSupplier<Profile> mProfileSupplier;
+    private final ObservableSupplier<Boolean> mOmniboxFocusStateSupplier;
+    private final Supplier<String> mUrlBarTextSupplier;
+    private final Supplier<ViewRectProvider> mUrlBarViewRectProviderSupplier;
+    private final @Nullable OnLongClickListener mOnLongClickListener;
+    private final SharedPreferencesManager mSharedPreferencesManager;
+    private final WindowAndroid mWindowAndroid;
+    private final ActivityLifecycleDispatcher mLifecycleDispatcher;
 
     /**
      * Creates a new {@link ToolbarLongPressMenuHandler}.
@@ -168,6 +171,7 @@
                         buildMenuItems(onTop),
                         (model) -> {
                             handleMenuClick(model.get(ListMenuItemProperties.MENU_ITEM_ID));
+                            assumeNonNull(mPopupMenu);
                             mPopupMenu.dismiss();
                         });
 
@@ -268,7 +272,7 @@
         return new int[] {x, y};
     }
 
-    public PopupWindow getPopupWindowForTesting() {
+    public @Nullable PopupWindow getPopupWindowForTesting() {
         return mPopupMenu;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java
index 14a11d3..b59c4f3 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java
@@ -11,8 +11,6 @@
 import android.widget.FrameLayout;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.coordinatorlayout.widget.CoordinatorLayout;
 import androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams;
@@ -21,6 +19,8 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BottomControlsLayer;
 import org.chromium.chrome.browser.browser_controls.BottomControlsStacker;
 import org.chromium.chrome.browser.browser_controls.BottomControlsStacker.LayerScrollBehavior;
@@ -40,6 +40,7 @@
 import java.lang.annotation.RetentionPolicy;
 
 /** Class responsible for managing the position (top, bottom) of the browsing mode toolbar. */
+@NullMarked
 public class ToolbarPositionController implements OnSharedPreferenceChangeListener {
 
     @IntDef({
@@ -66,20 +67,20 @@
     // User-configured, or, otherwise, default Toolbar placement; may be null, if target placement
     // has not been determined yet. Prefer `isToolbarConfiguredToShowOnTop()` call when querying
     // intended placement.
-    private static Boolean sToolbarShouldShowOnTop;
+    private static @Nullable Boolean sToolbarShouldShowOnTop;
 
     private final BrowserControlsSizer mBrowserControlsSizer;
     private final ObservableSupplier<Boolean> mIsNtpShowingSupplier;
     private final ObservableSupplier<Boolean> mIsTabSwitcherFinishedShowingSupplier;
     private final ObservableSupplier<Boolean> mIsOmniboxFocusedSupplier;
     private final ObservableSupplier<Boolean> mIsFormFieldFocusedSupplier;
-    @NonNull private final ObservableSupplier<Boolean> mIsFindInPageShowingSupplier;
+    private final ObservableSupplier<Boolean> mIsFindInPageShowingSupplier;
     private final ControlContainer mControlContainer;
     private final BottomControlsStacker mBottomControlsStacker;
     private final ObservableSupplierImpl<Integer> mBrowserControlsOffsetSupplier;
-    @NonNull private final View mToolbarProgressBarContainer;
-    @NonNull private final KeyboardVisibilityDelegate mKeyboardVisibilityDelegate;
-    @NonNull private final Context mContext;
+    private final View mToolbarProgressBarContainer;
+    private final KeyboardVisibilityDelegate mKeyboardVisibilityDelegate;
+    private final Context mContext;
     @LayerVisibility private int mLayerVisibility;
     private final BottomControlsLayer mBottomToolbarLayer;
     private final BottomControlsLayer mProgressBarLayer;
@@ -106,19 +107,19 @@
      *     the bottom toolbar with other bottom-anchored UI.
      */
     public ToolbarPositionController(
-            @NonNull BrowserControlsSizer browserControlsSizer,
-            @NonNull SharedPreferences sharedPreferences,
-            @NonNull ObservableSupplier<Boolean> isNtpShowingSupplier,
-            @NonNull ObservableSupplier<Boolean> isTabSwitcherFinishedShowingSupplier,
-            @NonNull ObservableSupplier<Boolean> isOmniboxFocusedSupplier,
-            @NonNull ObservableSupplier<Boolean> isFormFieldFocusedSupplier,
-            @NonNull ObservableSupplier<Boolean> isFindInPageShowingSupplier,
-            @NonNull KeyboardVisibilityDelegate keyboardVisibilityDelegate,
-            @NonNull ControlContainer controlContainer,
-            @NonNull BottomControlsStacker bottomControlsStacker,
-            @NonNull ObservableSupplierImpl<Integer> browserControlsOffsetSupplier,
-            @NonNull View toolbarProgressBarContainer,
-            @NonNull Context context) {
+            BrowserControlsSizer browserControlsSizer,
+            SharedPreferences sharedPreferences,
+            ObservableSupplier<Boolean> isNtpShowingSupplier,
+            ObservableSupplier<Boolean> isTabSwitcherFinishedShowingSupplier,
+            ObservableSupplier<Boolean> isOmniboxFocusedSupplier,
+            ObservableSupplier<Boolean> isFormFieldFocusedSupplier,
+            ObservableSupplier<Boolean> isFindInPageShowingSupplier,
+            KeyboardVisibilityDelegate keyboardVisibilityDelegate,
+            ControlContainer controlContainer,
+            BottomControlsStacker bottomControlsStacker,
+            ObservableSupplierImpl<Integer> browserControlsOffsetSupplier,
+            View toolbarProgressBarContainer,
+            Context context) {
         mBrowserControlsSizer = browserControlsSizer;
         mIsNtpShowingSupplier = isNtpShowingSupplier;
         mIsTabSwitcherFinishedShowingSupplier = isTabSwitcherFinishedShowingSupplier;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBar.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBar.java
index e7c8c6db..3089815 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBar.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBar.java
@@ -17,11 +17,12 @@
 import android.view.animation.Interpolator;
 import android.widget.ProgressBar;
 
-import androidx.annotation.Nullable;
 import androidx.core.view.ViewCompat;
 
 import org.chromium.base.MathUtils;
 import org.chromium.base.ThreadUtils;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.theme.ThemeUtils;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
@@ -34,6 +35,7 @@
  * indeterminate animation will begin playing and the animation will move across the screen smoothly
  * instead of jumping.
  */
+@NullMarked
 public class ToolbarProgressBar extends ClipDrawableProgressBar
         implements BrowserControlsStateProvider.Observer {
     /** Interface for progress bar animation interpolation logics. */
@@ -86,13 +88,13 @@
     private int mThemeColor;
 
     /** The indeterminate animating view for the progress bar. */
-    private ToolbarProgressBarAnimatingView mAnimatingView;
+    private @Nullable ToolbarProgressBarAnimatingView mAnimatingView;
 
     /** The progress bar's height. */
     private final int mProgressBarHeight;
 
     /** The current running animator that controls the fade in/out of the progress bar. */
-    @Nullable private Animator mFadeAnimator;
+    private @Nullable Animator mFadeAnimator;
 
     private final Runnable mStartSmoothIndeterminate =
             new Runnable() {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarAnimatingView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarAnimatingView.java
index 80ca6ec..53585c59f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarAnimatingView.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarAnimatingView.java
@@ -17,6 +17,8 @@
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.interpolators.Interpolators;
 
@@ -24,6 +26,7 @@
  * An animating ImageView that is drawn on top of the progress bar. This will animate over the
  * current length of the progress bar only if the progress bar is static for some amount of time.
  */
+@NullMarked
 public class ToolbarProgressBarAnimatingView extends ImageView {
     /** The drawable inside this ImageView. */
     private final ColorDrawable mAnimationDrawable;
@@ -82,7 +85,7 @@
     private float mLastAnimatedFraction;
 
     /** The last animation that received an update. */
-    private ValueAnimator mLastUpdatedAnimation;
+    private @Nullable ValueAnimator mLastUpdatedAnimation;
 
     /** The ratio of px to dp. */
     private final float mDpToPx;
@@ -181,10 +184,11 @@
 
     /**
      * Update the animating view.
+     *
      * @param animator The current running animator.
      * @param animatedFraction The current fraction of completion for the animation.
      */
-    private void updateAnimation(ValueAnimator animator, float animatedFraction) {
+    private void updateAnimation(@Nullable ValueAnimator animator, float animatedFraction) {
         if (mIsCanceled) return;
         float interpolatorProgress = mInterpolator.getInterpolation(animatedFraction);
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabController.java
index 6f26244..14e6e0c 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabController.java
@@ -4,7 +4,10 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import org.chromium.build.annotations.NullMarked;
+
 /** Handles toolbar triggered actions on the specific tab. */
+@NullMarked
 public interface ToolbarTabController {
     /**
      * If the page is currently loading, this will trigger the tab to stop. If the page is fully
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java
index 86567b4..3d96e203 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImpl.java
@@ -4,12 +4,13 @@
 
 package org.chromium.chrome.browser.toolbar;
 
-import androidx.annotation.NonNull;
+import static org.chromium.build.NullUtil.assumeNonNull;
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -27,6 +28,7 @@
 import org.chromium.ui.base.PageTransition;
 
 /** Implementation of {@link ToolbarTabController}. */
+@NullMarked
 public class ToolbarTabControllerImpl implements ToolbarTabController {
     private final Supplier<Tab> mTabSupplier;
     private final Supplier<Tracker> mTrackerSupplier;
@@ -34,7 +36,7 @@
     private final Supplier<String> mHomepageUrlSupplier;
     private final Runnable mOnSuccessRunnable;
     private final Supplier<Tab> mActivityTabSupplier;
-    private final @NonNull TabCreatorManager mTabCreatorManager;
+    private final TabCreatorManager mTabCreatorManager;
     private final @Nullable MultiInstanceManager mMultiInstanceManager;
 
     /**
@@ -57,7 +59,7 @@
             Supplier<String> homepageUrlSupplier,
             Runnable onSuccessRunnable,
             Supplier<Tab> activityTabSupplier,
-            @NonNull TabCreatorManager tabCreatorManager,
+            TabCreatorManager tabCreatorManager,
             @Nullable MultiInstanceManager multiInstanceManager) {
         mTabSupplier = tabSupplier;
         mTrackerSupplier = trackerSupplier;
@@ -110,6 +112,7 @@
                             .createNewTab(
                                     new LoadUrlParams(tab.getUrl()), TabLaunchType.UNSET, tab);
             if (mMultiInstanceManager == null) return false;
+            assumeNonNull(newTab);
             mMultiInstanceManager.moveTabToNewWindow(newTab);
             // Don't run mOnSuccessRunnable since nothing happened in the current tab.
             return true;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
index e1929d1..3e1ade8 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
@@ -12,6 +12,8 @@
 import org.chromium.base.FeatureList;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
@@ -32,6 +34,7 @@
  * <p>TODO(crbug.com/40729195): Move this to ../voice/ along with VoiceRecognitionHandler and the
  * assistant support.
  */
+@NullMarked
 public class VoiceToolbarButtonController extends BaseButtonDataProvider {
     private final Supplier<Tracker> mTrackerSupplier;
 
@@ -122,7 +125,8 @@
     }
 
     @Override
-    protected boolean shouldShowButton(Tab tab) {
+    protected boolean shouldShowButton(@Nullable Tab tab) {
+        if (tab == null) return false;
         if (!super.shouldShowButton(tab)) return false;
 
         return mVoiceSearchDelegate.isVoiceSearchEnabled()
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
index 82a93b4..df5e8fce 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
@@ -4,16 +4,19 @@
 
 package org.chromium.chrome.browser.toolbar.adaptive;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.PopupWindow;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.MenuBuilderHelper;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.components.browser_ui.widget.BrowserUiListMenuUtils;
@@ -26,11 +29,12 @@
 import org.chromium.ui.widget.RectProvider;
 
 /** Coordinator for the Adaptive Button action menu, responsible for creating a popup menu. */
+@NullMarked
 public class AdaptiveButtonActionMenuCoordinator {
     private final boolean mShowMenu;
 
     // For test.
-    private BasicListMenu mListMenu;
+    @Nullable private BasicListMenu mListMenu;
 
     public AdaptiveButtonActionMenuCoordinator(boolean showMenu) {
         mShowMenu = showMenu;
@@ -41,8 +45,8 @@
      *
      * @param onItemClicked called when a menu item is selected
      */
-    @Nullable
-    public View.OnLongClickListener createOnLongClickListener(Callback<Integer> onItemClicked) {
+    public View.@Nullable OnLongClickListener createOnLongClickListener(
+            Callback<Integer> onItemClicked) {
         if (!AdaptiveToolbarFeatures.isCustomizationEnabled()) return null;
 
         return view -> {
@@ -91,6 +95,7 @@
                 verticalPadding);
         ListMenuDelegate delegate =
                 new ListMenuDelegate() {
+                    @SuppressWarnings("NullAway")
                     @Override
                     public ListMenu getListMenu() {
                         return mListMenu;
@@ -120,6 +125,6 @@
     }
 
     public View getContentViewForTesting() {
-        return mListMenu.getContentView();
+        return assumeNonNull(mListMenu).getContentView();
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBehavior.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBehavior.java
index 3368b3e..872b816 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBehavior.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBehavior.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.ui.base.DeviceFormFactor;
 
@@ -16,6 +17,7 @@
 import java.util.Set;
 
 /** Embedder-specific behavior of Adaptive Toolbar. */
+@NullMarked
 public interface AdaptiveToolbarBehavior {
 
     /** List of the button variants both BrApp/CCT have in common. */
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBridge.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBridge.java
index 273e52c..54225bea 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBridge.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarBridge.java
@@ -11,12 +11,14 @@
 import org.jni_zero.NativeMethods;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.profiles.Profile;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /** Bridge between UI layer and native where segmentation platform is invoked. */
+@NullMarked
 public class AdaptiveToolbarBridge {
     /**
      * Called to get the per-session button list to show on the adaptive toolbar.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
index 9794d2e..1a5bcca 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.adaptive;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.ADAPTIVE_TOOLBAR_CUSTOMIZATION_ENABLED;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.ADAPTIVE_TOOLBAR_CUSTOMIZATION_SETTINGS;
 import static org.chromium.chrome.browser.toolbar.adaptive.settings.AdaptiveToolbarSettingsFragment.ARG_UI_STATE_AUTO_BUTTON_CAPTION;
@@ -17,7 +18,6 @@
 import android.os.Bundle;
 import android.view.View;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
@@ -29,6 +29,8 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneShotCallback;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -54,6 +56,7 @@
 import java.util.Objects;
 
 /** Meta {@link ButtonDataProvider} which chooses the optional button variant that will be shown. */
+@NullMarked
 public class AdaptiveToolbarButtonController
         implements ButtonDataProvider,
                 ButtonDataObserver,
@@ -62,7 +65,7 @@
 
     private final Context mContext;
     private ObserverList<ButtonDataObserver> mObservers = new ObserverList<>();
-    @Nullable private ButtonDataProvider mSingleProvider;
+    private @Nullable ButtonDataProvider mSingleProvider;
 
     // Maps from {@link AdaptiveToolbarButtonVariant} to {@link ButtonDataProvider}.
     private Map<Integer, ButtonDataProvider> mButtonDataProviderMap = new HashMap<>();
@@ -74,7 +77,7 @@
     private final ButtonDataImpl mButtonData = new ButtonDataImpl();
 
     /** The last received {@link ButtonSpec}. */
-    @Nullable private ButtonSpec mOriginalButtonSpec;
+    private @Nullable ButtonSpec mOriginalButtonSpec;
 
     /** {@code true} if the SessionVariant histogram value was already recorded. */
     private boolean mIsSessionVariantRecorded;
@@ -85,15 +88,15 @@
     private final Callback<AdaptiveToolbarStatePredictor.UiState> mUiStateCallback;
     private final AdaptiveToolbarBehavior mToolbarBehavior;
 
-    @Nullable private AdaptiveToolbarStatePredictor mAdaptiveToolbarStatePredictor;
-    @Nullable private View.OnLongClickListener mMenuHandler;
+    private @Nullable AdaptiveToolbarStatePredictor mAdaptiveToolbarStatePredictor;
+    private View.@Nullable OnLongClickListener mMenuHandler;
     private final Callback<Integer> mMenuClickListener;
     private final AdaptiveButtonActionMenuCoordinator mMenuCoordinator;
     private int mScreenWidthDp;
 
     private @AdaptiveToolbarButtonVariant int mSessionButtonVariant =
             AdaptiveToolbarButtonVariant.UNKNOWN;
-    private CurrentTabObserver mPageLoadMetricsRecorder;
+    private @Nullable CurrentTabObserver mPageLoadMetricsRecorder;
 
     /**
      * Constructs the {@link AdaptiveToolbarButtonController}.
@@ -117,6 +120,7 @@
                 id -> {
                     if (id == R.id.customize_adaptive_button_menu_id) {
                         RecordUserAction.record("MobileAdaptiveMenuCustomize");
+                        assumeNonNull(mAdaptiveToolbarStatePredictor);
                         mAdaptiveToolbarStatePredictor.recomputeUiState(this::startSettings);
                         return;
                     }
@@ -216,7 +220,7 @@
     }
 
     @Override
-    public ButtonData get(@Nullable Tab tab) {
+    public @Nullable ButtonData get(@Nullable Tab tab) {
         final ButtonData receivedButtonData =
                 mSingleProvider == null ? null : mSingleProvider.get(tab);
         if (receivedButtonData == null) {
@@ -276,8 +280,7 @@
         };
     }
 
-    @Nullable
-    private View.OnLongClickListener createMenuHandler() {
+    private View.@Nullable OnLongClickListener createMenuHandler() {
         if (!FeatureList.isInitialized()) return null;
         return mMenuCoordinator.createOnLongClickListener(mMenuClickListener);
     }
@@ -321,8 +324,7 @@
     }
 
     /** Returns the {@link ButtonDataProvider} used in a single-variant mode. */
-    @Nullable
-    public ButtonDataProvider getSingleProviderForTesting() {
+    public @Nullable ButtonDataProvider getSingleProviderForTesting() {
         return mSingleProvider;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
index a6ed23a..fbcf319 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
@@ -10,6 +10,8 @@
 
 import org.chromium.base.FeatureList;
 import org.chromium.base.ResettersForTesting;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.readaloud.ReadAloudFeatures;
@@ -18,6 +20,7 @@
 import java.util.HashMap;
 
 /** A utility class for handling feature flags used by {@link AdaptiveToolbarButtonController}. */
+@NullMarked
 public class AdaptiveToolbarFeatures {
     /** Finch default group for new tab variation. */
     static final String NEW_TAB = "new-tab";
@@ -48,11 +51,11 @@
             "action_chip_with_different_color";
 
     /** For testing only. */
-    private static String sDefaultSegmentForTesting;
+    private static @Nullable String sDefaultSegmentForTesting;
 
-    private static HashMap<Integer, Boolean> sActionChipOverridesForTesting;
-    private static HashMap<Integer, Boolean> sAlternativeColorOverridesForTesting;
-    private static HashMap<Integer, Boolean> sIsDynamicActionOverridesForTesting;
+    private static @Nullable HashMap<Integer, Boolean> sActionChipOverridesForTesting;
+    private static @Nullable HashMap<Integer, Boolean> sAlternativeColorOverridesForTesting;
+    private static @Nullable HashMap<Integer, Boolean> sIsDynamicActionOverridesForTesting;
 
     /**
      * @return Whether the button variant is a dynamic action.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarPrefs.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarPrefs.java
index 42eecda..f87f803 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarPrefs.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarPrefs.java
@@ -7,12 +7,14 @@
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.ADAPTIVE_TOOLBAR_CUSTOMIZATION_ENABLED;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.ADAPTIVE_TOOLBAR_CUSTOMIZATION_SETTINGS;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 
 /**
  * A utility class for handling adaptive toolbar customization user settings used by {@link
  * AdaptiveToolbarButtonController}.
  */
+@NullMarked
 public class AdaptiveToolbarPrefs {
     /**
      * Returns whether the customization preference toggle is enabled. Returns true if no value has
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
index 342502b..3675bf85 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
@@ -7,12 +7,12 @@
 import android.content.Context;
 import android.util.Pair;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
 import org.chromium.base.ResettersForTesting;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionUtil;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.segmentation_platform.proto.SegmentationProto.SegmentId;
@@ -25,19 +25,20 @@
  * preference, and segmentation platform backend prediction. This class is used only for the
  * segmentation experiment.
  */
+@NullMarked
 public class AdaptiveToolbarStatePredictor {
 
     /**
      * Key used to lookup segmentation results for adaptive toolbar. Must be kept in sync with
      * components/segmentation_platform/internal/constants.cc.
      */
-    private static List<Integer> sSegmentationResultsForTesting;
+    private static @Nullable List<Integer> sSegmentationResultsForTesting;
 
-    private static Integer sToolbarStateForTesting;
-    @NonNull private final Profile mProfile;
+    private static @Nullable Integer sToolbarStateForTesting;
+    private final Profile mProfile;
     private final AdaptiveToolbarBehavior mBehavior;
 
-    @Nullable private final AndroidPermissionDelegate mAndroidPermissionDelegate;
+    private final @Nullable AndroidPermissionDelegate mAndroidPermissionDelegate;
 
     /** The result of the predictor. Contains the UI states specific to the toolbar button. */
     public static class UiState {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStats.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStats.java
index c761155b..826cc8b3 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStats.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStats.java
@@ -9,12 +9,14 @@
 import androidx.annotation.IntDef;
 
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor.UiState;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /** Utility methods related to metrics collection for adaptive toolbar button. */
+@NullMarked
 public class AdaptiveToolbarStats {
     // Please treat this list as append only and keep it in sync with
     // AdaptiveToolbarRadioButtonState in enums.xml.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OpenInBrowserButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OpenInBrowserButtonController.java
index 93817f1..340d9e0 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OpenInBrowserButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OpenInBrowserButtonController.java
@@ -10,6 +10,7 @@
 import android.view.View;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.optional_button.BaseButtonDataProvider;
@@ -24,6 +25,7 @@
  * Optional toolbar button which opens the current Custom Tab in BrApp. May be used by {@link
  * AdaptiveToolbarButtonController}.
  */
+@NullMarked
 public class OpenInBrowserButtonController extends BaseButtonDataProvider {
 
     private final Runnable mOpenInBrowserRunnable;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
index e4ea442..4348774 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
@@ -10,11 +10,12 @@
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -35,6 +36,7 @@
  * Optional toolbar button which opens a new tab. May be used by {@link
  * AdaptiveToolbarButtonController}.
  */
+@NullMarked
 public class OptionalNewTabButtonController extends BaseButtonDataProvider
         implements ConfigurationChangedObserver {
     /**
@@ -54,8 +56,7 @@
         }
 
         /** Returns a {@link TabCreatorManager} used for creating the new tab. */
-        @Nullable
-        TabCreatorManager getTabCreatorManager() {
+        @Nullable TabCreatorManager getTabCreatorManager() {
             return mTabCreatorManagerSupplier.get();
         }
 
@@ -68,8 +69,7 @@
          *
          * <p>TODO(crbug.com/40753461): Make IncognitoStateProvider available in RootUiCooridnator.
          */
-        @Nullable
-        Supplier<Tab> getActiveTabSupplier() {
+        @Nullable Supplier<Tab> getActiveTabSupplier() {
             return mActiveTabSupplier;
         }
     }
@@ -154,7 +154,8 @@
     }
 
     @Override
-    protected boolean shouldShowButton(Tab tab) {
+    protected boolean shouldShowButton(@Nullable Tab tab) {
+        if (tab == null) return false;
         if (!super.shouldShowButton(tab) || mIsTablet) return false;
 
         if (UrlUtilities.isNtpUrl(tab.getUrl())) return false;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/TranslateToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/TranslateToolbarButtonController.java
index e118b60d..2b0f736 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/TranslateToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/TranslateToolbarButtonController.java
@@ -10,6 +10,8 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.optional_button.BaseButtonDataProvider;
@@ -21,6 +23,7 @@
 import org.chromium.components.feature_engagement.Tracker;
 
 /** Handles the translate button on the toolbar. */
+@NullMarked
 public class TranslateToolbarButtonController extends BaseButtonDataProvider {
     private final Supplier<Tracker> mTrackerSupplier;
 
@@ -75,7 +78,8 @@
     }
 
     @Override
-    protected boolean shouldShowButton(Tab tab) {
+    protected boolean shouldShowButton(@Nullable Tab tab) {
+        if (tab == null) return false;
         if (!super.shouldShowButton(tab)) return false;
         if (tab.isNativePage() && tab.getNativePage().isPdf()) return false;
         return UrlUtilities.isHttpOrHttps(tab.getUrl());
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarHeaderPreference.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarHeaderPreference.java
index 6fa31f0..c2e7bc97 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarHeaderPreference.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarHeaderPreference.java
@@ -9,9 +9,11 @@
 
 import androidx.preference.Preference;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.R;
 
 /** Fragment that allows the user to configure toolbar shorcut preferences. */
+@NullMarked
 public class AdaptiveToolbarHeaderPreference extends Preference {
     public AdaptiveToolbarHeaderPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java
index 1a07242c..ed4b3f80 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java
@@ -7,11 +7,12 @@
 import android.app.Activity;
 import android.os.Bundle;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionUtil;
 import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment;
 import org.chromium.chrome.browser.toolbar.R;
@@ -29,6 +30,7 @@
 import java.lang.ref.WeakReference;
 
 /** Fragment that allows the user to configure toolbar shortcut preferences. */
+@NullMarked
 public class AdaptiveToolbarSettingsFragment extends ChromeBaseSettingsFragment {
     /** The key for the switch taggle on the setting page. */
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@@ -45,12 +47,12 @@
     public static final String ARG_UI_STATE_PREFERENCE_SELECTION = "preference_selection";
     public static final String ARG_UI_STATE_AUTO_BUTTON_CAPTION = "auto_button_caption";
 
-    private @NonNull ChromeSwitchPreference mToolbarShortcutSwitch;
-    private @NonNull RadioButtonGroupAdaptiveToolbarPreference mRadioButtonGroup;
+    private ChromeSwitchPreference mToolbarShortcutSwitch;
+    private RadioButtonGroupAdaptiveToolbarPreference mRadioButtonGroup;
     private final ObservableSupplierImpl<String> mPageTitle = new ObservableSupplierImpl<>();
 
     @Override
-    public void onCreatePreferences(Bundle bundle, String s) {
+    public void onCreatePreferences(@Nullable Bundle bundle, @Nullable String s) {
         mPageTitle.set(getString(R.string.toolbar_shortcut));
         SettingsUtils.addPreferencesFromResource(this, R.xml.adaptive_toolbar_preference);
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/RadioButtonGroupAdaptiveToolbarPreference.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/RadioButtonGroupAdaptiveToolbarPreference.java
index 647b8f029..b3021b53 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/RadioButtonGroupAdaptiveToolbarPreference.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/RadioButtonGroupAdaptiveToolbarPreference.java
@@ -4,19 +4,22 @@
 
 package org.chromium.chrome.browser.toolbar.adaptive.settings;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.RadioGroup;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.build.annotations.EnsuresNonNullIf;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor;
@@ -26,17 +29,18 @@
 import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout;
 
 /** Fragment that allows the user to configure toolbar shortcut preferences. */
+@NullMarked
 public class RadioButtonGroupAdaptiveToolbarPreference extends Preference
         implements RadioGroup.OnCheckedChangeListener {
-    private @NonNull RadioButtonWithDescriptionLayout mGroup;
-    private @NonNull RadioButtonWithDescription mAutoButton;
-    private @NonNull RadioButtonWithDescription mNewTabButton;
-    private @NonNull RadioButtonWithDescription mShareButton;
-    private @NonNull RadioButtonWithDescription mVoiceSearchButton;
-    private @NonNull RadioButtonWithDescription mTranslateButton;
-    private @NonNull RadioButtonWithDescription mAddToBookmarksButton;
-    private @NonNull RadioButtonWithDescription mReadAloudButton;
-    private @NonNull RadioButtonWithDescription mPageSummaryButton;
+    private @Nullable RadioButtonWithDescriptionLayout mGroup;
+    private @Nullable RadioButtonWithDescription mAutoButton;
+    private @Nullable RadioButtonWithDescription mNewTabButton;
+    private @Nullable RadioButtonWithDescription mShareButton;
+    private @Nullable RadioButtonWithDescription mVoiceSearchButton;
+    private @Nullable RadioButtonWithDescription mTranslateButton;
+    private @Nullable RadioButtonWithDescription mAddToBookmarksButton;
+    private @Nullable RadioButtonWithDescription mReadAloudButton;
+    private @Nullable RadioButtonWithDescription mPageSummaryButton;
     private @AdaptiveToolbarButtonVariant int mSelected;
     private @AdaptiveToolbarButtonVariant int mAutoButtonCaption;
     private @Nullable AdaptiveToolbarStatePredictor mStatePredictor;
@@ -45,6 +49,7 @@
     private boolean mCanUsePageSummary;
     private boolean mButtonsInitialized;
     private Runnable mInitRadioButtonRunnable = this::initializeRadioButtonSelection;
+    private boolean mIsBound;
 
     public RadioButtonGroupAdaptiveToolbarPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -76,10 +81,28 @@
         mPageSummaryButton =
                 (RadioButtonWithDescription) holder.findViewById(R.id.adaptive_option_page_summary);
 
+        mIsBound = true;
+
         mInitRadioButtonRunnable.run();
         RecordUserAction.record("Mobile.AdaptiveToolbarButton.SettingsPage.Opened");
     }
 
+    @EnsuresNonNullIf({
+        "mGroup",
+        "mAutoButton",
+        "mNewTabButton",
+        "mShareButton",
+        "mVoiceSearchButton",
+        "mTranslateButton",
+        "mAddToBookmarksButton",
+        "mReadAloudButton",
+        "mPageSummaryButton"
+    })
+    @SuppressWarnings("NullAway")
+    private boolean isBound() {
+        return mIsBound;
+    }
+
     /**
      * Sets the state predictor for the preference, which provides data about the predicted "best"
      * choice for the button. This must be done post-construction since the preference is
@@ -92,7 +115,7 @@
     }
 
     private void initializeRadioButtonSelection() {
-        if (mStatePredictor == null || mGroup == null || mButtonsInitialized) return;
+        if (mStatePredictor == null || !isBound() || mButtonsInitialized) return;
 
         mStatePredictor.recomputeUiState(
                 uiState -> {
@@ -120,7 +143,7 @@
      * @param uiState {@link UiState} to initialize buttons with.
      */
     public void initButtonsFromUiState(UiState uiState) {
-        if (mGroup == null) {
+        if (!isBound()) {
             // View bindings are not ready yet. Try this again after the completion.
             mInitRadioButtonRunnable = () -> initButtonsFromUiState(uiState);
             return;
@@ -150,7 +173,9 @@
     }
 
     @Override
-    public void onCheckedChanged(RadioGroup group, int checkedId) {
+    public void onCheckedChanged(@Nullable RadioGroup group, int checkedId) {
+        if (!isBound()) return;
+
         @AdaptiveToolbarButtonVariant int previousSelection = mSelected;
         if (mAutoButton.isChecked()) {
             mSelected = AdaptiveToolbarButtonVariant.AUTO;
@@ -189,8 +214,7 @@
     }
 
     @VisibleForTesting
-    @Nullable
-    RadioButtonWithDescription getButton(@AdaptiveToolbarButtonVariant int variant) {
+    @Nullable RadioButtonWithDescription getButton(@AdaptiveToolbarButtonVariant int variant) {
         switch (variant) {
             case AdaptiveToolbarButtonVariant.AUTO:
                 return mAutoButton;
@@ -280,11 +304,12 @@
      * @param shouldBeVisible Whether the button should be hidden or not.
      */
     private void updateButtonVisibility(
-            RadioButtonWithDescription button, boolean shouldBeVisible) {
+            @Nullable RadioButtonWithDescription button, boolean shouldBeVisible) {
         if (button == null) return;
 
         button.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
         if (button.isChecked() && !shouldBeVisible) {
+            assumeNonNull(mAutoButton);
             mAutoButton.setChecked(true);
             onCheckedChanged(mGroup, mAutoButton.getId());
         }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java
index 3dceb89b..333d77ef 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java
@@ -7,6 +7,7 @@
 import android.content.res.ColorStateList;
 import android.view.View;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey;
@@ -18,6 +19,7 @@
  *
  * @see PropertyKey
  */
+@NullMarked
 class BackButtonProperties {
     public static final WritableObjectPropertyKey<Runnable> CLICK_LISTENER =
             new WritableObjectPropertyKey<>();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonViewBinder.java
index 111d1ae..20d9401f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonViewBinder.java
@@ -9,6 +9,7 @@
 
 import androidx.core.widget.ImageViewCompat;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -16,6 +17,7 @@
  * A class that binds changed {@link PropertyKey} in the {@link PropertyModel} to actual Android
  * view.
  */
+@NullMarked
 class BackButtonViewBinder {
 
     private BackButtonViewBinder() {}
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
index 56e6d1d..e536c3ca 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsContentDelegate.java
@@ -5,16 +5,19 @@
 package org.chromium.chrome.browser.toolbar.bottom;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 
 /**
- * Interface for the bottom controls content UI. This UI delegates various operations to
- * the implementation. This UI manages its own visibility through
- * {@link BottomControlsCoordinator.BottomControlsVisibilityController}.
+ * Interface for the bottom controls content UI. This UI delegates various operations to the
+ * implementation. This UI manages its own visibility through {@link
+ * BottomControlsCoordinator.BottomControlsVisibilityController}.
  */
+@NullMarked
 public interface BottomControlsContentDelegate extends BackPressHandler {
     /**
      * Called by the ToolbarManager when the system back button is pressed.
+     *
      * @return Whether or not the TabGroupUi consumed the event.
      */
     boolean onBackPressed();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
index b686d633..e23826a 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -15,6 +15,7 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.supplier.SupplierUtils;
 import org.chromium.base.supplier.TransitiveObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.browser_controls.BottomControlsStacker;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -44,6 +45,7 @@
  * when the controls are being scrolled off-screen. The Android version does not draw unless the
  * controls offset is 0.
  */
+@NullMarked
 public class BottomControlsCoordinator implements BackPressHandler {
     /** Interface for the BottomControls component to hide and show itself. */
     public interface BottomControlsVisibilityController {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
index 95dee97..b820836 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
@@ -4,11 +4,11 @@
 
 package org.chromium.chrome.browser.toolbar.bottom;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.CallbackController;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BottomControlsLayer;
 import org.chromium.chrome.browser.browser_controls.BottomControlsStacker;
 import org.chromium.chrome.browser.browser_controls.BottomControlsStacker.LayerScrollBehavior;
@@ -35,6 +35,7 @@
  * coordinators, running most of the business logic associated with the bottom controls component,
  * and updating the model accordingly.
  */
+@NullMarked
 class BottomControlsMediator
         implements BrowserControlsStateProvider.Observer,
                 KeyboardVisibilityDelegate.KeyboardVisibilityListener,
@@ -82,9 +83,9 @@
     /** Whether the soft keyboard is visible. */
     private boolean mIsKeyboardVisible;
 
-    private LayoutStateProvider mLayoutStateProvider;
+    private @Nullable LayoutStateProvider mLayoutStateProvider;
 
-    @Nullable private ChangeObserver mEdgeToEdgeChangeObserver;
+    private @Nullable ChangeObserver mEdgeToEdgeChangeObserver;
     private int mEdgeToEdgePaddingPx;
 
     /**
@@ -371,7 +372,7 @@
         return mBottomControlsShadowHeight;
     }
 
-    ChangeObserver getEdgeToEdgeChangeObserverForTesting() {
+    @Nullable ChangeObserver getEdgeToEdgeChangeObserverForTesting() {
         return mEdgeToEdgeChangeObserver;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
index 06dcdeb..9a50ce63 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsProperties.java
@@ -4,12 +4,14 @@
 
 package org.chromium.chrome.browser.toolbar.bottom;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.cc.input.OffsetTag;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
 
+@NullMarked
 class BottomControlsProperties {
     /** The height of the Android View in px. */
     static final WritableIntPropertyKey ANDROID_VIEW_HEIGHT = new WritableIntPropertyKey();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
index 9000c1b..1a95187b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java
@@ -6,11 +6,13 @@
 
 import android.view.View;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.dynamics.DynamicResourceReadyOnceCallback;
 
+@NullMarked
 class BottomControlsViewBinder {
     /**
      * A wrapper class that holds a {@link ScrollingBottomViewResourceFrameLayout} and a composited
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java
index c64250b..dd36042 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java
@@ -12,11 +12,10 @@
 import android.util.AttributeSet;
 import android.view.View;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.toolbar.ConstraintsChecker;
 import org.chromium.chrome.browser.toolbar.R;
@@ -28,6 +27,7 @@
  * A {@link ViewResourceFrameLayout} that specifically handles redraw of the top shadow of the view
  * it represents.
  */
+@NullMarked
 public class ScrollingBottomViewResourceFrameLayout extends ViewResourceFrameLayout {
     /** A cached rect to avoid extra allocations. */
     private final Rect mCachedRect = new Rect();
@@ -77,7 +77,8 @@
             }
 
             @Override
-            public void onCaptureStart(Canvas canvas, Rect dirtyRect) {
+            @SuppressWarnings("NullAway")
+            public void onCaptureStart(Canvas canvas, @Nullable Rect dirtyRect) {
                 // The android and composited views both have a shadow. The default state is to
                 // to show only the android shadow. When the bottom controls begin to scroll off,
                 // the android view is hidden, and the composited shadow is made visible. However,
@@ -132,9 +133,10 @@
      * Should be invoked any time a model change occurs that that materially impacts the way the
      * view should be drawn such that a new capture is warranted. Should not be affected by
      * animations.
+     *
      * @param token Can be used to compare with object equality against previous model states.
      */
-    public void onModelTokenChange(@NonNull Object token) {
+    public void onModelTokenChange(Object token) {
         mCurrentSnapshotToken = token;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
index 84a6cc31..d5c17dc 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java
@@ -10,6 +10,8 @@
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.cc.input.OffsetTag;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.EventFilter;
@@ -28,6 +30,7 @@
  * scrolling.
  */
 @JNINamespace("android")
+@NullMarked
 public class ScrollingBottomViewSceneLayer extends SceneOverlayLayer implements SceneOverlay {
     /** Handle to the native side of this class. */
     private long mNativePtr;
@@ -48,7 +51,7 @@
     private boolean mIsVisible;
 
     /** The OffsetTag indicating that this layer will be moved by viz. */
-    private OffsetTag mOffsetTag;
+    private @Nullable OffsetTag mOffsetTag;
 
     /** The {@link ViewResourceFrameLayout} that this scene layer represents. */
     private ViewResourceFrameLayout mBottomView;
@@ -153,7 +156,7 @@
     }
 
     @Override
-    public EventFilter getEventFilter() {
+    public @Nullable EventFilter getEventFilter() {
         return null;
     }
 
@@ -202,6 +205,6 @@
                 float xOffset,
                 float yOffset,
                 boolean showShadow,
-                OffsetTag offsetTag);
+                @Nullable OffsetTag offsetTag);
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButton.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButton.java
index 6567137..16e6fa7 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButton.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButton.java
@@ -8,9 +8,11 @@
 import android.util.AttributeSet;
 
 import org.chromium.base.TraceEvent;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.listmenu.ListMenuButton;
 
 /** The home button. */
+@NullMarked
 public class HomeButton extends ListMenuButton {
     public HomeButton(Context context, AttributeSet attrs) {
         super(context, attrs);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
index 2f388d6..c8abafa 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
@@ -10,12 +10,12 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.MenuBuilderHelper;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.components.browser_ui.widget.BrowserUiListMenuUtils;
@@ -30,6 +30,7 @@
  * home button.
  */
 // TODO(crbug.com/40676825): Fix the visibility bug on NTP.
+@NullMarked
 public class HomeButtonCoordinator {
     private static final int ID_SETTINGS = 0;
 
@@ -38,7 +39,7 @@
     private final Supplier<Boolean> mIsHomeButtonMenuDisabled;
 
     private final Callback<Context> mOnMenuClickCallback;
-    private MVCListAdapter.ModelList mMenuList;
+    private MVCListAdapter.@Nullable ModelList mMenuList;
     private @Nullable ListMenuDelegate mListMenuDelegate;
 
     /**
@@ -49,11 +50,11 @@
      * @param isHomepageMenuDisabledSupplier Supplier for whether the home button menu is enabled.
      */
     public HomeButtonCoordinator(
-            @NonNull Context context,
-            @NonNull View homeButton,
+            Context context,
+            View homeButton,
             OnClickListener onClickListener,
-            @NonNull Callback<Context> onMenuClickCallback,
-            @NonNull Supplier<Boolean> isHomepageMenuDisabledSupplier) {
+            Callback<Context> onMenuClickCallback,
+            Supplier<Boolean> isHomepageMenuDisabledSupplier) {
         mContext = context;
         mHomeButton = (HomeButton) homeButton;
         mOnMenuClickCallback = onMenuClickCallback;
@@ -97,7 +98,7 @@
         return true;
     }
 
-    public MVCListAdapter.ModelList getMenuForTesting() {
+    public MVCListAdapter.@Nullable ModelList getMenuForTesting() {
         return mMenuList;
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
index a100172..1618adf 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
@@ -4,15 +4,15 @@
 
 package org.chromium.chrome.browser.toolbar.load_progress;
 
-import androidx.annotation.NonNull;
-
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
 /** Coordinator for the load progress bar. Owns all progress bar sub-components. */
+@NullMarked
 public class LoadProgressCoordinator {
     private final PropertyModel mModel;
     private final LoadProgressMediator mMediator;
@@ -24,8 +24,7 @@
      * @param progressBarView Toolbar progress bar view.
      */
     public LoadProgressCoordinator(
-            @NonNull ObservableSupplier<Tab> tabSupplier,
-            @NonNull ToolbarProgressBar progressBarView) {
+            ObservableSupplier<Tab> tabSupplier, ToolbarProgressBar progressBarView) {
         mProgressBarView = progressBarView;
         mModel = new PropertyModel(LoadProgressProperties.ALL_KEYS);
         mMediator = new LoadProgressMediator(tabSupplier, mModel);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
index 3631ea87..dc12487 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
@@ -4,10 +4,9 @@
 
 package org.chromium.chrome.browser.toolbar.load_progress;
 
-import androidx.annotation.NonNull;
-
 import org.chromium.base.MathUtils;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.tab.CurrentTabObserver;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -21,6 +20,7 @@
  * Mediator for the load progress bar. Listens for changes to the loading state of the current tab
  * and adjusts its property model accordingly.
  */
+@NullMarked
 public class LoadProgressMediator {
     static final float MINIMUM_LOAD_PROGRESS = 0.05f;
 
@@ -33,8 +33,7 @@
      * @param tabSupplier An observable supplier of the current {@link Tab}.
      * @param model MVC property model instance used for load progress bar.
      */
-    public LoadProgressMediator(
-            @NonNull ObservableSupplier<Tab> tabSupplier, @NonNull PropertyModel model) {
+    public LoadProgressMediator(ObservableSupplier<Tab> tabSupplier, PropertyModel model) {
         mModel = model;
         mLoadProgressSimulator = new LoadProgressSimulator(model);
         mTabObserver =
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressProperties.java
index 93762c3..6401752 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressProperties.java
@@ -6,6 +6,7 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -13,6 +14,7 @@
 import java.lang.annotation.RetentionPolicy;
 
 /** List of load progress bar properties. */
+@NullMarked
 class LoadProgressProperties {
     @IntDef({
         CompletionState.UNFINISHED,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressSimulator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressSimulator.java
index 77248ec52..77c9c95 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressSimulator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressSimulator.java
@@ -11,13 +11,15 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.MathUtils;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /**
- * Simulator for  load progress changes when the page being rendered doesn't actually send load
+ * Simulator for load progress changes when the page being rendered doesn't actually send load
  * progress signals, e.g. when swapping in a pre-rendered page. Uses a message loop to send update
  * messages to itself to update the simulated progress value on a regular interval.
  */
+@NullMarked
 class LoadProgressSimulator {
     private static final int MSG_ID_UPDATE_PROGRESS = 1;
     private static final int PROGRESS_INCREMENT_DELAY_MS = 10;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressViewBinder.java
index 1d0f331..976fc01 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressViewBinder.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.load_progress;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
 import org.chromium.chrome.browser.toolbar.load_progress.LoadProgressProperties.CompletionState;
 import org.chromium.ui.modelutil.PropertyKey;
@@ -13,6 +14,7 @@
  * View binder for the load progress bar. Adjusts view properties on ToolbarProgressBar in response
  * to changes in the associated property model.
  */
+@NullMarked
 public class LoadProgressViewBinder {
     public void bind(PropertyModel model, ToolbarProgressBar view, PropertyKey propertyKey) {
         if (propertyKey == LoadProgressProperties.COMPLETION_STATE) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java
index 373845a67..cb77cf9 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.menu_button;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -28,6 +30,9 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.EnsuresNonNull;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.theme.ThemeColorProvider.TintObserver;
 import org.chromium.chrome.browser.theme.ThemeUtils;
 import org.chromium.chrome.browser.toolbar.R;
@@ -37,6 +42,7 @@
 import org.chromium.ui.interpolators.Interpolators;
 
 /** The overflow menu button. */
+@NullMarked
 public class MenuButton extends FrameLayout implements TintObserver {
     /** The {@link ImageButton} for the menu button. */
     private ImageButton mMenuImageButton;
@@ -46,21 +52,21 @@
 
     private @BrandedColorScheme int mBrandedColorScheme;
 
-    private AppMenuButtonHelper mAppMenuButtonHelper;
+    private @Nullable AppMenuButtonHelper mAppMenuButtonHelper;
 
     private boolean mHighlightingMenu;
-    private PulseDrawable mHighlightDrawable;
+    private @Nullable PulseDrawable mHighlightDrawable;
     private Drawable mOriginalBackground;
 
-    private AnimatorSet mMenuBadgeAnimatorSet;
+    private @Nullable AnimatorSet mMenuBadgeAnimatorSet;
     private boolean mIsMenuBadgeAnimationRunning;
 
-    /** A provider that notifies components when the theme color changes.*/
-    private BitmapDrawable mMenuImageButtonAnimationDrawable;
+    /** A provider that notifies components when the theme color changes. */
+    private @Nullable BitmapDrawable mMenuImageButtonAnimationDrawable;
 
-    private BitmapDrawable mUpdateBadgeAnimationDrawable;
+    private @Nullable BitmapDrawable mUpdateBadgeAnimationDrawable;
 
-    private Supplier<MenuButtonState> mStateSupplier;
+    private @Nullable Supplier<MenuButtonState> mStateSupplier;
 
     public MenuButton(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -111,7 +117,9 @@
         }
     }
 
+    @EnsuresNonNull({"mMenuImageButtonAnimationDrawable"})
     private void updateImageResources() {
+        assumeNonNull(mMenuImageButton.getDrawable().getConstantState());
         mMenuImageButtonAnimationDrawable =
                 (BitmapDrawable)
                         mMenuImageButton.getDrawable().getConstantState().newDrawable().mutate();
@@ -137,6 +145,7 @@
         @DrawableRes int drawable = getUpdateBadgeIcon(buttonState, mBrandedColorScheme);
         mUpdateBadgeView.setImageDrawable(
                 ApiCompatibilityUtils.getDrawable(getResources(), drawable));
+        assumeNonNull(mUpdateBadgeView.getDrawable().getConstantState());
         mUpdateBadgeAnimationDrawable =
                 (BitmapDrawable)
                         mUpdateBadgeView.getDrawable().getConstantState().newDrawable().mutate();
@@ -315,8 +324,8 @@
 
     @Override
     public void onTintChanged(
-            ColorStateList tintList,
-            ColorStateList activityFocusTintList,
+            @Nullable ColorStateList tintList,
+            @Nullable ColorStateList activityFocusTintList,
             @BrandedColorScheme int brandedColorScheme) {
         ImageViewCompat.setImageTintList(mMenuImageButton, tintList);
         mBrandedColorScheme = brandedColorScheme;
@@ -331,8 +340,8 @@
         }
 
         return isShowingAppMenuUpdateBadge()
-                ? mUpdateBadgeAnimationDrawable
-                : mMenuImageButtonAnimationDrawable;
+                ? assumeNonNull(mUpdateBadgeAnimationDrawable)
+                : assumeNonNull(mMenuImageButtonAnimationDrawable);
     }
 
     /**
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonCoordinator.java
index 63e4a47..9fba066d 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonCoordinator.java
@@ -6,6 +6,9 @@
 
 import static android.view.View.LAYOUT_DIRECTION_RTL;
 
+import static org.chromium.build.NullUtil.assertNonNull;
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.animation.Animator;
 import android.app.Activity;
 import android.graphics.Canvas;
@@ -13,11 +16,12 @@
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.IdRes;
-import androidx.annotation.Nullable;
 
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.theme.ThemeColorProvider;
 import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonProperties.ShowBadgeProperty;
@@ -35,6 +39,7 @@
  * Root component for the app menu button on the toolbar. Owns the MenuButton view and handles
  * changes to its visual state, e.g. showing/hiding the app update badge.
  */
+@NullMarked
 public class MenuButtonCoordinator {
     public interface SetFocusFunction {
         void setFocus(boolean focus, int reason);
@@ -43,9 +48,9 @@
     private final Activity mActivity;
     private final PropertyModel mPropertyModel;
     private MenuButtonMediator mMediator;
-    private AppMenuButtonHelper mAppMenuButtonHelper;
-    private MenuButton mMenuButton;
-    private PropertyModelChangeProcessor mChangeProcessor;
+    private @Nullable AppMenuButtonHelper mAppMenuButtonHelper;
+    private @Nullable MenuButton mMenuButton;
+    private @Nullable PropertyModelChangeProcessor mChangeProcessor;
 
     /**
      * @param appMenuCoordinatorSupplier Supplier for the AppMenuCoordinator, which owns all other
@@ -76,7 +81,7 @@
             Supplier<MenuButtonState> menuButtonStateSupplier,
             Runnable onMenuButtonClicked,
             @IdRes int menuButtonId) {
-        mActivity = windowAndroid.getActivity().get();
+        mActivity = assertNonNull(windowAndroid.getActivity().get());
         mMenuButton = mActivity.findViewById(menuButtonId);
         mPropertyModel =
                 new PropertyModel.Builder(MenuButtonProperties.ALL_KEYS)
@@ -173,6 +178,7 @@
      *
      * @param menuItemId The ID of the menu item to be highlighted.
      */
+    @SuppressWarnings("NullAway")
     public void highlightMenuItemOnShow(@IdRes int menuItemId) {
         mAppMenuButtonHelper.highlightMenuItemOnShow(menuItemId);
     }
@@ -188,7 +194,7 @@
      * Get the underlying MenuButton view. Present for legacy reasons only; don't add new usages.
      */
     @Deprecated
-    public MenuButton getMenuButton() {
+    public @Nullable MenuButton getMenuButton() {
         return mMenuButton;
     }
 
@@ -200,6 +206,7 @@
         mMediator.setClickable(isClickable);
     }
 
+    @SuppressWarnings("NullAway")
     public void destroy() {
         if (mMediator != null) {
             mMediator.destroy();
@@ -220,8 +227,7 @@
         return mMediator != null ? mMediator::updateStateChanged : null;
     }
 
-    @Nullable
-    public ObservableSupplier<AppMenuButtonHelper> getMenuButtonHelperSupplier() {
+    public @Nullable ObservableSupplier<AppMenuButtonHelper> getMenuButtonHelperSupplier() {
         if (mMediator == null) return null;
         return mMediator.getMenuButtonHelperSupplier();
     }
@@ -239,11 +245,13 @@
     /**
      * Draws the current visual state of this component for the purposes of rendering the tab
      * switcher animation, setting the alpha to fade the view by the appropriate amount.
+     *
      * @param root Root view for the menu button; used to position the canvas that's drawn on.
      * @param canvas Canvas to draw to.
      * @param alpha Integer (0-255) alpha level to draw at.
      */
     public void drawTabSwitcherAnimationOverlay(View root, Canvas canvas, int alpha) {
+        assumeNonNull(mMenuButton);
         canvas.save();
         ViewUtils.translateCanvasToView(root, mMenuButton, canvas);
         mMenuButton.drawTabSwitcherAnimationOverlay(canvas, alpha);
@@ -253,9 +261,10 @@
     /**
      * Creates an animator for the MenuButton during the process offocusing or unfocusing the
      * UrlBar. The animation translate and fades the button into/out of view.
+     *
      * @return The Animator object for the MenuButton.
      * @param isFocusingUrl Whether the animation is for focusing the URL, meaning the button is
-     *         fading out of view, or un-focusing, meaning it's fading into view.
+     *     fading out of view, or un-focusing, meaning it's fading into view.
      */
     public Animator getUrlFocusingAnimator(boolean isFocusingUrl) {
         return mMediator.getUrlFocusingAnimator(
@@ -274,6 +283,7 @@
      * @param backgroundResId The button background resource.
      */
     public void updateButtonBackground(@DrawableRes int backgroundResId) {
+        assumeNonNull(mMenuButton);
         mMenuButton.getImageButton().setBackgroundResource(backgroundResId);
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java
index e8e8f67..2803c7e 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.toolbar.menu_button;
 
+import static org.chromium.build.NullUtil.assertNonNull;
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.app.Activity;
@@ -11,8 +14,6 @@
 import android.content.res.Resources;
 import android.view.View;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.Callback;
 import org.chromium.base.MathUtils;
 import org.chromium.base.metrics.RecordUserAction;
@@ -20,6 +21,8 @@
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
 import org.chromium.chrome.browser.theme.ThemeColorProvider;
@@ -43,12 +46,13 @@
  * Mediator for the MenuButton. Listens for MenuButton state changes and drives corresponding
  * changes to the property model that backs the MenuButton view.
  */
+@NullMarked
 class MenuButtonMediator implements AppMenuObserver {
     private Callback<AppMenuCoordinator> mAppMenuCoordinatorSupplierObserver;
     private @Nullable AppMenuPropertiesDelegate mAppMenuPropertiesDelegate;
-    private AppMenuButtonHelper mAppMenuButtonHelper;
+    private @Nullable AppMenuButtonHelper mAppMenuButtonHelper;
     private ObservableSupplierImpl<AppMenuButtonHelper> mAppMenuButtonHelperSupplier;
-    private AppMenuHandler mAppMenuHandler;
+    private @Nullable AppMenuHandler mAppMenuHandler;
     private final BrowserStateBrowserControlsVisibilityDelegate mControlsVisibilityDelegate;
     private final SetFocusFunction mSetUrlBarFocusFunction;
     private final PropertyModel mPropertyModel;
@@ -111,7 +115,7 @@
         mAppMenuCoordinatorSupplierObserver = this::onAppMenuInitialized;
         mAppMenuCoordinatorSupplier = appMenuCoordinatorSupplier;
         mAppMenuCoordinatorSupplier.onAvailable(mAppMenuCoordinatorSupplierObserver);
-        mActivity = windowAndroid.getActivity().get();
+        mActivity = assertNonNull(windowAndroid.getActivity().get());
         mResources = mActivity.getResources();
         mAppMenuButtonHelperSupplier = new ObservableSupplierImpl<>();
         mKeyboardDelegate = windowAndroid.getKeyboardDelegate();
@@ -191,6 +195,7 @@
 
     void destroy() {
         if (mAppMenuButtonHelper != null) {
+            assumeNonNull(mAppMenuHandler);
             mAppMenuHandler.removeObserver(this);
             mAppMenuButtonHelper = null;
         }
@@ -225,8 +230,8 @@
     }
 
     private void onTintChanged(
-            ColorStateList tintList,
-            ColorStateList activityFocusTintList,
+            @Nullable ColorStateList tintList,
+            @Nullable ColorStateList activityFocusTintList,
             @BrandedColorScheme int brandedColorScheme) {
         mPropertyModel.set(
                 MenuButtonProperties.THEME,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonProperties.java
index ff05ead..ba5c8ae 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonProperties.java
@@ -7,9 +7,9 @@
 import android.content.res.ColorStateList;
 import android.view.View.OnKeyListener;
 
-import androidx.annotation.NonNull;
-
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 import org.chromium.ui.modelutil.PropertyKey;
@@ -17,13 +17,14 @@
 import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
+@NullMarked
 class MenuButtonProperties {
     static class ThemeProperty {
-        @NonNull public ColorStateList mColorStateList;
+        public @Nullable ColorStateList mColorStateList;
         public @BrandedColorScheme int mBrandedColorScheme;
 
         public ThemeProperty(
-                @NonNull ColorStateList colorStateList,
+                @Nullable ColorStateList colorStateList,
                 @BrandedColorScheme int brandedColorScheme) {
             mColorStateList = colorStateList;
             mBrandedColorScheme = brandedColorScheme;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonState.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonState.java
index f495739c..663d5de 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonState.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonState.java
@@ -7,11 +7,14 @@
 import androidx.annotation.DrawableRes;
 import androidx.annotation.StringRes;
 
+import org.chromium.build.annotations.NullMarked;
+
 /** The UI state required to properly display a 'update decorated' main menu button. */
+@NullMarked
 public class MenuButtonState {
     /**
-     * The new content description of the menu button.  Always set if this object is not
-     * {@code null}.
+     * The new content description of the menu button. Always set if this object is not {@code
+     * null}.
      */
     public @StringRes int menuContentDescription;
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonViewBinder.java
index 36098ee4..8e0caba8 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonViewBinder.java
@@ -6,12 +6,14 @@
 
 import android.view.View;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonProperties.ShowBadgeProperty;
 import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonProperties.ThemeProperty;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder;
 
+@NullMarked
 class MenuButtonViewBinder implements ViewBinder<PropertyModel, MenuButton, PropertyKey> {
     // Whether MenuButtonState supplier was set already. The supplier needs to be set before
     // some other properties.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuItemState.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuItemState.java
index f60f789..91b4647 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuItemState.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuItemState.java
@@ -6,12 +6,15 @@
 
 import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
+
 /** The UI state required to properly display an update-related main menu item. */
+@NullMarked
 public class MenuItemState {
-    /** The title resource of the menu.  Always set if this object is not {@code null}. */
+    /** The title resource of the menu. Always set if this object is not {@code null}. */
     public @StringRes int title;
 
     /** The color resource of the title.  Always set if this object is not {@code null}. */
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuUiState.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuUiState.java
index 2d7aa29a..cbc2b1a 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuUiState.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuUiState.java
@@ -4,16 +4,17 @@
 
 package org.chromium.chrome.browser.toolbar.menu_button;
 
-import androidx.annotation.Nullable;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 
 /**
- * The UI state required to properly decorate the main menu.  This may include the button
- * decorations as well as the actual update item to show in the menu.
+ * The UI state required to properly decorate the main menu. This may include the button decorations
+ * as well as the actual update item to show in the menu.
  */
+@NullMarked
 public class MenuUiState {
     /**
-     * The optional UI state for building the menu item.  If {@code null} no item should be
-     * shown.
+     * The optional UI state for building the menu item. If {@code null} no item should be shown.
      */
     public @Nullable MenuItemState itemState;
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/BaseButtonDataProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/BaseButtonDataProvider.java
index 21101b0..9826537a9 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/BaseButtonDataProvider.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/BaseButtonDataProvider.java
@@ -10,12 +10,13 @@
 import android.view.View.OnClickListener;
 
 import androidx.annotation.CallSuper;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
 import org.chromium.base.FeatureList;
 import org.chromium.base.ObserverList;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
@@ -25,13 +26,14 @@
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** Base class for button data providers used on the adaptive toolbar. */
+@NullMarked
 public abstract class BaseButtonDataProvider implements ButtonDataProvider, OnClickListener {
     protected final ButtonDataImpl mButtonData;
     protected final Supplier<Tab> mActiveTabSupplier;
 
     private final ObserverList<ButtonDataObserver> mObservers = new ObserverList<>();
-    private final ModalDialogManager mModalDialogManager;
-    private ModalDialogManagerObserver mModalDialogObserver;
+    private final @Nullable ModalDialogManager mModalDialogManager;
+    private @Nullable ModalDialogManagerObserver mModalDialogObserver;
 
     private boolean mShouldShowOnIncognitoTabs;
 
@@ -108,7 +110,7 @@
      * @return whether the button should be shown for the current tab.
      */
     @CallSuper
-    protected boolean shouldShowButton(Tab tab) {
+    protected boolean shouldShowButton(@Nullable Tab tab) {
         if (tab == null) return false;
 
         if (tab.isIncognito() && !mShouldShowOnIncognitoTabs) return false;
@@ -128,7 +130,7 @@
      *
      * @param tab Current tab.
      */
-    private void maybeSetIphCommandBuilder(Tab tab) {
+    private void maybeSetIphCommandBuilder(@Nullable Tab tab) {
         if (mButtonData.getButtonSpec().getIphCommandBuilder() != null
                 || tab == null
                 || !FeatureList.isInitialized()
@@ -154,7 +156,7 @@
      * @return An {@link org.chromium.chrome.browser.user_education.IphCommand} instance to set on
      *     this button, or null if no IPH should be used.
      */
-    protected IphCommandBuilder getIphCommandBuilder(Tab tab) {
+    protected @Nullable IphCommandBuilder getIphCommandBuilder(Tab tab) {
         return null;
     }
 
@@ -170,7 +172,7 @@
     }
 
     @Override
-    public ButtonData get(Tab tab) {
+    public ButtonData get(@Nullable Tab tab) {
         mButtonData.setCanShow(shouldShowButton(tab));
         maybeSetIphCommandBuilder(tab);
 
@@ -179,6 +181,7 @@
 
     @Override
     @CallSuper
+    @SuppressWarnings("NullAway")
     public void destroy() {
         mObservers.clear();
         if (mModalDialogManager != null) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java
index 2e6a048..01211e40 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java
@@ -8,10 +8,10 @@
 import android.view.View;
 
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
 import org.chromium.chrome.browser.user_education.IphCommandBuilder;
@@ -23,6 +23,7 @@
  *
  * @see ButtonDataProvider
  */
+@NullMarked
 public interface ButtonData {
     /** Returns {@code true} when the {@link ButtonDataProvider} wants to show a button. */
     boolean canShow();
@@ -47,13 +48,13 @@
     /** A set of button properties which are not expected to change values often. */
     final class ButtonSpec {
         public static final int INVALID_TOOLTIP_TEXT_ID = 0;
-        @NonNull private final Drawable mDrawable;
-        // TODO(crbug.com/40753109): make mOnClickListener @NonNull
-        @Nullable private final View.OnClickListener mOnClickListener;
-        @Nullable private final View.OnLongClickListener mOnLongClickListener;
+        private final Drawable mDrawable;
+        // TODO(crbug.com/40753109): make mOnClickListener
+        private final View.OnClickListener mOnClickListener;
+        private final View.@Nullable OnLongClickListener mOnLongClickListener;
         private final String mContentDescription;
         private final boolean mSupportsTinting;
-        @Nullable private final IphCommandBuilder mIphCommandBuilder;
+        private final @Nullable IphCommandBuilder mIphCommandBuilder;
         @AdaptiveToolbarButtonVariant private final int mButtonVariant;
         private final boolean mIsDynamicAction;
         @StringRes private final int mActionChipLabelResId;
@@ -62,9 +63,9 @@
         private final boolean mHasErrorBadge;
 
         public ButtonSpec(
-                @NonNull Drawable drawable,
-                @NonNull View.OnClickListener onClickListener,
-                @Nullable View.OnLongClickListener onLongClickListener,
+                Drawable drawable,
+                View.OnClickListener onClickListener,
+                View.@Nullable OnLongClickListener onLongClickListener,
                 String contentDescription,
                 boolean supportsTinting,
                 @Nullable IphCommandBuilder iphCommandBuilder,
@@ -88,19 +89,17 @@
         }
 
         /** Returns the {@link Drawable} for the button icon. */
-        public @NonNull Drawable getDrawable() {
+        public Drawable getDrawable() {
             return mDrawable;
         }
 
         /** Returns the {@link View.OnClickListener} used on the button. */
-        @NonNull
         public View.OnClickListener getOnClickListener() {
             return mOnClickListener;
         }
 
         /** Returns an optional {@link View.OnLongClickListener} used on the button. */
-        @NonNull
-        public View.OnLongClickListener getOnLongClickListener() {
+        public View.@Nullable OnLongClickListener getOnLongClickListener() {
             return mOnLongClickListener;
         }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataImpl.java
index 0a7d7b0b..56f85650 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataImpl.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataImpl.java
@@ -9,10 +9,10 @@
 import android.view.View.OnClickListener;
 
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.user_education.IphCommandBuilder;
@@ -20,19 +20,20 @@
 import java.util.Objects;
 
 /** An implementation of the {@link ButtonData}. */
+@NullMarked
 public class ButtonDataImpl implements ButtonData {
     private boolean mCanShow;
     private boolean mIsEnabled;
     private @DrawableRes int mBackgroundResId;
 
-    private ButtonSpec mButtonSpec;
+    private @SuppressWarnings("NullAway.Init") ButtonSpec mButtonSpec;
 
     public ButtonDataImpl() {}
 
     public ButtonDataImpl(
             boolean canShow,
-            @NonNull Drawable drawable,
-            @NonNull OnClickListener onClickListener,
+            Drawable drawable,
+            OnClickListener onClickListener,
             String contentDescription,
             boolean supportsTinting,
             @Nullable IphCommandBuilder iphCommandBuilder,
@@ -56,8 +57,8 @@
 
     public ButtonDataImpl(
             boolean canShow,
-            @NonNull Drawable drawable,
-            @NonNull OnClickListener onClickListener,
+            Drawable drawable,
+            OnClickListener onClickListener,
             String contentDescription,
             @StringRes int actionChipLabelResId,
             boolean supportsTinting,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataProvider.java
index c13b62c1..8d9332e 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataProvider.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonDataProvider.java
@@ -4,14 +4,15 @@
 
 package org.chromium.chrome.browser.toolbar.optional_button;
 
-import androidx.annotation.Nullable;
-
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 
 /**
  * Interface for components that wish to display a button in the "optional" button slot in the
  * browsing mode toolbar.
  */
+@NullMarked
 public interface ButtonDataProvider {
     /**
      * Observer class for changes in button state. Implementers should notify their observers when
@@ -35,7 +36,7 @@
     void removeObserver(ButtonDataObserver obs);
 
     /** Get the current ButtonData, including any tab-specific adjustments. */
-    ButtonData get(@Nullable Tab tab);
+    @Nullable ButtonData get(@Nullable Tab tab);
 
     /**
      * Destroy the provider. This should be made safe to call multiple times, in case a provider is
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonConstants.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonConstants.java
index 0fcd415..a7b8d7b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonConstants.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonConstants.java
@@ -6,10 +6,13 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /** Defines constants used by optional button. */
+@NullMarked
 public class OptionalButtonConstants {
     /**
      * Defines the different transition types for optional button, they are used as arguments to the
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java
index 8b775ad..2b7be11 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.optional_button;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -16,6 +18,8 @@
 import org.chromium.base.Callback;
 import org.chromium.base.FeatureList;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
 import org.chromium.chrome.browser.user_education.IphCommandBuilder;
@@ -37,13 +41,14 @@
  * The coordinator for a button that may appear on the toolbar whose icon and click handler can be
  * updated with animations.
  */
+@NullMarked
 public class OptionalButtonCoordinator {
     private final OptionalButtonMediator mMediator;
     private final OptionalButtonView mView;
     private final Supplier<UserEducationHelper> mUserEducationHelper;
     private final Supplier<Tracker> mFeatureEngagementTrackerSupplier;
-    private Callback<Integer> mTransitionFinishedCallback;
-    private IphCommandBuilder mIphCommandBuilder;
+    private @Nullable Callback<Integer> mTransitionFinishedCallback;
+    private @Nullable IphCommandBuilder mIphCommandBuilder;
 
     @IntDef({
         TransitionType.SWAPPING,
@@ -131,7 +136,7 @@
      * (according to the BooleanSupplier set with setIsAnimationAllowedPredicate) then this update
      * will be animated. Otherwise it'll instantly switch to the new icon.
      */
-    public void updateButton(ButtonData buttonData, boolean isIncognito) {
+    public void updateButton(@Nullable ButtonData buttonData, boolean isIncognito) {
         if (buttonData != null
                 && buttonData.getButtonSpec() != null
                 && buttonData.getButtonSpec().getIphCommandBuilder() != null) {
@@ -148,6 +153,7 @@
 
         // Dynamic buttons include an action chip resource ID by default regardless of variant.
         if (hasActionChipResourceId) {
+            assumeNonNull(buttonData);
             // We should only show the action chip if the action chip variant is enabled.
             boolean isActionChipVariant =
                     FeatureList.isInitialized()
@@ -200,7 +206,7 @@
     /**
      * Updates the foreground color on the icons and label to match the current theme/website color.
      */
-    public void setIconForegroundColor(ColorStateList colorStateList) {
+    public void setIconForegroundColor(@Nullable ColorStateList colorStateList) {
         mMediator.setIconForegroundColor(colorStateList);
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonMediator.java
index da8c592fe..d7badf8f9 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonMediator.java
@@ -9,8 +9,11 @@
 import androidx.annotation.ColorInt;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.ui.modelutil.PropertyModel;
 
+@NullMarked
 class OptionalButtonMediator {
     private final PropertyModel mModel;
 
@@ -18,7 +21,7 @@
         mModel = model;
     }
 
-    void updateButton(ButtonData buttonData) {
+    void updateButton(@Nullable ButtonData buttonData) {
         mModel.set(OptionalButtonProperties.BUTTON_DATA, buttonData);
         if (buttonData != null) {
             mModel.set(OptionalButtonProperties.IS_ENABLED, buttonData.isEnabled());
@@ -29,7 +32,7 @@
         mModel.set(OptionalButtonProperties.TRANSITION_STARTED_CALLBACK, transitionStartedCallback);
     }
 
-    void setIconForegroundColor(ColorStateList colorStateList) {
+    void setIconForegroundColor(@Nullable ColorStateList colorStateList) {
         mModel.set(OptionalButtonProperties.ICON_TINT_LIST, colorStateList);
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonProperties.java
index 3d6d83bb..7b12feb 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonProperties.java
@@ -8,6 +8,7 @@
 import android.view.ViewGroup;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
@@ -15,6 +16,7 @@
 
 import java.util.function.BooleanSupplier;
 
+@NullMarked
 class OptionalButtonProperties {
     // We skip equality checks because some controllers update their button by changing the
     // ButtonSpec value on the same ButtonData instance. In addition we don't split this into
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
index 1e0f98dce..62cd527 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.optional_button;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -31,8 +33,6 @@
 
 import androidx.annotation.DimenRes;
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.appcompat.widget.TooltipCompat;
 import androidx.core.view.ViewCompat;
@@ -42,6 +42,9 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
+import org.chromium.build.annotations.MonotonicNonNull;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.R;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
@@ -54,6 +57,7 @@
 import java.util.function.BooleanSupplier;
 
 /** Toolbar button that performs animated transitions between icons. */
+@NullMarked
 class OptionalButtonView extends FrameLayout implements TransitionListener {
     private static final int SWAP_TRANSITION_DURATION_MS = 300;
     private static final int HIDE_TRANSITION_DURATION_MS = 225;
@@ -66,18 +70,18 @@
     private ListMenuButton mButton;
     private ImageView mAnimationImage;
 
-    private Drawable mIconDrawable;
+    private @Nullable Drawable mIconDrawable;
 
-    private ViewGroup mTransitionRoot;
-    private String mContentDescription;
-    private String mActionChipLabelString;
+    private @MonotonicNonNull ViewGroup mTransitionRoot;
+    private @Nullable String mContentDescription;
+    private @Nullable String mActionChipLabelString;
     private boolean mCurrentButtonSupportsTinting;
-    private ColorStateList mForegroundColorTint;
+    private @Nullable ColorStateList mForegroundColorTint;
     private int mBackgroundColorFilter;
-    private Runnable mOnBeforeHideTransitionCallback;
-    private Callback<Transition> mFakeBeginTransitionForTesting;
-    private Handler mHandler;
-    private Handler mHandlerForTesting;
+    private @Nullable Runnable mOnBeforeHideTransitionCallback;
+    private @Nullable Callback<Transition> mFakeBeginTransitionForTesting;
+    private @Nullable Handler mHandler;
+    private @Nullable Handler mHandlerForTesting;
 
     private @State int mState;
 
@@ -87,15 +91,16 @@
     private @ButtonType int mCurrentButtonType;
     private @ButtonType int mNextButtonType;
 
-    private OnClickListener mClickListener;
-    private OnLongClickListener mLongClickListener;
-    private Callback<Integer> mTransitionStartedCallback;
-    private Callback<Integer> mTransitionFinishedCallback;
-    private BooleanSupplier mIsAnimationAllowedPredicate;
+    private @Nullable OnClickListener mClickListener;
+    private @Nullable OnLongClickListener mLongClickListener;
+    private @Nullable Callback<Integer> mTransitionStartedCallback;
+    private @Nullable Callback<Integer> mTransitionFinishedCallback;
+    private @Nullable BooleanSupplier mIsAnimationAllowedPredicate;
     private final Runnable mCollapseActionChipRunnable =
             new Runnable() {
                 @Override
                 public void run() {
+                    assumeNonNull(mIsAnimationAllowedPredicate);
                     if (mIsAnimationAllowedPredicate.getAsBoolean()) {
                         animateActionChipCollapse();
                     } else {
@@ -352,7 +357,7 @@
     }
 
     /** Constructor for inflating from XML. */
-    public OptionalButtonView(@NonNull Context context, @Nullable AttributeSet attrs) {
+    public OptionalButtonView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
 
         mState = State.HIDDEN;
@@ -419,10 +424,11 @@
     /**
      * Listens to all transition ends. This is called even if the transition is cancelled or if all
      * animations are disabled. Implementation of {@link TransitionListener}.
+     *
      * @param transition Transition that ended, not used.
      */
     @Override
-    public void onTransitionEnd(Transition transition) {
+    public void onTransitionEnd(@Nullable Transition transition) {
         if (mTransitionFinishedCallback != null
                 && getCurrentTransitionType() != TransitionType.NONE) {
             mTransitionFinishedCallback.onResult(getCurrentTransitionType());
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewBinder.java
index 1d276c9f..c522d08 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewBinder.java
@@ -4,9 +4,11 @@
 
 package org.chromium.chrome.browser.toolbar.optional_button;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
+@NullMarked
 class OptionalButtonViewBinder {
     static void bind(PropertyModel model, OptionalButtonView view, PropertyKey propertyKey) {
         if (OptionalButtonProperties.BUTTON_DATA.equals(propertyKey)) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ShrinkTransition.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ShrinkTransition.java
index 92cb47a..949b38d 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ShrinkTransition.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ShrinkTransition.java
@@ -13,10 +13,13 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import org.chromium.build.annotations.NullMarked;
+
 /**
  * A transition that changes a view's scale when it's appearing or disappearing, it animates both
  * scaleX and scaleY towards 0 when disappearing and towards 1 when appearing.
  */
+@NullMarked
 public class ShrinkTransition extends Visibility {
     @Override
     public Animator onAppear(
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonProperties.java
index e7e4418..2de036f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonProperties.java
@@ -9,6 +9,7 @@
 import android.view.View;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
 import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey;
@@ -16,6 +17,7 @@
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 /** Reload button properties set. */
+@NullMarked
 class ReloadButtonProperties {
 
     public static final WritableFloatPropertyKey ALPHA = new WritableFloatPropertyKey();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonViewBinder.java
index 7f786b2..cea4bff 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/reload_button/ReloadButtonViewBinder.java
@@ -12,11 +12,13 @@
 import androidx.core.widget.ImageViewCompat;
 
 import org.chromium.base.Callback;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** A binder that binds model changes to view state. */
+@NullMarked
 class ReloadButtonViewBinder {
     /**
      * Reflects model property change based on they key on the view.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarHeaderPreference.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarHeaderPreference.java
index b81ce081..42c98c8 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarHeaderPreference.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarHeaderPreference.java
@@ -10,20 +10,21 @@
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.toolbar.R;
 
 /** The header shows on the top of {@link AddressBarPreference}. */
+@NullMarked
 public class AddressBarHeaderPreference extends Preference
         implements OnSharedPreferenceChangeListener {
-    private @NonNull ImageView mToolbarPositionImage;
+    private @Nullable ImageView mToolbarPositionImage;
 
     public AddressBarHeaderPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -56,12 +57,16 @@
     @Override
     public void onSharedPreferenceChanged(
             SharedPreferences sharedPreferences, @Nullable String key) {
-        if (key.equals(ChromePreferenceKeys.TOOLBAR_TOP_ANCHORED)) {
+        if (key != null && key.equals(ChromePreferenceKeys.TOOLBAR_TOP_ANCHORED)) {
             updateImageVisibility();
         }
     }
 
     private void updateImageVisibility() {
+        if (mToolbarPositionImage == null) {
+            return;
+        }
+
         boolean showOnTop = AddressBarPreference.isToolbarConfiguredToShowOnTop();
 
         mToolbarPositionImage.setSelected(showOnTop);
@@ -72,9 +77,8 @@
         mToolbarPositionImage.setContentDescription(getContext().getString(stringRes));
     }
 
-    @NonNull
     @VisibleForTesting
-    ImageView getToolbarPositionImage() {
+    @Nullable ImageView getToolbarPositionImage() {
         return mToolbarPositionImage;
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ActionModeController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ActionModeController.java
index eb5f698..1645734c 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ActionModeController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ActionModeController.java
@@ -15,17 +15,20 @@
 import androidx.appcompat.app.ActionBar;
 
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.R;
 
 /**
  * This class controls the how toolbar animates while the action mode bar is being shown. It also
  * manages a {@link ToolbarActionModeCallback}.
  */
+@NullMarked
 public class ActionModeController {
     private static final int SLIDE_DURATION_MS = 200;
 
     private ToolbarActionModeCallback mToolbarActionModeCallback;
-    private ObjectAnimator mCurrentAnimation;
+    private @Nullable ObjectAnimator mCurrentAnimation;
     private boolean mShowingActionMode;
     private ObservableSupplier<Integer> mTabStripHeightSupplier;
     private final Context mContext;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java
index 6f60a29..576ae0b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java
@@ -8,6 +8,8 @@
 
 import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.ToolbarFeatures;
 
 import java.lang.annotation.Retention;
@@ -19,6 +21,7 @@
  * arbitrarily and consistently pick one reason. The reason is used to report metrics and should
  * still be a useful tool for understanding captures.
  */
+@NullMarked
 public class CaptureReadinessResult {
     /**
      * TODO(peilinwang): For debugging https://crbug.com/398845668, if an animation is blocking a
@@ -135,7 +138,7 @@
                 TopToolbarBlockCaptureReason.NUM_ENTRIES);
     }
 
-    public static void logCaptureReasonFromResult(CaptureReadinessResult result) {
+    public static void logCaptureReasonFromResult(@Nullable CaptureReadinessResult result) {
         if (!ToolbarFeatures.shouldRecordSuppressionMetrics()) {
             return;
         }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java
index 60883af..353ec57 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -20,13 +22,14 @@
 import android.widget.TextView;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.widget.ImageViewCompat;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.R;
@@ -46,6 +49,7 @@
 import java.util.Set;
 
 /** A popup that handles displaying the navigation history for a given tab. */
+@NullMarked
 public class NavigationPopup implements AdapterView.OnItemClickListener {
     private static final int MAXIMUM_HISTORY_ITEMS = 8;
     private static final int FULL_HISTORY_ENTRY_INDEX = -1;
@@ -77,7 +81,7 @@
     private final NavigationAdapter mAdapter;
     private final @Type int mType;
     private final int mFaviconSize;
-    @Nullable private final OnLayoutChangeListener mAnchorViewLayoutChangeListener;
+    private final @Nullable OnLayoutChangeListener mAnchorViewLayoutChangeListener;
     private final Supplier<Tab> mCurrentTabSupplier;
     private final HistoryDelegate mHistoryDelegate;
 
@@ -86,7 +90,7 @@
     /** Loads the favicons asynchronously. */
     private FaviconHelper mFaviconHelper;
 
-    private Runnable mOnDismissCallback;
+    private @Nullable Runnable mOnDismissCallback;
 
     private boolean mInitialized;
 
@@ -100,10 +104,11 @@
      * @param currentTabSupplier Supplies the current tab.
      * @param historyDelegate Delegate used to display navigation history.
      */
+    @SuppressWarnings("NullAway")
     public NavigationPopup(
             Profile profile,
             Context context,
-            NavigationController navigationController,
+            @Nullable NavigationController navigationController,
             @Type int type,
             Supplier<Tab> currentTabSupplier,
             HistoryDelegate historyDelegate) {
@@ -222,6 +227,7 @@
 
     private void centerPopupOverAnchorViewAndShow() {
         assert mInitialized;
+        assumeNonNull(mPopup.getAnchorView());
         int horizontalOffset = (mPopup.getAnchorView().getWidth() - mPopup.getWidth()) / 2;
         if (horizontalOffset > 0) mPopup.setHorizontalOffset(horizontalOffset);
         mPopup.show();
@@ -232,6 +238,7 @@
         mInitialized = false;
         if (mDefaultFaviconHelper != null) mDefaultFaviconHelper.clearCache();
         if (mAnchorViewLayoutChangeListener != null) {
+            assumeNonNull(mPopup.getAnchorView());
             mPopup.getAnchorView().removeOnLayoutChangeListener(mAnchorViewLayoutChangeListener);
         }
         if (mOnDismissCallback != null) mOnDismissCallback.run();
@@ -298,7 +305,7 @@
     }
 
     private class NavigationAdapter extends BaseAdapter {
-        private Integer mTopPadding;
+        private @Nullable Integer mTopPadding;
 
         @Override
         public int getCount() {
@@ -321,10 +328,11 @@
             if (convertView == null) {
                 LayoutInflater inflater = LayoutInflater.from(parent.getContext());
                 convertView = inflater.inflate(R.layout.navigation_popup_item, parent, false);
-                viewHolder = new EntryViewHolder();
-                viewHolder.mContainer = convertView;
-                viewHolder.mImageView = convertView.findViewById(R.id.favicon_img);
-                viewHolder.mTextView = convertView.findViewById(R.id.entry_title);
+                viewHolder =
+                        new EntryViewHolder(
+                                /* container= */ convertView,
+                                /* imageView= */ convertView.findViewById(R.id.favicon_img),
+                                /* textView= */ convertView.findViewById(R.id.entry_title));
                 convertView.setTag(viewHolder);
             } else {
                 viewHolder = (EntryViewHolder) convertView.getTag();
@@ -378,6 +386,12 @@
     }
 
     private static class EntryViewHolder {
+        private EntryViewHolder(View container, ImageView imageView, TextView textView) {
+            mContainer = container;
+            mImageView = imageView;
+            mTextView = textView;
+        }
+
         View mContainer;
         ImageView mImageView;
         TextView mTextView;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/OptionalBrowsingModeButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/OptionalBrowsingModeButtonController.java
index bf62b08..036b26e 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/OptionalBrowsingModeButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/OptionalBrowsingModeButtonController.java
@@ -7,6 +7,8 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.optional_button.ButtonData;
@@ -22,10 +24,11 @@
  * mode toolbar.
  */
 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+@NullMarked
 public class OptionalBrowsingModeButtonController {
     private final UserEducationHelper mUserEducationHelper;
     private final Map<ButtonDataProvider, ButtonDataProvider.ButtonDataObserver> mObserverMap;
-    private ButtonDataProvider mCurrentProvider;
+    private @Nullable ButtonDataProvider mCurrentProvider;
     private List<ButtonDataProvider> mButtonDataProviders;
     private final ToolbarLayout mToolbarLayout;
     private final Supplier<Tab> mTabSupplier;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/PhoneCaptureStateToken.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/PhoneCaptureStateToken.java
index c5afd84b..0465a42 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/PhoneCaptureStateToken.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/PhoneCaptureStateToken.java
@@ -9,6 +9,8 @@
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.optional_button.ButtonData;
 import org.chromium.chrome.browser.toolbar.top.ToolbarPhone.VisualState;
 
@@ -19,6 +21,7 @@
  * against new states, to infer if anything important has changed. Especially useful when deciding
  * if a new bitmap capture is warranted.
  */
+@NullMarked
 class PhoneCaptureStateToken {
     private final @ColorInt int mTint;
     private final int mTabCount;
@@ -35,7 +38,7 @@
     public PhoneCaptureStateToken(
             @ColorInt int tint,
             int tabCount,
-            ButtonData optionalButtonData,
+            @Nullable ButtonData optionalButtonData,
             @VisualState int visualState,
             VisibleUrlText visibleUrlText,
             @DrawableRes int securityIcon,
@@ -69,7 +72,7 @@
      * @return The difference.
      */
     public static @ToolbarSnapshotDifference int getAnyDifference(
-            PhoneCaptureStateToken current, PhoneCaptureStateToken next) {
+            @Nullable PhoneCaptureStateToken current, PhoneCaptureStateToken next) {
         assert next != null;
         if (current == null) {
             return ToolbarSnapshotDifference.NULL;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ResourceFactory.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ResourceFactory.java
index 281c3c8d..fc8d94d 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ResourceFactory.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ResourceFactory.java
@@ -9,8 +9,11 @@
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
+import org.chromium.build.annotations.NullMarked;
+
 /** Utility class for creating native resources. */
 @JNINamespace("android")
+@NullMarked
 public class ResourceFactory {
     public static long createToolbarContainerResource(
             Rect toolbarPosition, Rect locationBarPosition, int shadowHeight) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
index 5297dba..f5d8b0a 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.components.browser_ui.widget.BrowserUiListMenuUtils.buildMenuListItem;
 import static org.chromium.ui.listmenu.BasicListMenu.buildMenuDivider;
 
@@ -14,16 +15,18 @@
 import android.widget.PopupWindow;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.incognito.IncognitoUtils;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.MenuBuilderHelper;
 import org.chromium.chrome.browser.toolbar.R;
@@ -45,6 +48,7 @@
  * The main coordinator for the Tab Switcher Action Menu, responsible for creating the popup menu
  * (popup window) in general and building a list of menu items.
  */
+@NullMarked
 public class TabSwitcherActionMenuCoordinator {
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
@@ -130,7 +134,7 @@
     private final Profile mProfile;
 
     // For test.
-    private View mContentView;
+    private @Nullable View mContentView;
 
     /** Construct a coordinator for the given {@link Profile}. */
     TabSwitcherActionMenuCoordinator(
@@ -190,7 +194,7 @@
     }
 
     @VisibleForTesting
-    View getContentView() {
+    @Nullable View getContentView() {
         return mContentView;
     }
 
@@ -274,13 +278,14 @@
     }
 
     private boolean doTabGroupsExist() {
-        @Nullable TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get();
+        TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get();
         if (tabModelSelector != null) {
-            return tabModelSelector
+            TabGroupModelFilter currentTabGroupModelFilter =
+                    tabModelSelector
                             .getTabGroupModelFilterProvider()
-                            .getCurrentTabGroupModelFilter()
-                            .getTabGroupCount()
-                    != 0;
+                            .getCurrentTabGroupModelFilter();
+            assumeNonNull(currentTabGroupModelFilter);
+            return currentTabGroupModelFilter.getTabGroupCount() != 0;
         }
         return false;
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabletCaptureStateToken.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabletCaptureStateToken.java
index ba12178..a98e20a 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabletCaptureStateToken.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabletCaptureStateToken.java
@@ -9,8 +9,9 @@
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
+
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 
 import java.util.Objects;
 
@@ -19,6 +20,7 @@
  * produced by capturing is identical to the bitmap corresponding to the given token. This is used
  * to avoid re-capturing unnecessarily.
  */
+@NullMarked
 class TabletCaptureStateToken {
     private final @Nullable ButtonCaptureStateToken mHomeButtonToken;
     private final @Nullable ButtonCaptureStateToken mBackwardButtonToken;
@@ -33,14 +35,14 @@
     private final int mTabCount;
     private final int mViewWidth;
 
-    private static ButtonCaptureStateToken buttonTokenUseDrawableInstance(
+    private static @Nullable ButtonCaptureStateToken buttonTokenUseDrawableInstance(
             @Nullable ImageButton imageButton) {
         return imageButton == null
                 ? null
                 : new DrawableInstanceButtonCaptureStateToken(imageButton);
     }
 
-    private static ButtonCaptureStateToken buttonTokenWithDrawableRes(
+    private static @Nullable ButtonCaptureStateToken buttonTokenWithDrawableRes(
             @Nullable ImageButton imageButton, @DrawableRes int iconRes) {
         return imageButton == null
                 ? null
@@ -58,7 +60,7 @@
         private final int mLevel;
         private final @ColorInt int mImageTint;
 
-        private ButtonCaptureStateToken(@NonNull ImageButton imageButton) {
+        private ButtonCaptureStateToken(ImageButton imageButton) {
             mVisibility = imageButton.getVisibility();
             mIsEnabled = imageButton.isEnabled();
             mLevel = imageButton.getDrawable() == null ? 0 : imageButton.getDrawable().getLevel();
@@ -92,13 +94,13 @@
     private static class DrawableInstanceButtonCaptureStateToken extends ButtonCaptureStateToken {
         private final Drawable mImageDrawable;
 
-        private DrawableInstanceButtonCaptureStateToken(@NonNull ImageButton imageButton) {
+        private DrawableInstanceButtonCaptureStateToken(ImageButton imageButton) {
             super(imageButton);
             mImageDrawable = imageButton.getDrawable();
         }
 
         @Override
-        public boolean equals(Object o) {
+        public boolean equals(@Nullable Object o) {
             if (this == o) return true;
             if (!(o instanceof DrawableInstanceButtonCaptureStateToken)) return false;
             DrawableInstanceButtonCaptureStateToken that =
@@ -116,13 +118,13 @@
         private final @DrawableRes int mDrawableRes;
 
         private DrawableResButtonCaptureStateToken(
-                @NonNull ImageButton imageButton, @DrawableRes int drawableRes) {
+                ImageButton imageButton, @DrawableRes int drawableRes) {
             super(imageButton);
             mDrawableRes = drawableRes;
         }
 
         @Override
-        public boolean equals(Object o) {
+        public boolean equals(@Nullable Object o) {
             if (this == o) return true;
             if (!(o instanceof DrawableResButtonCaptureStateToken)) return false;
             DrawableResButtonCaptureStateToken that = (DrawableResButtonCaptureStateToken) o;
@@ -159,7 +161,7 @@
         mViewWidth = viewWidth;
     }
 
-    public @ToolbarSnapshotDifference int getAnyDifference(TabletCaptureStateToken that) {
+    public @ToolbarSnapshotDifference int getAnyDifference(@Nullable TabletCaptureStateToken that) {
         if (that == null) {
             return ToolbarSnapshotDifference.NULL;
         } else if (!Objects.equals(mHomeButtonToken, that.mHomeButtonToken)) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButton.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButton.java
index 51f2dc5..d9674c5c 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButton.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButton.java
@@ -8,7 +8,6 @@
 import android.graphics.Canvas;
 import android.util.AttributeSet;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.PluralsRes;
 import androidx.appcompat.widget.TooltipCompat;
 
@@ -16,6 +15,9 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.tab_ui.TabModelDotInfo;
 import org.chromium.chrome.browser.theme.ThemeUtils;
@@ -36,6 +38,7 @@
  * TODO(twellington): Replace with TabSwitcherButtonCoordinator so code can be shared with bottom
  * toolbar.
  */
+@NullMarked
 public class ToggleTabStackButton extends ListMenuButton implements TabSwitcherDrawable.Observer {
     private final Callback<Integer> mTabCountSupplierObserver = this::onUpdateTabCount;
     private final Callback<TabModelDotInfo> mNotificationDotObserver =
@@ -44,7 +47,7 @@
     private ObservableSupplier<Integer> mTabCountSupplier;
     private ObservableSupplier<TabModelDotInfo> mNotificationDotSupplier;
     private Supplier<Boolean> mIsIncognitoSupplier;
-    private @Nullable UserEducationHelper mUserEducationHelper;
+    private UserEducationHelper mUserEducationHelper;
 
     public ToggleTabStackButton(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -90,6 +93,7 @@
      * @param isIncognitoSupplier A supplier used to check for incongito state.
      * @param userEducationHelper Used to show an IPH.
      */
+    @Initializer
     void setSuppliers(
             ObservableSupplier<Integer> tabCountSupplier,
             ObservableSupplier<TabModelDotInfo> notificationDotSupplier,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java
index 38c5463e..7bb4f638 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
@@ -12,8 +14,6 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnLongClickListener;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
@@ -21,6 +21,8 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
@@ -46,24 +48,25 @@
  * TODO(crbug.com/40588354): Finish converting HomeButton to MVC and move more logic into this
  * class.
  */
+@NullMarked
 public class ToggleTabStackButtonCoordinator {
     private final CallbackController mCallbackController = new CallbackController();
     private final Context mContext;
-    @NonNull private ToggleTabStackButton mToggleTabStackButton;
+    private ToggleTabStackButton mToggleTabStackButton;
     private final UserEducationHelper mUserEducationHelper;
     private final Supplier<Boolean> mIsIncognitoSupplier;
     private final OneshotSupplier<Boolean> mPromoShownOneshotSupplier;
     private final CurrentTabObserver mPageLoadObserver;
     private final ObservableSupplier<TabModelSelector> mTabModelSelectorSupplier;
 
-    private LayoutStateProvider mLayoutStateProvider;
-    private LayoutStateObserver mLayoutStateObserver;
+    private @Nullable LayoutStateProvider mLayoutStateProvider;
+    private @Nullable LayoutStateObserver mLayoutStateObserver;
     @VisibleForTesting boolean mIphBeingShown;
     // Non-null when tab declutter is enabled and initWithNative is called.
     private @Nullable ObservableSupplier<Integer> mArchivedTabCountSupplier;
     private @Nullable Runnable mArchivedTabsIphShownCallback;
     private @Nullable Runnable mArchivedTabsIphDismissedCallback;
-    private @Nullable Callback<Integer> mArchivedTabCountObserver = this::maybeShowDeclutterIph;
+    private Callback<Integer> mArchivedTabCountObserver = this::maybeShowDeclutterIph;
     private boolean mAlreadyRequestedDeclutterIph;
 
     /**
@@ -127,8 +130,8 @@
             ObservableSupplier<Integer> tabCountSupplier,
             @Nullable ObservableSupplier<Integer> archivedTabCountSupplier,
             ObservableSupplier<TabModelDotInfo> tabModelNotificationDotSupplier,
-            @NonNull Runnable archivedTabsIphShownCallback,
-            @NonNull Runnable archivedTabsIphDismissedCallback) {
+            Runnable archivedTabsIphShownCallback,
+            Runnable archivedTabsIphDismissedCallback) {
         mToggleTabStackButton.setOnClickListener(onClickListener);
         mToggleTabStackButton.setOnLongClickListener(onLongClickListener);
         mToggleTabStackButton.setSuppliers(
@@ -152,6 +155,7 @@
         mPageLoadObserver.destroy();
 
         if (mLayoutStateProvider != null) {
+            assumeNonNull(mLayoutStateObserver);
             mLayoutStateProvider.removeObserver(mLayoutStateObserver);
             mLayoutStateProvider = null;
             mLayoutStateObserver = null;
@@ -327,6 +331,8 @@
         mAlreadyRequestedDeclutterIph = true;
         HighlightParams params = new HighlightParams(HighlightShape.CIRCLE);
         params.setBoundsRespectPadding(true);
+        assumeNonNull(mArchivedTabsIphShownCallback);
+        assumeNonNull(mArchivedTabsIphDismissedCallback);
         mUserEducationHelper.requestShowIph(
                 new IphCommandBuilder(
                                 mContext.getResources(),
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/Toolbar.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/Toolbar.java
index b741dae..8cf8b0e8ab 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/Toolbar.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/Toolbar.java
@@ -8,17 +8,20 @@
 import android.view.View;
 import android.widget.ProgressBar;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
 
 /**
  * An interface for outside packages to interact with the top toolbar. Other than for testing
- * purposes this interface should be used rather than {@link TopToolbarCoordinator} or
- * {@link ToolbarLayout} and extending classes.
+ * purposes this interface should be used rather than {@link TopToolbarCoordinator} or {@link
+ * ToolbarLayout} and extending classes.
  */
+@NullMarked
 public interface Toolbar {
     /**
-     * Calculates the {@link Rect} that represents the content area of the location bar.  This
-     * rect will be relative to the toolbar.
+     * Calculates the {@link Rect} that represents the content area of the location bar. This rect
+     * will be relative to the toolbar.
+     *
      * @param outRect The Rect that represents the content area of the location bar.
      */
     void getLocationBarContentRect(Rect outRect);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarActionModeCallback.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarActionModeCallback.java
index be2164df..508bf03 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarActionModeCallback.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarActionModeCallback.java
@@ -8,13 +8,18 @@
 import android.view.Menu;
 import android.view.MenuItem;
 
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+
 /** A custom ActionMode.Callback that handles copy, paste selection in omnibox and toolbar. */
+@NullMarked
 public class ToolbarActionModeCallback implements ActionMode.Callback {
     private ActionModeController mActionModeController;
 
     private boolean mMovedToolbar;
 
     /** Sets the {@link #mActionModeController}. */
+    @Initializer
     public void setActionModeController(ActionModeController actionModeController) {
         mActionModeController = actionModeController;
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarColorObserverManager.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarColorObserverManager.java
index 4764d78..bf91235 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarColorObserverManager.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarColorObserverManager.java
@@ -4,11 +4,10 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
-
 import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator.ToolbarColorObserver;
 import org.chromium.ui.util.ColorUtils;
 
@@ -16,6 +15,7 @@
  * A class to receive toolbar color change updates from toolbar components and send the rendering
  * toolbar color to the ToolbarColorObserver.
  */
+@NullMarked
 class ToolbarColorObserverManager implements ToolbarColorObserver {
     private @Nullable ToolbarColorObserver mToolbarColorObserver;
     private @ColorInt int mToolbarColor;
@@ -25,7 +25,7 @@
      *
      * @param toolbarColorObserver The observer to listen to toolbar color change.
      */
-    void setToolbarColorObserver(@NonNull ToolbarColorObserver toolbarColorObserver) {
+    void setToolbarColorObserver(ToolbarColorObserver toolbarColorObserver) {
         mToolbarColorObserver = toolbarColorObserver;
         notifyToolbarColorChanged();
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
index a2ca1d0..5783585 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -23,7 +25,6 @@
 import android.widget.FrameLayout;
 
 import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.coordinatorlayout.widget.CoordinatorLayout;
 import androidx.core.content.res.ResourcesCompat;
@@ -34,6 +35,9 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
@@ -66,6 +70,7 @@
 import java.util.function.BooleanSupplier;
 
 /** Layout for the browser controls (omnibox, menu, tab strip, etc..). */
+@NullMarked
 public class ToolbarControlContainer extends OptimizedFrameLayout
         implements ControlContainer, DesktopWindowStateManager.AppHeaderObserver {
     private boolean mIncognito;
@@ -76,8 +81,8 @@
     private Toolbar mToolbar;
     private ToolbarViewResourceFrameLayout mToolbarContainer;
 
-    private SwipeGestureListener mSwipeGestureListener;
-    private OnDragListener mToolbarContainerDragListener;
+    private @Nullable SwipeGestureListener mSwipeGestureListener;
+    private @Nullable OnDragListener mToolbarContainerDragListener;
 
     private boolean mIsAppInUnfocusedDesktopWindow;
     private final int mToolbarLayoutHeight;
@@ -85,7 +90,7 @@
     private View mToolbarHairline;
     private ViewGroup mToolbarView;
     private boolean mShowLocationBarOnly;
-    private View mLocationBarView;
+    private @Nullable View mLocationBarView;
 
     /**
      * Constructs a new control container.
@@ -148,6 +153,7 @@
     }
 
     @Override
+    @Initializer
     public void initWithToolbar(int toolbarLayoutId) {
         try (TraceEvent te = TraceEvent.scoped("ToolbarControlContainer.initWithToolbar")) {
             mToolbarContainer =
@@ -271,6 +277,7 @@
                         getContext().getResources(),
                         TabUiThemeUtil.getTabResource(),
                         getContext().getTheme());
+        assumeNonNull(backgroundTabImage);
         backgroundTabImage.setTint(
                 TabUiThemeUtil.getTabStripSelectedTabColor(getContext(), incognito));
         LayerDrawable backgroundDrawable =
@@ -313,6 +320,7 @@
      * @param layoutStateProviderSupplier Used to check the current layout type.
      * @param fullscreenManager Used to check whether in fullscreen.
      */
+    @Initializer
     public void setPostInitializationDependencies(
             Toolbar toolbar,
             ViewGroup toolbarView,
@@ -407,7 +415,7 @@
     /** The layout that handles generating the toolbar view resource. */
     // Only publicly visible due to lint warnings.
     public static class ToolbarViewResourceFrameLayout extends ViewResourceFrameLayout {
-        @Nullable private BooleanSupplier mIsMidVisibilityToggle;
+        private BooleanSupplier mIsMidVisibilityToggle;
         private boolean mReadyForBitmapCapture;
 
         public ToolbarViewResourceFrameLayout(Context context, AttributeSet attrs) {
@@ -422,6 +430,7 @@
         /**
          * @see ToolbarViewResourceAdapter#setPostInitializationDependencies.
          */
+        @Initializer
         public void setPostInitializationDependencies(
                 Toolbar toolbar,
                 ObservableSupplier<Integer> constraintsSupplier,
@@ -488,18 +497,17 @@
         private final Callback<Boolean> mOnCompositorInMotionChange =
                 this::onCompositorInMotionChange;
 
-        @Nullable private Toolbar mToolbar;
-        @Nullable private ConstraintsChecker mConstraintsObserver;
-        @Nullable private Supplier<Tab> mTabSupplier;
-        @Nullable private ObservableSupplier<Boolean> mCompositorInMotionSupplier;
+        private Toolbar mToolbar;
+        private ConstraintsChecker mConstraintsObserver;
+        private Supplier<Tab> mTabSupplier;
+        private ObservableSupplier<Boolean> mCompositorInMotionSupplier;
 
-        @Nullable
         private BrowserStateBrowserControlsVisibilityDelegate
                 mBrowserStateBrowserControlsVisibilityDelegate;
 
-        @Nullable private BooleanSupplier mControlContainerIsVisibleSupplier;
-        @Nullable private LayoutStateProvider mLayoutStateProvider;
-        @Nullable private FullscreenManager mFullscreenManager;
+        private BooleanSupplier mControlContainerIsVisibleSupplier;
+        private @Nullable LayoutStateProvider mLayoutStateProvider;
+        private FullscreenManager mFullscreenManager;
 
         private int mControlsToken = TokenHolder.INVALID_TOKEN;
 
@@ -525,6 +533,7 @@
          * @param layoutStateProviderSupplier Used to check the current layout type.
          * @param fullscreenManager Used to check whether in fullscreen.
          */
+        @Initializer
         public void setPostInitializationDependencies(
                 Toolbar toolbar,
                 ObservableSupplier<Integer> constraintsSupplier,
@@ -636,7 +645,8 @@
         }
 
         @Override
-        public void onCaptureStart(Canvas canvas, Rect dirtyRect) {
+        @SuppressWarnings("NullAway")
+        public void onCaptureStart(Canvas canvas, @Nullable Rect dirtyRect) {
             RecordHistogram.recordEnumeratedHistogram(
                     "Android.Toolbar.BitmapCapture",
                     ToolbarCaptureType.TOP,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
index c7f1ee48..67faf22 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -21,8 +21,6 @@
 import androidx.annotation.CallSuper;
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.widget.TooltipCompat;
 
@@ -31,6 +29,9 @@
 import org.chromium.base.lifetime.DestroyChecker;
 import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.omnibox.LocationBar;
@@ -72,6 +73,7 @@
  * interaction that are not from Views inside Toolbar hierarchy all interactions should be done
  * through {@link Toolbar} rather than using this class directly.
  */
+@NullMarked
 public abstract class ToolbarLayout extends FrameLayout
         implements Destroyable, TintObserver, ThemeColorObserver {
     private @Nullable ToolbarColorObserver mToolbarColorObserver;
@@ -85,7 +87,7 @@
     private ToolbarDataProvider mToolbarDataProvider;
     private ToolbarTabController mToolbarTabController;
 
-    @Nullable protected ToolbarProgressBar mProgressBar;
+    protected ToolbarProgressBar mProgressBar;
 
     private boolean mNativeLibraryReady;
     private boolean mUrlHasFocus;
@@ -93,16 +95,17 @@
 
     protected ThemeColorProvider mThemeColorProvider;
     private MenuButtonCoordinator mMenuButtonCoordinator;
-    private AppMenuButtonHelper mAppMenuButtonHelper;
+    private @Nullable AppMenuButtonHelper mAppMenuButtonHelper;
 
     private ToggleTabStackButtonCoordinator mTabSwitcherButtonCoordinator;
 
-    private TopToolbarOverlayCoordinator mOverlayCoordinator;
+    private @Nullable TopToolbarOverlayCoordinator mOverlayCoordinator;
 
-    private BrowserStateBrowserControlsVisibilityDelegate mBrowserControlsVisibilityDelegate;
+    private @Nullable BrowserStateBrowserControlsVisibilityDelegate
+            mBrowserControlsVisibilityDelegate;
     private int mShowBrowserControlsToken = TokenHolder.INVALID_TOKEN;
 
-    private TabStripTransitionCoordinator mTabStripTransitionCoordinator;
+    private @Nullable TabStripTransitionCoordinator mTabStripTransitionCoordinator;
     private int mTabStripTransitionToken = TokenHolder.INVALID_TOKEN;
 
     protected final DestroyChecker mDestroyChecker;
@@ -133,6 +136,7 @@
      * @param trackerSupplier Provides a {@link Tracker} when available.
      */
     @CallSuper
+    @Initializer
     public void initialize(
             ToolbarDataProvider toolbarDataProvider,
             ToolbarTabController tabController,
@@ -176,10 +180,12 @@
 
     // TODO(pnoland, https://crbug.com/865801): Move this from ToolbarLayout to forthcoming
     // BrowsingModeToolbarCoordinator.
+    @Initializer
     public void setLocationBarCoordinator(LocationBarCoordinator locationBarCoordinator) {}
 
     /** Cleans up any code as necessary. */
     @Override
+    @SuppressWarnings("NullAway")
     public void destroy() {
         mDestroyChecker.destroy();
 
@@ -211,14 +217,15 @@
     /**
      * @param toolbarColorObserver The observer that observes toolbar color change.
      */
-    public void setToolbarColorObserver(@NonNull ToolbarColorObserver toolbarColorObserver) {
+    public void setToolbarColorObserver(ToolbarColorObserver toolbarColorObserver) {
         mToolbarColorObserver = toolbarColorObserver;
     }
 
     /**
      * @param themeColorProvider The {@link ThemeColorProvider} used for tinting the toolbar
-     *                           buttons.
+     *     buttons.
      */
+    @Initializer
     void setThemeColorProvider(ThemeColorProvider themeColorProvider) {
         mThemeColorProvider = themeColorProvider;
         mThemeColorProvider.addTintObserver(this);
@@ -228,7 +235,7 @@
     /**
      * @return The tint the toolbar buttons should use.
      */
-    protected ColorStateList getTint() {
+    protected @Nullable ColorStateList getTint() {
         return mThemeColorProvider == null ? mDefaultTint : mThemeColorProvider.getTint();
     }
 
@@ -270,8 +277,8 @@
 
     @Override
     public void onTintChanged(
-            ColorStateList tint,
-            ColorStateList activityFocusTint,
+            @Nullable ColorStateList tint,
+            @Nullable ColorStateList activityFocusTint,
             @BrandedColorScheme int brandedColorScheme) {}
 
     @Override
@@ -285,7 +292,7 @@
      * Set hover tooltip text for buttons shared between phones and tablets. @TODO: Remove and use
      * the method in UiUtils.java instead once JaCoCo issue is resolved.
      */
-    protected void setTooltipText(View button, String text) {
+    protected void setTooltipText(View button, @Nullable String text) {
         if (button != null && VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             TooltipCompat.setTooltipText(button, text);
         }
@@ -314,12 +321,12 @@
                     }
 
                     @Override
-                    public Profile getProfile() {
+                    public @Nullable Profile getProfile() {
                         return null;
                     }
 
                     @Override
-                    public Tab getTab() {
+                    public @Nullable Tab getTab() {
                         return null;
                     }
 
@@ -409,6 +416,7 @@
     }
 
     @Override
+    @Initializer
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
@@ -439,7 +447,7 @@
     /**
      * @return The {@link ProgressBar} this layout uses.
      */
-    protected @Nullable ToolbarProgressBar getProgressBar() {
+    protected ToolbarProgressBar getProgressBar() {
         return mProgressBar;
     }
 
@@ -667,7 +675,7 @@
     /**
      * @return The current View showing in the Tab.
      */
-    View getCurrentTabView() {
+    @Nullable View getCurrentTabView() {
         Tab tab = mToolbarDataProvider.getTab();
         if (tab != null) {
             return tab.getView();
@@ -739,21 +747,21 @@
     /**
      * @return Optional button view.
      */
-    public View getOptionalButtonViewForTesting() {
+    public @Nullable View getOptionalButtonViewForTesting() {
         return null;
     }
 
     /**
      * @return Home button this {@link ToolbarLayout} contains, if any.
      */
-    public ImageView getHomeButton() {
+    public @Nullable ImageView getHomeButton() {
         return null;
     }
 
     /**
      * @return {@link ToggleTabStackButton} this {@link ToolbarLayout} contains.
      */
-    public ToggleTabStackButton getTabSwitcherButton() {
+    public @Nullable ToggleTabStackButton getTabSwitcherButton() {
         return null;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index cb759307..5f0d287 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.ui.accessibility.KeyboardFocusUtil.setFocusOnFirstFocusableDescendant;
 
 import android.animation.Animator;
@@ -37,8 +38,6 @@
 import androidx.annotation.ColorInt;
 import androidx.annotation.DrawableRes;
 import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.content.ContextCompat;
@@ -51,6 +50,11 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.MonotonicNonNull;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.NullUnmarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.NewTabPageDelegate;
@@ -96,6 +100,7 @@
 import java.util.function.BooleanSupplier;
 
 /** Phone specific toolbar implementation. */
+@NullMarked
 public class ToolbarPhone extends ToolbarLayout
         implements OmniboxSuggestionsDropdownScrollListener, ToolbarDataProvider.Observer {
     /** The amount of time transitioning from one theme color to another should take in ms. */
@@ -128,15 +133,15 @@
 
     private @Nullable ObservableSupplier<Integer> mTabCountSupplier;
 
-    private UserEducationHelper mUserEducationHelper;
+    private @Nullable UserEducationHelper mUserEducationHelper;
     protected LocationBarCoordinator mLocationBar;
     private ObservableSupplier<Tracker> mTrackerSupplier;
 
     private ViewGroup mToolbarButtonsContainer;
     // Non-null after inflation occurs.
-    private @NonNull ImageView mHomeButton;
+    private ImageView mHomeButton;
     protected View mUrlActionContainer;
-    private OptionalButtonCoordinator mOptionalButtonCoordinator;
+    private @MonotonicNonNull OptionalButtonCoordinator mOptionalButtonCoordinator;
 
     @ViewDebug.ExportedProperty(category = "chrome")
     protected int mTabSwitcherState;
@@ -160,12 +165,12 @@
      * width of the omnibox is not interpolated linearly from this value. The value will be the
      * maximum of {@link #mUrlFocusChangeFraction} and {@link #mNtpSearchBoxScrollFraction}.
      *
-     * 0.0 == no expansion, 1.0 == fully expanded.
+     * <p>0.0 == no expansion, 1.0 == fully expanded.
      */
     @ViewDebug.ExportedProperty(category = "chrome")
     protected float mUrlExpansionFraction;
 
-    private AnimatorSet mUrlFocusLayoutAnimator;
+    private @Nullable AnimatorSet mUrlFocusLayoutAnimator;
 
     protected boolean mDisableLocationBarRelayout;
     protected boolean mLayoutLocationBarInFocusedMode;
@@ -216,12 +221,12 @@
     private final int mToolbarSidePaddingForNtp;
     private final int mBackgroundHeightIncreaseWhenFocus;
 
-    private ValueAnimator mBrandColorTransitionAnimation;
+    private @Nullable ValueAnimator mBrandColorTransitionAnimation;
     private boolean mBrandColorTransitionActive;
 
     private boolean mIsHomeButtonEnabled;
 
-    private Runnable mLayoutUpdater;
+    private @Nullable Runnable mLayoutUpdater;
 
     /** The vertical inset of the location bar background. */
     private int mLocationBarBackgroundVerticalInset;
@@ -229,8 +234,8 @@
     /** The current color of the location bar. */
     private @ColorInt int mCurrentLocationBarColor;
 
-    private PhoneCaptureStateToken mPhoneCaptureStateToken;
-    private ButtonData mButtonData;
+    private @Nullable PhoneCaptureStateToken mPhoneCaptureStateToken;
+    private @Nullable ButtonData mButtonData;
 
     private @ColorInt int mToolbarBackgroundColorForNtp;
     private @ColorInt int mLocationBarBackgroundColorForNtp;
@@ -340,6 +345,7 @@
     }
 
     @Override
+    @Initializer
     public void initialize(
             ToolbarDataProvider toolbarDataProvider,
             ToolbarTabController tabController,
@@ -349,8 +355,8 @@
             UserEducationHelper userEducationHelper,
             ObservableSupplier<Tracker> trackerSupplier,
             ToolbarProgressBar progressBar,
-            ReloadButtonCoordinator reloadButtonCoordinator,
-            BackButtonCoordinator backButtonCoordinator) {
+            @Nullable ReloadButtonCoordinator reloadButtonCoordinator,
+            @Nullable BackButtonCoordinator backButtonCoordinator) {
         super.initialize(
                 toolbarDataProvider,
                 tabController,
@@ -369,9 +375,14 @@
     }
 
     @Override
+    @Initializer
     public void setLocationBarCoordinator(LocationBarCoordinator locationBarCoordinator) {
         mLocationBar = locationBarCoordinator;
-        initLocationBarBackground();
+        Resources res = getResources();
+        mLocationBarBackgroundVerticalInset =
+                res.getDimensionPixelSize(R.dimen.location_bar_vertical_margin);
+        mLocationBarBackground = createModernLocationBarBackground(getContext());
+        mActiveLocationBarBackground = mLocationBarBackground;
     }
 
     @Override
@@ -391,15 +402,6 @@
         super.destroy();
     }
 
-    /** Initializes the background, padding, margins, etc. for the location bar background. */
-    private void initLocationBarBackground() {
-        Resources res = getResources();
-        mLocationBarBackgroundVerticalInset =
-                res.getDimensionPixelSize(R.dimen.location_bar_vertical_margin);
-        mLocationBarBackground = createModernLocationBarBackground(getContext());
-        mActiveLocationBarBackground = mLocationBarBackground;
-    }
-
     /**
      * @param context The activity {@link Context}.
      * @return The drawable for the modern location bar background.
@@ -409,6 +411,7 @@
                 (GradientDrawable)
                         context.getDrawable(
                                 R.drawable.modern_toolbar_text_box_background_with_primary_color);
+        assumeNonNull(drawable);
         drawable.mutate();
         drawable.setColor(ContextCompat.getColor(context, R.color.toolbar_text_box_bg_color));
         return drawable;
@@ -908,12 +911,12 @@
     }
 
     /**
-     * @return The difference in the location bar width when the optional button is hidden
-     *         rather than showing. This is effectively the width of the optional button with
-     *         some adjustment to account for possible padding differences when the button
-     *         visibility changes.
+     * @return The difference in the location bar width when the optional button is hidden rather
+     *     than showing. This is effectively the width of the optional button with some adjustment
+     *     to account for possible padding differences when the button visibility changes.
      */
     @VisibleForTesting
+    @NullUnmarked
     float getLocationBarWidthOffsetForOptionalButton() {
         float widthChange = mOptionalButtonCoordinator.getViewWidth();
 
@@ -1631,6 +1634,7 @@
         VisibleUrlText visibleUrlText =
                 new VisibleUrlText(
                         urlBarData.displayText, mLocationBar.getOmniboxVisibleTextPrefixHint());
+        assumeNonNull(getTint());
         return new PhoneCaptureStateToken(
                 getTint().getDefaultColor(),
                 mTabCountSupplier == null ? 0 : mTabCountSupplier.get(),
@@ -1638,7 +1642,7 @@
                 mVisualState,
                 visibleUrlText,
                 securityIconResource,
-                ImageViewCompat.getImageTintList(mHomeButton),
+                assumeNonNull(ImageViewCompat.getImageTintList(mHomeButton)),
                 mHomeButton.getVisibility() == View.VISIBLE,
                 getMenuButtonCoordinator().isShowingUpdateBadge(),
                 getToolbarDataProvider().isPaintPreview(),
@@ -1688,8 +1692,8 @@
 
     @Override
     public void onTintChanged(
-            ColorStateList tint,
-            ColorStateList activityFocusTint,
+            @Nullable ColorStateList tint,
+            @Nullable ColorStateList activityFocusTint,
             @BrandedColorScheme int brandedColorScheme) {
         ImageViewCompat.setImageTintList(mHomeButton, tint);
 
@@ -1975,8 +1979,12 @@
             mUrlFocusLayoutAnimator.cancel();
             mUrlFocusLayoutAnimator = null;
         }
-        if (mOptionalButtonAnimationRunning) mOptionalButtonCoordinator.cancelTransition();
+        if (mOptionalButtonAnimationRunning) {
+            assumeNonNull(mOptionalButtonCoordinator);
+            mOptionalButtonCoordinator.cancelTransition();
+        }
         if (hasFocus && mBrandColorTransitionActive) {
+            assumeNonNull(mBrandColorTransitionAnimation);
             mBrandColorTransitionAnimation.cancel();
         }
 
@@ -2125,7 +2133,10 @@
     @Override
     public void onPrimaryColorChanged(boolean shouldAnimate) {
         super.onPrimaryColorChanged(shouldAnimate);
-        if (mBrandColorTransitionActive) mBrandColorTransitionAnimation.end();
+        if (mBrandColorTransitionActive) {
+            assumeNonNull(mBrandColorTransitionAnimation);
+            mBrandColorTransitionAnimation.end();
+        }
 
         final @ColorInt int initialColor = mToolbarBackground.getColor();
         final @ColorInt int finalColor =
@@ -2560,7 +2571,7 @@
             mHomeButton.setOnKeyListener(
                     new KeyboardNavigationListener() {
                         @Override
-                        public View getNextFocusForward() {
+                        public @Nullable View getNextFocusForward() {
                             // If the url_bar is outside the toolbar's bounds, optional button is
                             // the next button to go in order to bypass the url_bar when navigating
                             // forward.
@@ -2582,7 +2593,7 @@
                     .setOnKeyListener(
                             new KeyboardNavigationListener() {
                                 @Override
-                                public View getNextFocusBackward() {
+                                public @Nullable View getNextFocusBackward() {
                                     // If the url_bar is outside the toolbar's bounds and the home
                                     // button is visible, the
                                     // home button is the next button to go in order to bypass the
@@ -2602,7 +2613,8 @@
     }
 
     @Override
-    protected void updateOptionalButton(ButtonData buttonData) {
+    @SuppressWarnings("NullAway")
+    protected void updateOptionalButton(@Nullable ButtonData buttonData) {
         mButtonData = buttonData;
 
         if (mOptionalButtonCoordinator == null) {
@@ -2632,7 +2644,7 @@
     }
 
     @Override
-    public View getOptionalButtonViewForTesting() {
+    public @Nullable View getOptionalButtonViewForTesting() {
         if (mOptionalButtonCoordinator != null) {
             return mOptionalButtonCoordinator.getButtonView();
         }
@@ -2707,7 +2719,7 @@
      * @param toolbarColorObserver The observer that observes toolbar color change.
      */
     @Override
-    public void setToolbarColorObserver(@NonNull ToolbarColorObserver toolbarColorObserver) {
+    public void setToolbarColorObserver(ToolbarColorObserver toolbarColorObserver) {
         super.setToolbarColorObserver(toolbarColorObserver);
         notifyToolbarColorChanged(mToolbarBackground.getColor());
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotDifference.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotDifference.java
index bc5a918..8bcd5b80c 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotDifference.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotDifference.java
@@ -6,6 +6,8 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -39,6 +41,7 @@
     ToolbarSnapshotDifference.NUM_ENTRIES
 })
 @Retention(RetentionPolicy.SOURCE)
+@NullMarked
 public @interface ToolbarSnapshotDifference {
     int NONE = 0;
     int NULL = 1;
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 ba7e15d8..0e6da415 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
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import static org.chromium.build.NullUtil.assertNonNull;
 import static org.chromium.ui.accessibility.KeyboardFocusUtil.setFocusOnFirstFocusableDescendant;
 
 import android.animation.Animator;
@@ -33,6 +34,9 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
@@ -66,6 +70,7 @@
 
 /** The Toolbar object for Tablet screens. */
 @SuppressLint("Instantiatable")
+@NullMarked
 public class ToolbarTablet extends ToolbarLayout implements OnClickListener {
     private static final int ICON_FADE_IN_ANIMATION_DELAY_MS = 75;
     private static final int ICON_FADE_ANIMATION_DURATION_MS = 150;
@@ -76,14 +81,14 @@
     private ImageButton mReloadButton;
     private ImageButton mBookmarkButton;
     private ImageButton mSaveOfflineButton;
-    private View mIncognitoIndicator;
+    private @Nullable View mIncognitoIndicator;
 
     private boolean mIsInTabSwitcherMode;
     private boolean mToolbarButtonsVisible;
-    private ImageButton mOptionalButton;
+    private @Nullable ImageButton mOptionalButton;
     private boolean mOptionalButtonUsesTint;
 
-    private NavigationPopup mNavigationPopup;
+    private @Nullable NavigationPopup mNavigationPopup;
 
     private Boolean mIsIncognitoBranded;
     private LocationBarCoordinator mLocationBar;
@@ -93,10 +98,10 @@
     private final int mStartPaddingWithButtons;
     private final int mStartPaddingWithoutButtons;
     private boolean mShouldAnimateButtonVisibilityChange;
-    private AnimatorSet mButtonVisibilityAnimators;
+    private @Nullable AnimatorSet mButtonVisibilityAnimators;
     private HistoryDelegate mHistoryDelegate;
-    private ObservableSupplier<Integer> mTabCountSupplier;
-    private TabletCaptureStateToken mLastCaptureStateToken;
+    private @Nullable ObservableSupplier<Integer> mTabCountSupplier;
+    private @Nullable TabletCaptureStateToken mLastCaptureStateToken;
     private @DrawableRes int mBookmarkButtonImageRes;
 
     /**
@@ -132,6 +137,7 @@
     }
 
     @Override
+    @Initializer
     public void setLocationBarCoordinator(LocationBarCoordinator locationBarCoordinator) {
         mLocationBar = locationBarCoordinator;
         final @ColorInt int color = SemanticColorUtils.getColorSurfaceContainer(getContext());
@@ -274,8 +280,8 @@
 
     @Override
     public void onTintChanged(
-            ColorStateList tint,
-            ColorStateList activityFocusTint,
+            @Nullable ColorStateList tint,
+            @Nullable ColorStateList activityFocusTint,
             @BrandedColorScheme int brandedColorScheme) {
         ImageViewCompat.setImageTintList(mHomeButton, activityFocusTint);
         ImageViewCompat.setImageTintList(mForwardButton, activityFocusTint);
@@ -396,6 +402,7 @@
     }
 
     @Override
+    @Initializer
     public void initialize(
             ToolbarDataProvider toolbarDataProvider,
             ToolbarTabController tabController,
@@ -405,8 +412,8 @@
             UserEducationHelper userEducationHelper,
             ObservableSupplier<Tracker> trackerSupplier,
             ToolbarProgressBar progressBar,
-            ReloadButtonCoordinator reloadButtonCoordinator,
-            BackButtonCoordinator backButtonCoordinator) {
+            @Nullable ReloadButtonCoordinator reloadButtonCoordinator,
+            @Nullable BackButtonCoordinator backButtonCoordinator) {
         super.initialize(
                 toolbarDataProvider,
                 tabController,
@@ -419,8 +426,8 @@
                 reloadButtonCoordinator,
                 backButtonCoordinator);
         mHistoryDelegate = historyDelegate;
-        mReloadButtonCoordinator = reloadButtonCoordinator;
-        mBackButtonCoordinator = backButtonCoordinator;
+        mReloadButtonCoordinator = assertNonNull(reloadButtonCoordinator);
+        mBackButtonCoordinator = assertNonNull(backButtonCoordinator);
         menuButtonCoordinator.setVisibility(true);
     }
 
@@ -563,7 +570,7 @@
     }
 
     @Override
-    public View getOptionalButtonViewForTesting() {
+    public @Nullable View getOptionalButtonViewForTesting() {
         return mOptionalButton;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
index 73ebc53..9177d79 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -13,14 +13,14 @@
 import android.widget.ImageButton;
 
 import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneShotCallback;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.device.DeviceClassManager;
@@ -64,6 +64,7 @@
 import java.util.List;
 
 /** A coordinator for the top toolbar component. */
+@NullMarked
 public class TopToolbarCoordinator implements Toolbar {
 
     /** Observes toolbar URL expansion progress change. */
@@ -89,7 +90,7 @@
     private MenuButtonCoordinator mMenuButtonCoordinator;
     private @Nullable ReloadButtonCoordinator mReloadButtonCoordinator;
     private @Nullable final BackButtonCoordinator mBackButtonCoordinator;
-    private ObservableSupplier<AppMenuButtonHelper> mAppMenuButtonHelperSupplier;
+    private @Nullable ObservableSupplier<AppMenuButtonHelper> mAppMenuButtonHelperSupplier;
     private ObservableSupplier<TabModelSelector> mTabModelSelectorSupplier;
 
     /** Null until {@link #initializeWithNative} is called. */
@@ -97,7 +98,7 @@
 
     private ToolbarControlContainer mControlContainer;
     private Supplier<ResourceManager> mResourceManagerSupplier;
-    private TopToolbarOverlayCoordinator mOverlayCoordinator;
+    private @Nullable TopToolbarOverlayCoordinator mOverlayCoordinator;
 
     /**
      * The observer manager will receive all types of toolbar color change updates from toolbar
@@ -105,8 +106,8 @@
      */
     private ToolbarColorObserverManager mToolbarColorObserverManager;
 
-    private IncognitoStateProvider mIncognitoStateProvider;
-    private IncognitoStateObserver mIncognitoStateObserver;
+    private @Nullable IncognitoStateProvider mIncognitoStateProvider;
+    private @Nullable IncognitoStateObserver mIncognitoStateObserver;
 
     private TabObscuringHandler mTabObscuringHandler;
     private @Nullable DesktopWindowStateManager mDesktopWindowStateManager;
@@ -211,10 +212,8 @@
                             ignoreCache -> {
                                 var omniboxStub = getLocationBar().getOmniboxStub();
                                 if (omniboxStub != null) {
-                                    getLocationBar()
-                                            .getOmniboxStub()
-                                            .setUrlBarFocus(
-                                                    false, null, OmniboxFocusReason.UNFOCUS);
+                                    omniboxStub.setUrlBarFocus(
+                                            false, null, OmniboxFocusReason.UNFOCUS);
                                 }
                                 tabController.stopOrReloadCurrentTab(ignoreCache);
                             },
@@ -357,7 +356,7 @@
     /**
      * @param toolbarColorObserver The observer that observes toolbar color change.
      */
-    public void setToolbarColorObserver(@NonNull ToolbarColorObserver toolbarColorObserver) {
+    public void setToolbarColorObserver(ToolbarColorObserver toolbarColorObserver) {
         mToolbarColorObserverManager.setToolbarColorObserver(toolbarColorObserver);
     }
 
@@ -388,6 +387,7 @@
     }
 
     /** Cleans up any code as necessary. */
+    @SuppressWarnings("NullAway")
     public void destroy() {
         if (mOverlayCoordinator != null) {
             mOverlayCoordinator.destroy();
@@ -443,11 +443,10 @@
     /**
      * @return The wrapper for the browsing mode toolbar's menu button.
      */
-    public MenuButton getMenuButtonWrapper() {
+    public @Nullable MenuButton getMenuButtonWrapper() {
         return mMenuButtonCoordinator.getMenuButton();
     }
 
-    @Nullable
     @Override
     public ToolbarProgressBar getProgressBar() {
         return mToolbarLayout.getProgressBar();
@@ -738,7 +737,7 @@
     }
 
     /** Returns the {@link OptionalBrowsingModeButtonController}. */
-    public OptionalBrowsingModeButtonController getOptionalButtonControllerForTesting() {
+    public @Nullable OptionalBrowsingModeButtonController getOptionalButtonControllerForTesting() {
         return mOptionalButtonController;
     }
 
@@ -748,7 +747,7 @@
     }
 
     /** Returns the {@link TabStripTransitionCoordinator}. */
-    public TabStripTransitionCoordinator getTabStripTransitionCoordinator() {
+    public @Nullable TabStripTransitionCoordinator getTabStripTransitionCoordinator() {
         return mTabStripTransitionCoordinator;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
index cf1d3599..76e769f5 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayCoordinator.java
@@ -10,6 +10,8 @@
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.CompositorModelChangeProcessor;
@@ -28,6 +30,7 @@
 import java.util.List;
 
 /** The public interface for the top toolbar texture component. */
+@NullMarked
 public class TopToolbarOverlayCoordinator implements SceneOverlay {
     /** The view state for this overlay. */
     private final PropertyModel mModel;
@@ -139,7 +142,7 @@
     }
 
     @Override
-    public EventFilter getEventFilter() {
+    public @Nullable EventFilter getEventFilter() {
         return null;
     }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
index a4c57ac..115dc14 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediator.java
@@ -12,6 +12,8 @@
 import org.chromium.base.Callback;
 import org.chromium.base.ResettersForTesting;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.cc.input.OffsetTag;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsOffsetTagsInfo;
@@ -32,11 +34,12 @@
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** The business logic for controlling the top toolbar's cc texture. */
+@NullMarked
 public class TopToolbarOverlayMediator {
     // Forced testing params.
-    private static Boolean sIsTabletForTesting;
-    private static Integer sToolbarBackgroundColorForTesting;
-    private static Integer sUrlBarColorForTesting;
+    private static @Nullable Boolean sIsTabletForTesting;
+    private static @Nullable Integer sToolbarBackgroundColorForTesting;
+    private static @Nullable Integer sUrlBarColorForTesting;
 
     /** An Android Context. */
     private final Context mContext;
@@ -85,8 +88,8 @@
     private ObservableSupplier<Tab> mTabSupplier;
     private float mViewportHeight;
 
-    private OffsetTag mTopControlsOffsetTag;
-    private OffsetTag mBottomControlsOffsetTag;
+    private @Nullable OffsetTag mTopControlsOffsetTag;
+    private @Nullable OffsetTag mBottomControlsOffsetTag;
     private @ControlsPosition int mControlsPosition;
 
     TopToolbarOverlayMediator(
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
index 8f45637..7a4b769 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayProperties.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.toolbar.top;
 
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.cc.input.OffsetTag;
 import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar.DrawingInfo;
 import org.chromium.ui.modelutil.PropertyKey;
@@ -14,6 +15,7 @@
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 /** Properties associated with the top toolbar's composited layer. */
+@NullMarked
 public class TopToolbarOverlayProperties {
     /** Whether the URL should be hidden when rendered. */
     public static final WritableBooleanPropertyKey ANONYMIZE = new WritableBooleanPropertyKey();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
index 0cdc7503..5637ebf 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarSceneLayer.java
@@ -8,6 +8,8 @@
 import org.jni_zero.NativeMethods;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.cc.input.OffsetTag;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer;
@@ -19,6 +21,7 @@
 
 /** A SceneLayer to render the top toolbar. This is the "view" piece of the top toolbar overlay. */
 @JNINamespace("android")
+@NullMarked
 class TopToolbarSceneLayer extends SceneOverlayLayer {
     /** Pointer to native TopToolbarSceneLayer. */
     private long mNativePtr;
@@ -122,7 +125,7 @@
                 boolean showShadow,
                 boolean visible,
                 boolean anonymize,
-                OffsetTag offsetTag);
+                @Nullable OffsetTag offsetTag);
 
         void updateProgressBar(
                 long nativeTopToolbarSceneLayer,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ViewShiftingActionBarDelegate.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ViewShiftingActionBarDelegate.java
index b0a867b..35d3e55 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ViewShiftingActionBarDelegate.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ViewShiftingActionBarDelegate.java
@@ -9,9 +9,12 @@
 
 import androidx.appcompat.app.ActionBar;
 
+import org.chromium.build.annotations.NullMarked;
+
 /**
  * An {@link ActionModeController.ActionBarDelegate} that shifts a view as the action bar appears.
  */
+@NullMarked
 public class ViewShiftingActionBarDelegate implements ActionModeController.ActionBarDelegate {
     /** The action bar which this delegate works for. */
     private final ActionBar mActionBar;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/VisibleUrlText.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/VisibleUrlText.java
index 39ca019..18266d6 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/VisibleUrlText.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/VisibleUrlText.java
@@ -6,10 +6,10 @@
 
 import android.text.TextUtils;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 
 /**
@@ -18,11 +18,12 @@
  * upon. This means callers need to be able to tolerate false negatives. Typically fine for uses
  * such as performance optimizations where this failure state is just an inefficiency.
  */
+@NullMarked
 public class VisibleUrlText {
-    private final @NonNull CharSequence mUrlText;
+    private final CharSequence mUrlText;
     private final @Nullable CharSequence mVisibleTextPrefixHint;
 
-    public VisibleUrlText(@NonNull CharSequence urlText, @NonNull CharSequence prefixHint) {
+    public VisibleUrlText(CharSequence urlText, @Nullable CharSequence prefixHint) {
         mUrlText = urlText;
         boolean isPrefixValid = isValidVisibleTextPrefixHint(urlText, prefixHint);
         mVisibleTextPrefixHint = isPrefixValid ? prefixHint : null;
@@ -72,12 +73,14 @@
 
     /**
      * Determines the validity of the hint text given the passed in full text.
+     *
      * @param fullText The full text that should start with the hint.
      * @param hintText The hint text to be checked.
      * @return Whether the full text starts with the specified hint text.
      */
     @VisibleForTesting
-    static boolean isValidVisibleTextPrefixHint(CharSequence fullText, CharSequence hintText) {
+    static boolean isValidVisibleTextPrefixHint(
+            CharSequence fullText, @Nullable CharSequence hintText) {
         if (fullText == null || TextUtils.isEmpty(hintText)) return false;
         if (hintText.length() > fullText.length()) return false;
         return TextUtils.indexOf(fullText, hintText, 0, hintText.length()) == 0;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/FadeTransitionHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/FadeTransitionHandler.java
index 0f16c8d..2fc09f6 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/FadeTransitionHandler.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/FadeTransitionHandler.java
@@ -8,6 +8,7 @@
 
 import org.chromium.base.CallbackController;
 import org.chromium.base.supplier.OneshotSupplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.toolbar.top.tab_strip.TabStripTransitionCoordinator.TabStripTransitionDelegate;
 import org.chromium.ui.base.ViewUtils;
@@ -16,6 +17,7 @@
  * Owned and used by {@link TabStripTransitionCoordinator} to manage showing / hiding the tab strip
  * by an in-place fade transition facilitated by a scrim update.
  */
+@NullMarked
 class FadeTransitionHandler {
     // Minimum width (in dp) of the tab strip for it to be shown.
     // 284 = 2 * minTabWidth(108) - tabOverlap(28) + newTabButton (48) + modelSelectorButton(48).
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/HeightTransitionHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/HeightTransitionHandler.java
index cd73bd9db..a536af58 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/HeightTransitionHandler.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/HeightTransitionHandler.java
@@ -4,19 +4,20 @@
 
 package org.chromium.chrome.browser.toolbar.top.tab_strip;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.os.Handler;
 import android.util.DisplayMetrics;
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
 import org.chromium.base.CallbackController;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.OneshotSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider.Observer;
@@ -38,6 +39,7 @@
  * into / exit from desktop windowing mode that warrants the strip height to be updated to include /
  * exclude a reserved strip top padding.
  */
+@NullMarked
 class HeightTransitionHandler {
     private static final String TAG = "DTCStripTransition";
 
@@ -67,7 +69,7 @@
 
     private int mTabObscureToken = TokenHolder.INVALID_TOKEN;
     private final TabObscuringHandler mTabObscuringHandler;
-    private TabObscuringHandler.Observer mTabObscuringHandlerObserver;
+    private TabObscuringHandler.@Nullable Observer mTabObscuringHandlerObserver;
 
     private final OneshotSupplier<TabStripTransitionDelegate> mTabStripTransitionDelegateSupplier;
 
@@ -93,8 +95,8 @@
 
     private boolean mIsDestroyed;
 
-    private @Nullable BrowserControlsStateProvider.Observer mTransitionKickoffObserver;
-    private @Nullable BrowserControlsStateProvider.Observer mTransitionFinishedObserver;
+    private BrowserControlsStateProvider.@Nullable Observer mTransitionKickoffObserver;
+    private BrowserControlsStateProvider.@Nullable Observer mTransitionFinishedObserver;
 
     private boolean mForceUpdateHeight;
     private boolean mUpdateStripVisibility;
@@ -119,8 +121,8 @@
             ControlContainer controlContainer,
             View toolbarLayout,
             int tabStripHeightFromResource,
-            @NonNull CallbackController callbackController,
-            @NonNull Handler handler,
+            CallbackController callbackController,
+            Handler handler,
             TabObscuringHandler tabObscuringHandler,
             OneshotSupplier<TabStripTransitionDelegate> tabStripTransitionDelegateSupplier) {
         mBrowserControlsVisibilityManager = browserControlsVisibilityManager;
@@ -371,9 +373,9 @@
         // For cases where transition is finished in sequence during #onTransitionRequested (e.g.
         // browser control's visibility is under constraint), we'll call updateTabStripHeightImpl
         // to update the margin for the views.
-        boolean browserControlsHasConstraint =
-                mBrowserControlsVisibilityManager.getBrowserVisibilityDelegate().get()
-                        != BrowserControlsState.BOTH;
+        Integer visibility = mBrowserControlsVisibilityManager.getBrowserVisibilityDelegate().get();
+        assumeNonNull(visibility);
+        boolean browserControlsHasConstraint = visibility != BrowserControlsState.BOTH;
 
         if (javaAnimationInProgress || browserControlsHasConstraint) {
             updateTabStripHeightImpl(newHeight);
@@ -513,6 +515,7 @@
     }
 
     private void notifyTransitionFinished(boolean measureControlContainer) {
+        assumeNonNull(mTransitionFinishedObserver);
         mBrowserControlsVisibilityManager.removeObserver(mTransitionFinishedObserver);
         mTransitionFinishedObserver = null;
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/StripVisibilityState.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/StripVisibilityState.java
index 14dda8c..83a44973 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/StripVisibilityState.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/StripVisibilityState.java
@@ -6,6 +6,8 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.build.annotations.NullMarked;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -22,6 +24,7 @@
     StripVisibilityState.HIDDEN_BY_HEIGHT_TRANSITION,
     StripVisibilityState.HIDDEN_BY_FADE,
 })
+@NullMarked
 public @interface StripVisibilityState {
     /** Strip is visible. */
     int VISIBLE = 0;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/TabStripTransitionCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/TabStripTransitionCoordinator.java
index df8f10a..d4becda 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/TabStripTransitionCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/tab_strip/TabStripTransitionCoordinator.java
@@ -12,13 +12,13 @@
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.CallbackController;
 import org.chromium.base.ResettersForTesting;
 import org.chromium.base.supplier.OneshotSupplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager;
 import org.chromium.chrome.browser.tab.TabObscuringHandler;
 import org.chromium.chrome.browser.toolbar.ControlContainer;
@@ -30,8 +30,9 @@
 import org.chromium.components.browser_ui.desktop_windowing.DesktopWindowStateManager.AppHeaderObserver;
 
 /** Class used to manage tab strip visibility and height updates. */
+@NullMarked
 public class TabStripTransitionCoordinator implements ComponentCallbacks, AppHeaderObserver {
-    static Integer sHeightTransitionThresholdForTesting;
+    static @Nullable Integer sHeightTransitionThresholdForTesting;
 
     // Delay to kickoff the transition to avoid frame drops while application is too busy when the
     // configuration changed.
@@ -101,7 +102,7 @@
     private boolean mForceUpdateHeight;
     private boolean mForceFadeInStrip;
 
-    private OnLayoutChangeListener mOnLayoutChangedListener;
+    private @Nullable OnLayoutChangeListener mOnLayoutChangedListener;
     private @Nullable Runnable mLayoutTransitionTask;
 
     // TODO (crbug.com/345849359): Create a base handler class to hold common members.
@@ -130,9 +131,7 @@
             int tabStripHeightFromResource,
             TabObscuringHandler tabObscuringHandler,
             @Nullable DesktopWindowStateManager desktopWindowStateManager,
-            @NonNull
-                    OneshotSupplier<TabStripTransitionDelegate>
-                            tabStripTransitionDelegateSupplier) {
+            OneshotSupplier<TabStripTransitionDelegate> tabStripTransitionDelegateSupplier) {
         mControlContainer = controlContainer;
         mTabStripHeightFromResource = tabStripHeightFromResource;
         mDesktopWindowStateManager = desktopWindowStateManager;
@@ -182,7 +181,7 @@
     // ComponentCallbacks implementation.
 
     @Override
-    public void onConfigurationChanged(@NonNull Configuration newConfig) {
+    public void onConfigurationChanged(Configuration newConfig) {
         updateTabStripTransitionThreshold();
     }
 
diff --git a/chrome/browser/ui/ash/BUILD.gn b/chrome/browser/ui/ash/BUILD.gn
index 29f5c7c6..51adf5a 100644
--- a/chrome/browser/ui/ash/BUILD.gn
+++ b/chrome/browser/ui/ash/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import("//build/chromeos/crosier_tests.gni")
-import("//chromeos/ash/components/assistant/assistant.gni")
 
 assert(is_chromeos)
 
@@ -116,10 +115,6 @@
     "//chrome/browser/ui/ash/web_view:browser_tests",
     "//chrome/browser/ui/ash/wm:browser_tests",
   ]
-
-  if (enable_assistant_integration_tests) {
-    deps += [ "//chrome/browser/ui/ash/assistant:browser_tests" ]
-  }
 }
 
 if (is_chromeos_device) {
diff --git a/chrome/browser/ui/ash/assistant/BUILD.gn b/chrome/browser/ui/ash/assistant/BUILD.gn
index 5889d42b..0fbdeae 100644
--- a/chrome/browser/ui/ash/assistant/BUILD.gn
+++ b/chrome/browser/ui/ash/assistant/BUILD.gn
@@ -97,70 +97,3 @@
     "//testing/gtest",
   ]
 }
-
-if (enable_assistant_integration_tests) {
-  static_library("browser_test_support") {
-    testonly = true
-
-    sources = [
-      "assistant_test_mixin.cc",
-      "assistant_test_mixin.h",
-    ]
-
-    deps = [
-      "//ash:test_support",
-      "//ash/assistant/model",
-      "//ash/assistant/ui",
-      "//ash/assistant/ui:constants",
-      "//ash/constants",
-      "//ash/public/cpp",
-      "//base",
-      "//base/test:test_support",
-      "//chrome/browser",
-      "//chrome/browser/ash/login/test:test_support",
-      "//chrome/browser/ui",
-      "//chrome/browser/ui/ash/assistant/test_support",
-      "//chrome/test:test_support_ui",
-      "//chromeos/ash/components/login/auth/public:authpublic",
-      "//components/account_id",
-      "//components/language/core/browser",
-      "//google_apis",
-      "//net:test_support",
-      "//ui/events:test_support",
-      "//ui/views",
-    ]
-  }
-
-  source_set("browser_tests") {
-    testonly = true
-
-    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-
-    sources = [
-      "assistant_browsertest.cc",
-      "assistant_timers_browsertest.cc",
-    ]
-
-    deps = [
-      ":assistant",
-      ":browser_test_support",
-      "//ash/assistant/model",
-      "//ash/assistant/ui",
-      "//ash/assistant/ui",
-      "//ash/assistant/ui:constants",
-      "//ash/public/cpp:test_support",
-      "//base",
-      "//base/test:test_support",
-      "//chrome/browser/ui/ash/assistant/test_support",
-      "//chrome/test:test_support",
-      "//chromeos/ash/components/assistant/test_support",
-      "//chromeos/ash/components/audio",
-      "//chromeos/ash/services/assistant:lib",
-      "//chromeos/ash/services/assistant/public/cpp",
-      "//chromeos/dbus/power:power_manager_proto",
-      "//components/language/core/browser",
-      "//content/test:test_support",
-      "//ui/events:test_support",
-    ]
-  }
-}
diff --git a/chrome/browser/ui/ash/assistant/assistant_browser_tests.md b/chrome/browser/ui/ash/assistant/assistant_browser_tests.md
deleted file mode 100644
index be816e20..0000000
--- a/chrome/browser/ui/ash/assistant/assistant_browser_tests.md
+++ /dev/null
@@ -1,158 +0,0 @@
-# Assistant Browser Tests
-
-## Introduction
-
-This documentation concerns all Assistant browser/integration test which use
-`AssistantTestMixin` or any derived class.
-
-All these tests run the real LibAssistant code, and use a
-[FakeS3Server](go/fake-s3-for-libassistant) to intercept and replay the
-communication between LibAssistant and the cloud.  This allows these tests to
-run in the CQ, without requiring any network connectivity.
-
-## Adding a new test
-
-To add a new integration test, your test fixture must inherit from
-`MixinBasedInProcessBrowserTest` and must contain `AssistantTestMixin` as a
-private variable:
-
-    #include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
-    #include "chrome/test/base/mixin_based_in_process_browser_test.h"
-
-    class MyBrowserTest : public MixinBasedInProcessBrowserTest {
-     public:
-      MyBrowserTest() = default;
-      ~MyBrowserTest() override = default;
-
-      AssistantTestMixin* tester() { return &tester_; }
-
-     private:
-      AssistantTestMixin tester_{&mixin_host_, this,
-                                 embedded_test_server(),
-                                 FakeS3Mode::kReplay};
-
-    };
-
-Tests can use API provided by `AssistantTextMixin` to interact with the
-Assistant UI.  Look in `chrome/browser/ui/ash/assistant/assistant_test_mixin.h`
-to see all the available methods.
-
-Each test *must* start by starting the Assistant service and waiting for it to
-signal it's ready.
-That is done by calling `tester()->StartAssistantAndWaitForReady()`.
-
-    IN_PROC_BROWSER_TEST_F(MyBrowserTest, MyVeryFirstTest) {
-      tester()->StartAssistantAndWaitForReady();
-
-      // Your test code comes here.
-    }
-
-## Using the fake S3 server
-
-The fake S3 server can run in 3 different modes, all of which you'll need to
-use while adding new tests.
-
-You'll start by using the [_proxy_ mode](#in-proxy-mode) while developing a new
-test; This simply forwards all requests to a real S3 server.
-
-When you're ready to commit you'll switch to [_record_ mode](#in-record-mode)
-in order to record the interaction between LibAssistant and the S3 server.
-
-Afterwards you'll switch to [_replay_ mode](#in-replay-mode); In this mode the
-fake S3 server will replay the recorded interactions. This allows the CQ to run
-the tests without once requiring network connectivity to contact the real S3
-server.
-
-## Running the tests
-
-### In proxy mode
-
-In this mode the fake S3 server works as a simple proxy, forwarding all
-LibAssistant requests to the real S3 server (and proxying the responses back).
-
-As such, you will have to:
-
-1. Tell the fake S3 server to use this mode.
-2. Generate a real Gaia authentication token for the communication with the real S3 server.
-
-The first part can be achieved by passing `|FakeS3Mode::kProxy|` as the final
-argument to the constructor of the `|AssistantTextMixin|` instance in your test
-fixture.
-
-    // in your test fixture
-    private:
-      AssistantTestMixin tester_{&mixin_host_, this, embedded_test_server(),
-                                 FakeS3Mode::kProxy};
-
-The second part is achieved by running your tests through the wrapper script
-`chromeos/assistant/internal/test_support/run_with_access_token.py`.
-
-Start by opening a terminal in your `chromium/src` directory and then:
-
-    # First compile the browser_tests target
-    autoninja -C out/Default browser_tests
-    # Then run it (change the --gtest_filter args to the filter you need)
-    chromeos/assistant/internal/test_support/run_with_access_token.py out/Default/browser_tests --gtest_filter="AssistantBrowserTest.*"
-
-Alternatively you can also store the Gaia token you'd like to use in the environmental variable `TOKEN`:
-
-    export TOKEN="the.gaia.token.string"
-    out/Default/browser_tests --gtest_filter="AssistantBrowserTest.*"
-
-### In record mode
-
-In this mode the fake S3 server will again work as a proxy, but it will also
-store a recording of all the communications in a file called
-
-    chromeos/assistant/internal/test_data/<testfixture_testname>.fake_s3.proto
-
-A separate file is created for each test.
-
-You will need to run once in *record* mode when your test is ready to be
-committed.
-
-To do this, use the same steps described [above](#in-proxy-mode) but replace
-`|FakeS3Mode:kProxy|` with `|FakeS3Mode::kRecord|`.
-
-Note that these `.fake_s3.proto` files will need to be committed before you can
-commit your changes. See [here](#committing-your-tests) for more information.
-
-### In replay mode
-
-In this mode all S3 requests are handled by replaying the responses stored
-while running in _record_ mode.
-
-As this no longer contacts the real S3 server it does not need a Gaia token,
-so you no longer needs to use the `run_with_access_token.py` script.
-
-All you need to do is pass `|FakeS3Mode::kReplay|` as the final argument
-to the constructor of the `|AssistantTextMixin|` instance in your test fixture.
-
-    // in your test fixture
-    private:
-      AssistantTestMixin tester_{&mixin_host_, this, embedded_test_server(),
-                                 FakeS3Mode::kReplay};
-
-This is the mode the CQ runs in, and as such you must **make sure you've enabled this mode before pushing your CL!**
-
-## Removing/Renaming a test
-
-When a test is removed you should take care to remove the stale
-
-    chromeos/assistant/internal/test_data/<testfixture_testname>.fake_s3.proto
-
-file.
-
-Conversively, when a test is renamed you should remove the old `.fake_s3.proto`
-file and use [_record_ mode](#in-record-mode) to generate a new proto file.
-
-## Committing your tests
-
-Committing the tests has to be done in multiple steps:
-
-1. Create an internal CL to add the new files in
-   `chromeos/assistant/internal/test_data`.
-2. Uprev this CL.
-3. Create a CL for your browsertest changes
-4. (Optionally): If you deleted tests, create an internal CL to remove their `.fake_s3.proto` files from `chromeos/assistant/internal/test_data`.
-
diff --git a/chrome/browser/ui/ash/assistant/assistant_browsertest.cc b/chrome/browser/ui/ash/assistant/assistant_browsertest.cc
deleted file mode 100644
index 431ecde..0000000
--- a/chrome/browser/ui/ash/assistant/assistant_browsertest.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/public/cpp/test/app_list_test_api.h"
-#include "base/command_line.h"
-#include "base/run_loop.h"
-#include "base/test/bind.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_run_loop_timeout.h"
-#include "base/time/time.h"
-#include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chromeos/ash/components/assistant/test_support/expect_utils.h"
-#include "chromeos/ash/components/audio/cras_audio_handler.h"
-#include "chromeos/ash/services/assistant/public/cpp/features.h"
-#include "chromeos/ash/services/assistant/public/cpp/switches.h"
-#include "chromeos/ash/services/assistant/service.h"
-#include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "content/public/test/browser_test.h"
-#include "sandbox/policy/switches.h"
-
-namespace ash::assistant {
-
-namespace {
-
-using test::ExpectResult;
-
-// Please remember to set auth token when running in |kProxy| mode.
-constexpr auto kMode = FakeS3Mode::kReplay;
-// Update this when you introduce breaking changes to existing tests.
-constexpr int kVersion = 1;
-
-constexpr int kStartBrightnessPercent = 50;
-
-inline constexpr char kDlcInstallResultHistogram[] =
-    "Assistant.Libassistant.DlcInstallResult";
-
-inline constexpr char kDlcLoadStatusHistogram[] =
-    "Assistant.Libassistant.DlcLoadStatus";
-
-// Ensures that |value_| is within the range {min_, max_}. If it isn't, this
-// will print a nice error message.
-#define EXPECT_WITHIN_RANGE(min_, value_, max_)                               \
-  ({                                                                          \
-    EXPECT_TRUE(min_ <= value_ && value_ <= max_)                             \
-        << "Expected " << value_ << " to be within the range " << "{" << min_ \
-        << ", " << max_ << "}.";                                              \
-  })
-
-}  // namespace
-
-// All tests are disabled because LibAssistant V2 binary does not run on Linux
-// bot. To run the tests on gLinux, please add
-// `--gtest_also_run_disabled_tests`.
-class DISABLED_AssistantBrowserTest : public MixinBasedInProcessBrowserTest,
-                                      public testing::WithParamInterface<bool> {
- public:
-  DISABLED_AssistantBrowserTest()
-      : DISABLED_AssistantBrowserTest(/*disable_sandbox=*/true) {}
-
-  explicit DISABLED_AssistantBrowserTest(bool disable_sandbox) {
-    // Do not log to file in test. Otherwise multiple tests may create/delete
-    // the log file at the same time. See http://crbug.com/1307868.
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kDisableLibAssistantLogfile);
-
-    if (disable_sandbox) {
-      // In browser tests, the fake_s3_server uses gRPC framework, which is not
-      // allowed in the sandbox by default. Instead of enabling and setting up
-      // the gRPC policy, we do not enable sandbox in the tests.
-      base::CommandLine::ForCurrentProcess()->AppendSwitch(
-          sandbox::policy::switches::kNoSandbox);
-    }
-  }
-
-  DISABLED_AssistantBrowserTest(const DISABLED_AssistantBrowserTest&) = delete;
-  DISABLED_AssistantBrowserTest& operator=(
-      const DISABLED_AssistantBrowserTest&) = delete;
-
-  ~DISABLED_AssistantBrowserTest() override = default;
-
-  AssistantTestMixin* tester() { return &tester_; }
-
-  void ShowAssistantUi() {
-    if (!tester()->IsVisible()) {
-      tester()->PressAssistantKey();
-    }
-
-    // Make sure that the app list bubble finished showing.
-    AppListTestApi().WaitForBubbleWindow(
-        /*wait_for_opening_animation=*/false);
-  }
-
-  void CloseAssistantUi() {
-    if (tester()->IsVisible()) {
-      tester()->PressAssistantKey();
-    }
-  }
-
-  void InitializeBrightness() {
-    auto* power_manager = chromeos::PowerManagerClient::Get();
-    power_manager::SetBacklightBrightnessRequest request;
-    request.set_percent(kStartBrightnessPercent);
-    request.set_transition(
-        power_manager::SetBacklightBrightnessRequest_Transition_INSTANT);
-    request.set_cause(
-        power_manager::SetBacklightBrightnessRequest_Cause_USER_REQUEST);
-    chromeos::PowerManagerClient::Get()->SetScreenBrightness(request);
-
-    // Wait for the initial value to settle.
-    ExpectResult(
-        true, base::BindLambdaForTesting([&]() {
-          constexpr double kEpsilon = 0.1;
-          auto current_brightness = tester()->SyncCall(base::BindOnce(
-              &chromeos::PowerManagerClient::GetScreenBrightnessPercent,
-              base::Unretained(power_manager)));
-          return current_brightness &&
-                 std::abs(kStartBrightnessPercent -
-                          current_brightness.value()) < kEpsilon;
-        }));
-  }
-
-  void ExpectBrightnessUp() {
-    auto* power_manager = chromeos::PowerManagerClient::Get();
-    // Check the brightness changes
-    ExpectResult(
-        true, base::BindLambdaForTesting([&]() {
-          constexpr double kEpsilon = 1;
-          auto current_brightness = tester()->SyncCall(base::BindOnce(
-              &chromeos::PowerManagerClient::GetScreenBrightnessPercent,
-              base::Unretained(power_manager)));
-
-          return current_brightness && (current_brightness.value() -
-                                        kStartBrightnessPercent) > kEpsilon;
-        }));
-  }
-
-  void ExpectBrightnessDown() {
-    auto* power_manager = chromeos::PowerManagerClient::Get();
-    // Check the brightness changes
-    ExpectResult(
-        true, base::BindLambdaForTesting([&]() {
-          constexpr double kEpsilon = 1;
-          auto current_brightness = tester()->SyncCall(base::BindOnce(
-              &chromeos::PowerManagerClient::GetScreenBrightnessPercent,
-              base::Unretained(power_manager)));
-
-          return current_brightness && (kStartBrightnessPercent -
-                                        current_brightness.value()) > kEpsilon;
-        }));
-  }
-
-  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
-
- private:
-  base::HistogramTester histogram_tester_;
-  AssistantTestMixin tester_{&mixin_host_, this, embedded_test_server(), kMode,
-                             kVersion};
-};
-
-class DISABLED_AssistantBrowserTestWithSandbox
-    : public DISABLED_AssistantBrowserTest {
- public:
-  DISABLED_AssistantBrowserTestWithSandbox()
-      : DISABLED_AssistantBrowserTest(/*disable_sandbox=*/false) {}
-};
-
-// Tests that Assistant can start up with sandbox.
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTestWithSandbox, Ready) {
-  tester()->StartAssistantAndWaitForReady();
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldOpenAssistantUiWhenPressingAssistantKey) {
-  tester()->StartAssistantAndWaitForReady();
-
-  tester()->PressAssistantKey();
-
-  // Make sure that the app list bubble finished showing (the app list view gets
-  // created asynchronously).
-  AppListTestApi().WaitForBubbleWindow(
-      /*wait_for_opening_animation=*/false);
-
-  EXPECT_TRUE(tester()->IsVisible());
-  histogram_tester()->ExpectTotalCount(kDlcInstallResultHistogram, 1);
-  histogram_tester()->ExpectTotalCount(kDlcLoadStatusHistogram, 1);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldDisplayTextResponse) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  tester()->SendTextQuery("test");
-  tester()->ExpectAnyOfTheseTextResponses({
-      "No one told me there would be a test",
-      "You're coming in loud and clear",
-      "debug OK",
-      "I can assure you, this thing's on",
-      "Is this thing on?",
-  });
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldDisplayTextResponseWithTwoContiniousQueries) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  tester()->SendTextQuery("phone");
-  tester()->SendTextQuery("test");
-  tester()->ExpectAnyOfTheseTextResponses({
-      "No one told me there would be a test",
-      "You're coming in loud and clear",
-      "debug OK",
-      "I can assure you, this thing's on",
-      "Is this thing on?",
-  });
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldDisplayCardResponse) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  tester()->SendTextQuery("What is the highest mountain in the world?");
-  tester()->ExpectCardResponse("Mount Everest");
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest, ShouldTurnUpVolume) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  auto* cras = CrasAudioHandler::Get();
-  constexpr int kStartVolumePercent = 50;
-  cras->SetOutputVolumePercent(kStartVolumePercent);
-  EXPECT_EQ(kStartVolumePercent, cras->GetOutputVolumePercent());
-
-  tester()->SendTextQuery("turn up volume");
-
-  ExpectResult(true, base::BindRepeating(
-                         [](CrasAudioHandler* cras) {
-                           return cras->GetOutputVolumePercent() >
-                                  kStartVolumePercent;
-                         },
-                         cras));
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest, ShouldTurnDownVolume) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  auto* cras = CrasAudioHandler::Get();
-  constexpr int kStartVolumePercent = 50;
-  cras->SetOutputVolumePercent(kStartVolumePercent);
-  EXPECT_EQ(kStartVolumePercent, cras->GetOutputVolumePercent());
-
-  tester()->SendTextQuery("turn down volume");
-
-  ExpectResult(true, base::BindRepeating(
-                         [](CrasAudioHandler* cras) {
-                           return cras->GetOutputVolumePercent() <
-                                  kStartVolumePercent;
-                         },
-                         cras));
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest, ShouldTurnUpBrightness) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  InitializeBrightness();
-
-  tester()->SendTextQuery("turn up brightness");
-
-  ExpectBrightnessUp();
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldTurnDownBrightness) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  InitializeBrightness();
-
-  tester()->SendTextQuery("turn down brightness");
-
-  ExpectBrightnessDown();
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldPuntWhenChangingUnsupportedSetting) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  tester()->SendTextQuery("enable night mode");
-
-  tester()->ExpectTextResponse("Night Mode isn't available on your device");
-}
-
-// TODO(crbug.com/40142964): Disabled because it's flaky.
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantBrowserTest,
-                       ShouldShowSingleErrorOnNetworkDown) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-
-  ASSERT_TRUE(tester()->IsVisible());
-
-  tester()->DisableFakeS3Server();
-
-  base::RunLoop().RunUntilIdle();
-
-  tester()->SendTextQuery("Is this thing on?");
-
-  tester()->ExpectErrorResponse(
-      "Something went wrong. Try again in a few seconds");
-
-  // Make sure no further changes happen to the view hierarchy.
-  tester()->ExpectNoChange(base::Seconds(1));
-
-  // This is necessary to prevent a UserInitiatedVoicelessActivity from
-  // blocking test harness teardown while we wait on assistant to finish
-  // the interaction.
-  CloseAssistantUi();
-}
-
-}  // namespace ash::assistant
diff --git a/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc b/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc
deleted file mode 100644
index 93d6544..0000000
--- a/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc
+++ /dev/null
@@ -1,605 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
-
-#include <algorithm>
-#include <utility>
-#include <vector>
-
-#include "ash/assistant/model/ui/assistant_card_element.h"
-#include "ash/assistant/ui/assistant_ui_constants.h"
-#include "ash/assistant/ui/main_stage/assistant_ui_element_view.h"
-#include "ash/constants/ash_switches.h"
-#include "ash/public/cpp/assistant/assistant_state.h"
-#include "ash/public/cpp/test/assistant_test_api.h"
-#include "base/auto_reset.h"
-#include "base/containers/to_vector.h"
-#include "base/memory/raw_ptr.h"
-#include "base/run_loop.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/test/scoped_run_loop_timeout.h"
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "chrome/browser/ash/login/test/embedded_test_server_setup_mixin.h"
-#include "chrome/browser/ash/login/test/login_manager_mixin.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h"
-#include "chrome/test/base/fake_gaia_mixin.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chromeos/ash/components/login/auth/public/user_context.h"
-#include "components/account_id/account_id.h"
-#include "components/language/core/browser/pref_names.h"
-#include "google_apis/gaia/gaia_id.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/dns/mock_host_resolver.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/views/controls/label.h"
-
-namespace ash::assistant {
-
-namespace {
-
-constexpr const char kTestUser[] = "test_user@gmail.com";
-constexpr const GaiaId::Literal kTestUserGaiaId("test_user_gaia_id");
-
-LoginManagerMixin::TestUserInfo GetTestUserInfo() {
-  return LoginManagerMixin::TestUserInfo(
-      AccountId::FromUserEmailGaiaId(kTestUser, kTestUserGaiaId));
-}
-
-// Waiter that blocks in the |Wait| method until a given |AssistantStatus|
-// is reached, or until a timeout is hit.
-// On timeout this will abort the test with a useful error message.
-class AssistantStatusWaiter : private AssistantStateObserver {
- public:
-  AssistantStatusWaiter(AssistantState* state, AssistantStatus expected_status)
-      : state_(state), expected_status_(expected_status) {
-    state_->AddObserver(this);
-  }
-
-  ~AssistantStatusWaiter() override { state_->RemoveObserver(this); }
-
-  void RunUntilExpectedStatus() {
-    if (state_->assistant_status() == expected_status_) {
-      return;
-    }
-
-    // Wait until we're ready or we hit the timeout.
-    base::RunLoop run_loop;
-    base::AutoReset<base::OnceClosure> quit_loop(&quit_loop_,
-                                                 run_loop.QuitClosure());
-    EXPECT_NO_FATAL_FAILURE(run_loop.Run())
-        << "Failed waiting for AssistantStatus |" << expected_status_ << "|. "
-        << "Current status is |" << state_->assistant_status() << "|. "
-        << "One possible cause is that you're using an expired access token.";
-  }
-
- private:
-  void OnAssistantStatusChanged(AssistantStatus status) override {
-    if (status == expected_status_ && quit_loop_) {
-      std::move(quit_loop_).Run();
-    }
-  }
-
-  const raw_ptr<AssistantState> state_;
-  AssistantStatus const expected_status_;
-
-  base::OnceClosure quit_loop_;
-};
-
-// Base class that observes all new responses being displayed under the
-// |parent_view|, waiting for HasResponse() to return |true| or until a timeout
-// is hit. On timeout this will abort the test with a useful error message. By
-// default, HasResponse() checks for any non-empty response, but this behavior
-// can be overridden by derived classes wishing to assert more specific
-// expectations. The derived classes must implement the logic to extract the
-// response from a given view.
-class ResponseWaiter : private views::ViewObserver {
- public:
-  explicit ResponseWaiter(views::View* parent_view)
-      : parent_view_(parent_view) {
-    parent_view_->AddObserver(this);
-  }
-
-  ~ResponseWaiter() override {
-    if (parent_view_) {
-      parent_view_->RemoveObserver(this);
-    }
-  }
-
-  void RunUntilResponseReceived() {
-    if (HasResponse()) {
-      return;
-    }
-
-    // Wait until we're ready or we hit the timeout.
-    base::RunLoop run_loop;
-    base::AutoReset<base::OnceClosure> quit_loop(&quit_loop_,
-                                                 run_loop.QuitClosure());
-    EXPECT_NO_FATAL_FAILURE(run_loop.Run())
-        << "Failed waiting for Assistant response.\n"
-        << GetFailureMessage();
-  }
-
-  std::string GetResponseText() const {
-    return GetResponseTextRecursive(parent_view_);
-  }
-
- private:
-  // views::ViewObserver overrides:
-  void OnViewHierarchyChanged(
-      views::View* observed_view,
-      const views::ViewHierarchyChangedDetails& details) override {
-    if (quit_loop_ && HasResponse()) {
-      std::move(quit_loop_).Run();
-    }
-  }
-
-  void OnViewIsDeleting(views::View* observed_view) override {
-    DCHECK(observed_view == parent_view_);
-
-    if (quit_loop_) {
-      ADD_FAILURE() << parent_view_->GetClassName() << " is deleted "
-                    << "before receiving the Assistant response.\n"
-                    << GetFailureMessage();
-      std::move(quit_loop_).Run();
-    }
-
-    parent_view_ = nullptr;
-  }
-
-  virtual bool HasResponse() const { return !GetResponseText().empty(); }
-
-  virtual std::string GetFailureMessage() const {
-    return "Expected to receive any non-empty response.";
-  }
-
-  std::string GetResponseTextRecursive(views::View* view) const {
-    std::optional<std::string> response_maybe = GetResponseTextOfView(view);
-    if (response_maybe) {
-      return response_maybe.value() + "\n";
-    } else {
-      std::stringstream result;
-      for (views::View* child : view->children()) {
-        result << GetResponseTextRecursive(child);
-      }
-      return result.str();
-    }
-  }
-
-  virtual std::optional<std::string> GetResponseTextOfView(
-      views::View* view) const = 0;
-
-  raw_ptr<views::View> parent_view_;
-  base::OnceClosure quit_loop_;
-};
-
-// A ResponseWaiter which waits until one of |expected_responses| is received.
-// The derived classes must implement the logic to extract the response from a
-// given view.
-class ExpectedResponseWaiter : public ResponseWaiter {
- public:
-  ExpectedResponseWaiter(views::View* parent_view,
-                         const std::vector<std::string>& expected_responses)
-      : ResponseWaiter(parent_view), expected_responses_(expected_responses) {}
-
- private:
-  // ResponseWaiter overrides:
-  bool HasResponse() const override {
-    std::string response = GetResponseText();
-    for (const std::string& expected : expected_responses_) {
-      if (response.find(expected) != std::string::npos) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  std::string GetFailureMessage() const override {
-    std::stringstream message;
-    message << "Expected any of " << FormatExpectedResponses() << ".\n";
-    message << "Got \"" << GetResponseText() << "\"";
-    return message.str();
-  }
-
-  std::string FormatExpectedResponses() const {
-    std::stringstream result;
-    result << "{\n";
-    for (const std::string& expected : expected_responses_) {
-      result << "    \"" << expected << "\",\n";
-    }
-    result << "}";
-    return result.str();
-  }
-
-  std::vector<std::string> expected_responses_;
-};
-
-// A ResponseWaiter which waits until any non-empty response is received for a
-// response of the type indicated by the specified |class_name|.
-// NOTE: |class_name| must name a class inheriting from AssistantUiElementView.
-class TypedResponseWaiter : public ResponseWaiter {
- public:
-  TypedResponseWaiter(const std::string& class_name, views::View* parent_view)
-      : ResponseWaiter(parent_view), class_name_(class_name) {}
-
-  ~TypedResponseWaiter() override = default;
-
- private:
-  // ResponseWaiter overrides:
-  std::optional<std::string> GetResponseTextOfView(
-      views::View* view) const override {
-    if (view->GetClassName() == class_name_) {
-      return static_cast<AssistantUiElementView*>(view)->ToStringForTesting();
-    }
-    return std::nullopt;
-  }
-
-  const std::string class_name_;
-};
-
-// An ExpectedResponseWaiter which waits until one of |expected_responses| is
-// received for a response of the type indicated by the specified |class_name|.
-// NOTE: |class_name| must name a class inheriting from AssistantUiElementView.
-class TypedExpectedResponseWaiter : public ExpectedResponseWaiter {
- public:
-  TypedExpectedResponseWaiter(
-      const std::string& class_name,
-      views::View* parent_view,
-      const std::vector<std::string>& expected_responses)
-      : ExpectedResponseWaiter(parent_view, expected_responses),
-        class_name_(class_name) {}
-
-  ~TypedExpectedResponseWaiter() override = default;
-
- private:
-  // ExpectedResponseWaiter overrides:
-  std::optional<std::string> GetResponseTextOfView(
-      views::View* view) const override {
-    if (view->GetClassName() == class_name_) {
-      return static_cast<AssistantUiElementView*>(view)->ToStringForTesting();
-    }
-    return std::nullopt;
-  }
-
-  const std::string class_name_;
-};
-
-// Calls a callback when the view hierarchy changes.
-class CallbackViewHierarchyChangedObserver : views::ViewObserver {
- public:
-  explicit CallbackViewHierarchyChangedObserver(
-      views::View* parent_view,
-      base::RepeatingCallback<void(const views::ViewHierarchyChangedDetails&)>
-          callback)
-      : callback_(callback), parent_view_(parent_view) {
-    parent_view_->AddObserver(this);
-  }
-
-  ~CallbackViewHierarchyChangedObserver() override {
-    if (parent_view_) {
-      parent_view_->RemoveObserver(this);
-    }
-  }
-
-  // ViewObserver:
-  void OnViewHierarchyChanged(
-      views::View* observed_view,
-      const views::ViewHierarchyChangedDetails& details) override {
-    callback_.Run(details);
-  }
-
-  void OnViewIsDeleting(views::View* view) override {
-    DCHECK_EQ(view, parent_view_);
-
-    if (parent_view_) {
-      parent_view_->RemoveObserver(this);
-    }
-
-    parent_view_ = nullptr;
-  }
-
- private:
-  base::RepeatingCallback<void(const views::ViewHierarchyChangedDetails&)>
-      callback_;
-  raw_ptr<views::View> parent_view_;
-};
-
-}  // namespace
-
-// Test mixin for the browser tests that logs in the given user and issues
-// refresh and access tokens for this user.
-class LoggedInUserMixin : public InProcessBrowserTestMixin {
- public:
-  LoggedInUserMixin(InProcessBrowserTestMixinHost* host,
-                    InProcessBrowserTest* test_base,
-                    LoginManagerMixin::TestUserInfo user,
-                    net::EmbeddedTestServer* embedded_test_server)
-      : InProcessBrowserTestMixin(host),
-        login_manager_(host, {user}),
-        test_server_(host, embedded_test_server),
-        fake_gaia_(host),
-        user_(user),
-        test_base_(test_base),
-        user_context_(LoginManagerMixin::CreateDefaultUserContext(user)) {
-    // Tell LoginManagerMixin to launch the browser when the user is logged in.
-    login_manager_.SetShouldLaunchBrowser(true);
-  }
-
-  ~LoggedInUserMixin() override = default;
-
-  void SetAccessToken(std::string token) { access_token_ = token; }
-
-  void SetUpOnMainThread() override {
-    // By default, browser tests block anything that doesn't go to localhost, so
-    // account.google.com requests would never reach fake GAIA server without
-    // this.
-    test_base_->host_resolver()->AddRule("*", "127.0.0.1");
-
-    LogIn();
-    SetupFakeGaia();
-
-    // Ensure test_base_->browser() returns the browser of the logged in user
-    // session.
-    test_base_->SelectFirstBrowser();
-  }
-
-  void LogIn() {
-    user_context_.SetRefreshToken(kRefreshToken);
-    bool success = login_manager_.LoginAndWaitForActiveSession(user_context_);
-    EXPECT_TRUE(success) << "Failed to log in as test user.";
-  }
-
-  void SetupFakeGaia() {
-    FakeGaia::AccessTokenInfo token_info;
-    token_info.token = access_token_;
-    token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
-    token_info.email = user_context_.GetAccountId().GetUserEmail();
-    token_info.any_scope = true;
-    token_info.expires_in = kAccessTokenExpiration;
-
-    fake_gaia_.fake_gaia()->MapEmailToGaiaId(user_.account_id.GetUserEmail(),
-                                             user_.account_id.GetGaiaId());
-    fake_gaia_.fake_gaia()->IssueOAuthToken(kRefreshToken, token_info);
-  }
-
- private:
-  const char* kRefreshToken = FakeGaiaMixin::kFakeRefreshToken;
-  const int kAccessTokenExpiration = FakeGaiaMixin::kFakeAccessTokenExpiration;
-
-  LoginManagerMixin login_manager_;
-  EmbeddedTestServerSetupMixin test_server_;
-  FakeGaiaMixin fake_gaia_;
-
-  LoginManagerMixin::TestUserInfo user_;
-  const raw_ptr<InProcessBrowserTest> test_base_;
-  UserContext user_context_;
-  std::string access_token_{FakeGaiaMixin::kFakeAllScopeAccessToken};
-};
-
-AssistantTestMixin::AssistantTestMixin(
-    InProcessBrowserTestMixinHost* host,
-    InProcessBrowserTest* test_base,
-    net::EmbeddedTestServer* embedded_test_server,
-    FakeS3Mode mode,
-    int test_data_version)
-    : InProcessBrowserTestMixin(host),
-      fake_s3_server_(test_data_version),
-      mode_(mode),
-      test_api_(AssistantTestApi::Create()),
-      user_mixin_(std::make_unique<LoggedInUserMixin>(host,
-                                                      test_base,
-                                                      GetTestUserInfo(),
-                                                      embedded_test_server)) {}
-
-AssistantTestMixin::~AssistantTestMixin() = default;
-
-void AssistantTestMixin::SetUpCommandLine(base::CommandLine* command_line) {
-  // Prevent the Assistant setup flow dialog from popping up immediately on user
-  // start - otherwise the Assistant can not be started.
-  command_line->AppendSwitch(switches::kOobeSkipPostLogin);
-}
-
-void AssistantTestMixin::SetUpOnMainThread() {
-  fake_s3_server_.Setup(mode_);
-  user_mixin_->SetAccessToken(fake_s3_server_.GetAccessToken());
-  test_api_->DisableAnimations();
-}
-
-void AssistantTestMixin::TearDownOnMainThread() {
-  DisableAssistant();
-  DisableFakeS3Server();
-}
-
-void AssistantTestMixin::DisableFakeS3Server() {
-  fake_s3_server_.Teardown();
-}
-
-void AssistantTestMixin::StartAssistantAndWaitForReady(
-    base::TimeDelta wait_timeout) {
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-
-  // Note: You might be tempted to call this function from SetUpOnMainThread(),
-  // but that will not work as the Assistant service can not start until
-  // |BrowserTestBase| calls InitializeNetworkProcess(), which it only does
-  // after SetUpOnMainThread() finishes.
-
-  test_api_->SetAssistantEnabled(true);
-  SetPreferVoice(false);
-
-  AssistantStatusWaiter waiter(test_api_->GetAssistantState(),
-                               AssistantStatus::READY);
-  waiter.RunUntilExpectedStatus();
-}
-
-void AssistantTestMixin::SetAssistantEnabled(bool enabled) {
-  test_api_->SetAssistantEnabled(enabled);
-}
-
-void AssistantTestMixin::SetPreferVoice(bool prefer_voice) {
-  test_api_->SetPreferVoice(prefer_voice);
-}
-
-void AssistantTestMixin::SendTextQuery(const std::string& query) {
-  test_api_->SendTextQuery(query);
-}
-
-template <typename T>
-T AssistantTestMixin::SyncCall(
-    base::OnceCallback<void(base::OnceCallback<void(T)>)> func) {
-  const base::test::ScopedRunLoopTimeout run_timeout(
-      FROM_HERE, TestTimeouts::action_timeout());
-
-  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-  T result;
-  auto callback = base::BindOnce(
-      [](T* result_ptr, base::OnceClosure quit_closure, T result_value) {
-        *result_ptr = result_value;
-        std::move(quit_closure).Run();
-      },
-      &result, run_loop.QuitClosure());
-
-  std::move(func).Run(std::move(callback));
-
-  EXPECT_NO_FATAL_FAILURE(run_loop.Run())
-      << "Failed waiting for async callback to return.\n";
-
-  return result;
-}
-
-template std::optional<double> AssistantTestMixin::SyncCall(
-    base::OnceCallback<void(base::OnceCallback<void(std::optional<double>)>)>
-        func);
-
-void AssistantTestMixin::ExpectCardResponse(
-    const std::string& expected_response,
-    base::TimeDelta wait_timeout) {
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-  TypedExpectedResponseWaiter waiter("AssistantCardElementView",
-                                     test_api_->ui_element_container(),
-                                     {expected_response});
-  waiter.RunUntilResponseReceived();
-}
-
-void AssistantTestMixin::ExpectTextResponse(
-    const std::string& expected_response,
-    base::TimeDelta wait_timeout) {
-  ExpectAnyOfTheseTextResponses({expected_response}, wait_timeout);
-}
-
-void AssistantTestMixin::ExpectAnyOfTheseTextResponses(
-    const std::vector<std::string>& expected_responses,
-    base::TimeDelta wait_timeout) {
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-  TypedExpectedResponseWaiter waiter("AssistantTextElementView",
-                                     test_api_->ui_element_container(),
-                                     expected_responses);
-  waiter.RunUntilResponseReceived();
-}
-
-void AssistantTestMixin::ExpectErrorResponse(
-    const std::string& expected_response,
-    base::TimeDelta wait_timeout) {
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-  TypedExpectedResponseWaiter waiter("AssistantErrorElementView",
-                                     test_api_->ui_element_container(),
-                                     {expected_response});
-
-  waiter.RunUntilResponseReceived();
-}
-
-void AssistantTestMixin::ExpectTimersResponse(
-    const std::vector<base::TimeDelta>& timers,
-    base::TimeDelta wait_timeout) {
-  // We expect the textual representation of a timers response to be of the form
-  // "<timer1 remaining time in seconds>\n<timer2 remaining time in seconds>..."
-  std::stringstream expected_response;
-  for (const auto& timer : timers) {
-    expected_response << timer.InSeconds() << "\n";
-  }
-
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-  TypedExpectedResponseWaiter waiter("AssistantTimersElementView",
-                                     test_api_->ui_element_container(),
-                                     {expected_response.str()});
-  waiter.RunUntilResponseReceived();
-}
-
-std::vector<base::TimeDelta> AssistantTestMixin::ExpectAndReturnTimersResponse(
-    base::TimeDelta wait_timeout) {
-  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
-  TypedResponseWaiter waiter("AssistantTimersElementView",
-                             test_api_->ui_element_container());
-  waiter.RunUntilResponseReceived();
-
-  // We expect the textual representation of a timers response to be of the form
-  // "<timer1 remaining time in seconds>\n<timer2 remaining time in seconds>..."
-  std::vector<std::string> timers_as_strings =
-      base::SplitString(base::TrimString(waiter.GetResponseText(), "\n",
-                                         base::TrimPositions::TRIM_TRAILING),
-                        "\n", base::WhitespaceHandling::KEEP_WHITESPACE,
-                        base::SplitResult::SPLIT_WANT_ALL);
-
-  // Transform the textual representation of our timers into TimeDelta objects.
-  return base::ToVector(
-      timers_as_strings, [](const std::string& timer_as_string) {
-        int seconds_remaining = 0;
-        base::StringToInt(timer_as_string, &seconds_remaining);
-        return base::Seconds(seconds_remaining);
-      });
-}
-
-void AssistantTestMixin::PressAssistantKey() {
-  SendKeyPress(::ui::VKEY_ASSISTANT);
-}
-
-bool AssistantTestMixin::IsVisible() {
-  return test_api_->IsVisible();
-}
-
-void AssistantTestMixin::ExpectNoChange(base::TimeDelta wait_timeout) {
-  base::test::ScopedDisableRunLoopTimeout disable_timeout;
-
-  base::RunLoop run_loop;
-
-  // Exit the runloop after wait_timeout.
-  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      base::BindRepeating(
-          [](base::RepeatingClosure quit) { std::move(quit).Run(); },
-          run_loop.QuitClosure()),
-      wait_timeout);
-
-  // Fail the runloop when the view hierarchy changes.
-  auto callback = base::BindRepeating(
-      [](const views::ViewHierarchyChangedDetails& change) { FAIL(); });
-
-  CallbackViewHierarchyChangedObserver observer(
-      test_api_->ui_element_container(), std::move(callback));
-
-  EXPECT_NO_FATAL_FAILURE(run_loop.Run())
-      << "View hierarchy changed during ExpectNoChange.";
-}
-
-PrefService* AssistantTestMixin::GetUserPreferences() {
-  return ProfileManager::GetPrimaryUserProfile()->GetPrefs();
-}
-
-void AssistantTestMixin::SendKeyPress(::ui::KeyboardCode key) {
-  ::ui::test::EventGenerator event_generator(test_api_->root_window());
-  event_generator.PressKey(key, /*flags=*/::ui::EF_NONE);
-}
-
-void AssistantTestMixin::DisableAssistant() {
-  // First disable Assistant in the settings.
-  test_api_->SetAssistantEnabled(false);
-
-  // Then wait for the Service to shutdown.
-  AssistantStatusWaiter waiter(test_api_->GetAssistantState(),
-                               AssistantStatus::NOT_READY);
-  waiter.RunUntilExpectedStatus();
-}
-
-}  // namespace ash::assistant
diff --git a/chrome/browser/ui/ash/assistant/assistant_test_mixin.h b/chrome/browser/ui/ash/assistant/assistant_test_mixin.h
deleted file mode 100644
index 47a3337c..0000000
--- a/chrome/browser/ui/ash/assistant/assistant_test_mixin.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_TEST_MIXIN_H_
-#define CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_TEST_MIXIN_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "ui/events/keycodes/keyboard_codes_posix.h"
-
-class PrefService;
-
-namespace ash {
-class AssistantTestApi;
-}
-
-namespace ash::assistant {
-
-class LoggedInUserMixin;
-
-// Creates everything required to test the Assistant in browser tests.
-// This includes:
-//     - Installing a fake Gaia server so the test user is able to use the
-//       Assistant.
-//     - Setting up a fake S3 server to spoof fake interactions.
-//     - Enabling the Assistant service.
-//     - Disabling all Assistant animations.
-//
-// See definition of `FakeS3Server` for an explanation of the different modes
-// the fake S3 server can run in (specified by passing `FakeS3Mode` into the
-// constructor).
-class AssistantTestMixin : public InProcessBrowserTestMixin {
- public:
-  AssistantTestMixin(InProcessBrowserTestMixinHost* host,
-                     InProcessBrowserTest* test_base,
-                     net::EmbeddedTestServer* embedded_test_server,
-                     FakeS3Mode mode,
-                     int test_data_version);
-
-  AssistantTestMixin(const AssistantTestMixin&) = delete;
-  AssistantTestMixin& operator=(const AssistantTestMixin&) = delete;
-
-  ~AssistantTestMixin() override;
-
-  // InProcessBrowserTestMixin overrides:
-  void SetUpCommandLine(base::CommandLine* command_line) override;
-  void SetUpOnMainThread() override;
-  void TearDownOnMainThread() override;
-
-  void DisableFakeS3Server();
-
-  // Starts the Assistant service and wait until it is ready to process
-  // queries. Should be called as the first action in every test.
-  void StartAssistantAndWaitForReady(
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Changes the user setting controlling if the user has enabled Assistant.
-  void SetAssistantEnabled(bool enabled);
-
-  // Changes the user setting controlling if the user prefers voice or keyboard.
-  void SetPreferVoice(bool prefer_voice);
-
-  // Submits a text query. Can only be used when the Assistant UI is visible and
-  // displaying the query input text field.
-  void SendTextQuery(const std::string& query);
-
-  // Synchronize an async method call to make testing simpler. |func| is the
-  // async method to be invoked, the inner callback is the result callback. The
-  // result with type |T| will be the return value.
-  //
-  // NOTE: This is a template method. If you need to use it with a new type,
-  // you may see a link error. You will need to manually instantiate for the
-  // new type.  Please see .cc file for examples.
-  template <typename T>
-  T SyncCall(base::OnceCallback<void(base::OnceCallback<void(T)>)> func);
-
-  // Waits until a card response is rendered that contains the given text.
-  // If |expected_response| is not received in |wait_timeout|, this will fail
-  // the test.
-  void ExpectCardResponse(
-      const std::string& expected_response,
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Waits until an error response is rendered that contains the given text. If
-  // |expected_response| is not received in |wait_timeout|, this will fail the
-  // test.
-  void ExpectErrorResponse(
-      const std::string& expected_response,
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Waits until a text response is rendered that contains the given text.
-  // If |expected_response| is not received in |wait_timeout|, this will fail
-  // the test.
-  void ExpectTextResponse(
-      const std::string& expected_response,
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Same as above but checks if any of the given responses are encountered.
-  void ExpectAnyOfTheseTextResponses(
-      const std::vector<std::string>& expected_responses,
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Waits until a timers response is rendered that contains the given timers.
-  // If the expected response is not received in |wait_timeout|, this will fail
-  // the test.
-  void ExpectTimersResponse(
-      const std::vector<base::TimeDelta>& timers,
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Waits until a timers response is rendered and returns the time remaining of
-  // the rendered timers. If a timers response is not received in |wait_timeout|
-  // this will fail the test.
-  std::vector<base::TimeDelta> ExpectAndReturnTimersResponse(
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
-  // Presses the Assistant key, which will toggle the Assistant UI.
-  void PressAssistantKey();
-
-  // Returns true if the Assistant UI is currently visible.
-  bool IsVisible();
-
-  // Watches the view hierarchy for change and fails if
-  // a view is updated / deleted / added before wait_timeout time elapses.
-  void ExpectNoChange(
-      base::TimeDelta wait_timeout = TestTimeouts::action_timeout());
-
- private:
-  PrefService* GetUserPreferences();
-  void SendKeyPress(::ui::KeyboardCode key);
-  void DisableAssistant();
-
-  FakeS3Server fake_s3_server_;
-  FakeS3Mode mode_;
-  std::unique_ptr<AssistantTestApi> test_api_;
-  std::unique_ptr<LoggedInUserMixin> user_mixin_;
-};
-
-}  // namespace ash::assistant
-
-#endif  // CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_TEST_MIXIN_H_
diff --git a/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc b/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc
deleted file mode 100644
index 0359f05..0000000
--- a/chrome/browser/ui/ash/assistant/assistant_timers_browsertest.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "ash/public/cpp/test/app_list_test_api.h"
-#include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_widget.h"
-#include "ash/shell.h"
-#include "ash/system/notification_center/notification_center_tray.h"
-#include "ash/system/notification_center/views/notification_center_view.h"
-#include "ash/system/notification_center/views/notification_list_view.h"
-#include "ash/system/status_area_widget.h"
-#include "base/command_line.h"
-#include "base/scoped_observation.h"
-#include "base/strings/string_util.h"
-#include "base/test/bind.h"
-#include "base/test/icu_test_util.h"
-#include "base/time/time.h"
-#include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
-#include "chrome/browser/ui/ash/assistant/test_support/test_util.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chromeos/ash/services/assistant/public/cpp/features.h"
-#include "chromeos/ash/services/assistant/public/cpp/switches.h"
-#include "content/public/test/browser_test.h"
-#include "sandbox/policy/switches.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "ui/aura/window.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_observer.h"
-#include "ui/message_center/public/cpp/notification.h"
-#include "ui/message_center/views/notification_view.h"
-#include "ui/views/controls/button/label_button.h"
-
-namespace ash::assistant {
-
-namespace {
-
-using ::message_center::MessageCenter;
-using ::message_center::MessageCenterObserver;
-
-// Please remember to set auth token when *not* running in |kReplay| mode.
-constexpr auto kMode = FakeS3Mode::kReplay;
-
-// Update this when you introduce breaking changes to existing tests.
-constexpr int kVersion = 1;
-
-// Macros ----------------------------------------------------------------------
-
-#define EXPECT_VISIBLE_NOTIFICATIONS_BY_PREFIXED_ID(prefix_)                  \
-  {                                                                           \
-    if (!FindVisibleNotificationsByPrefixedId(prefix_).empty()) {             \
-      return;                                                                 \
-    }                                                                         \
-    MockMessageCenterObserver mock_observer;                                  \
-    base::ScopedObservation<MessageCenter, MessageCenterObserver>             \
-        observation_{&mock_observer};                                         \
-    observation_.Observe(MessageCenter::Get());                               \
-                                                                              \
-    base::RunLoop run_loop;                                                   \
-    EXPECT_CALL(mock_observer, OnNotificationAdded)                           \
-        .WillOnce(                                                            \
-            testing::Invoke([&run_loop](const std::string& notification_id) { \
-              if (!FindVisibleNotificationsByPrefixedId(prefix_).empty())     \
-                run_loop.QuitClosure().Run();                                 \
-            }));                                                              \
-    run_loop.Run();                                                           \
-  }
-
-// Helpers ---------------------------------------------------------------------
-
-// Returns the status area widget.
-StatusAreaWidget* FindStatusAreaWidget() {
-  return Shelf::ForWindow(Shell::GetRootWindowForNewWindows())
-      ->shelf_widget()
-      ->status_area_widget();
-}
-
-// Returns the set of Assistant notifications (as indicated by application id).
-message_center::NotificationList::Notifications FindAssistantNotifications() {
-  return MessageCenter::Get()->FindNotificationsByAppId("assistant");
-}
-
-// Returns the visible notification specified by |id|.
-message_center::Notification* FindVisibleNotificationById(
-    const std::string& id) {
-  return MessageCenter::Get()->FindVisibleNotificationById(id);
-}
-
-// Returns visible notifications having id starting with |prefix|.
-std::vector<message_center::Notification*> FindVisibleNotificationsByPrefixedId(
-    const std::string& prefix) {
-  std::vector<message_center::Notification*> notifications;
-  for (message_center::Notification* notification :
-       MessageCenter::Get()->GetVisibleNotifications()) {
-    if (base::StartsWith(notification->id(), prefix,
-                         base::CompareCase::SENSITIVE)) {
-      notifications.push_back(notification);
-    }
-  }
-  return notifications;
-}
-
-// Returns the view for the specified |notification|.
-message_center::MessageView* FindViewForNotification(
-    const message_center::Notification* notification) {
-  NotificationListView* notification_list_view =
-      FindStatusAreaWidget()
-          ->notification_center_tray()
-          ->GetNotificationListView();
-
-  // TODO(crbug/1335196): `FindDescendentsOfClass` returning empty list for
-  // `NotificationCenterView` even when `MessageView`s exist. Need to
-  // investigate and resolve.
-  return notification_list_view->GetMessageViewForNotificationId(
-      notification->id());
-}
-
-// Returns the action buttons for the specified |notification|.
-std::vector<views::LabelButton*> FindActionButtonsForNotification(
-    const message_center::Notification* notification) {
-  auto* notification_view = FindViewForNotification(notification);
-
-  std::vector<views::LabelButton*> action_buttons;
-  FindDescendentsOfClass(notification_view, &action_buttons);
-
-  return action_buttons;
-}
-
-// Returns the label for the specified |notification| title.
-// NOTE: This method assumes that the title string is unique from other strings
-// displayed in the notification. This should be safe since we only use this API
-// under controlled circumstances.
-views::Label* FindTitleLabelForNotification(
-    const message_center::Notification* notification) {
-  std::vector<views::Label*> labels;
-  FindDescendentsOfClass(FindViewForNotification(notification), &labels);
-  for (auto* label : labels) {
-    if (label->GetText() == notification->title()) {
-      return label;
-    }
-  }
-  return nullptr;
-}
-
-// Performs a tap of the specified |view| and waits until the RunLoop idles.
-void TapOnAndWait(const views::View* view) {
-  auto* root_window = view->GetWidget()->GetNativeWindow()->GetRootWindow();
-  ui::test::EventGenerator event_generator(root_window);
-  event_generator.MoveTouch(view->GetBoundsInScreen().CenterPoint());
-  event_generator.PressTouch();
-  event_generator.ReleaseTouch();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Mocks -----------------------------------------------------------------------
-
-class MockMessageCenterObserver
-    : public testing::NiceMock<MessageCenterObserver> {
- public:
-  // MessageCenterObserver:
-  MOCK_METHOD(void,
-              OnNotificationAdded,
-              (const std::string& notification_id),
-              (override));
-
-  MOCK_METHOD(void,
-              OnNotificationUpdated,
-              (const std::string& notification_id),
-              (override));
-};
-
-}  // namespace
-
-// AssistantTimersBrowserTest
-// --------------------------------------------------
-
-// All tests are disabled because LibAssistant V2 binary does not run on Linux
-// bot. To run the tests on gLinux, please add
-// `--gtest_also_run_disabled_tests`.
-class DISABLED_AssistantTimersBrowserTest
-    : public MixinBasedInProcessBrowserTest,
-      public testing::WithParamInterface<bool> {
- public:
-  DISABLED_AssistantTimersBrowserTest() {
-    // Do not log to file in test. Otherwise multiple tests may create/delete
-    // the log file at the same time. See http://crbug.com/1307868.
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kDisableLibAssistantLogfile);
-
-    // In browser tests, the fake_s3_server uses gRPC framework, which is not
-    // allowed in the sandbox by default. Instead of enabling and setting up the
-    // gRPC policy, we do not enable sandbox in the tests.
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        sandbox::policy::switches::kNoSandbox);
-  }
-
-  DISABLED_AssistantTimersBrowserTest(
-      const DISABLED_AssistantTimersBrowserTest&) = delete;
-  DISABLED_AssistantTimersBrowserTest& operator=(
-      const DISABLED_AssistantTimersBrowserTest&) = delete;
-
-  ~DISABLED_AssistantTimersBrowserTest() override = default;
-
-  void ShowAssistantUi() {
-    if (!tester()->IsVisible()) {
-      tester()->PressAssistantKey();
-    }
-    AppListTestApi().WaitForBubbleWindow(
-        /*wait_for_opening_animation=*/true);
-  }
-
-  AssistantTestMixin* tester() { return &tester_; }
-
- private:
-  base::test::ScopedRestoreICUDefaultLocale locale_{"en_US"};
-  AssistantTestMixin tester_{&mixin_host_, this, embedded_test_server(), kMode,
-                             kVersion};
-};
-
-// Tests -----------------------------------------------------------------------
-
-// Timer notifications should be dismissed when disabling Assistant in settings.
-// Flaky. See https://crbug.com/1196564.
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantTimersBrowserTest,
-                       ShouldDismissTimerNotificationsWhenDisablingAssistant) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-  EXPECT_TRUE(tester()->IsVisible());
-
-  // Confirm no Assistant notifications are currently being shown.
-  EXPECT_TRUE(FindAssistantNotifications().empty());
-
-  // Start a timer for one minute.
-  tester()->SendTextQuery("Set a timer for 1 minute.");
-
-  // Check for a stable substring of the expected answers.
-  tester()->ExpectTextResponse("1 min.");
-
-  // Expect that an Assistant timer notification is now showing.
-  EXPECT_VISIBLE_NOTIFICATIONS_BY_PREFIXED_ID("assistant/timer");
-
-  // Disable Assistant.
-  tester()->SetAssistantEnabled(false);
-  base::RunLoop().RunUntilIdle();
-
-  // Confirm that our Assistant timer notification has been dismissed.
-  EXPECT_TRUE(FindAssistantNotifications().empty());
-}
-
-// Pressing the "STOP" action button in a timer notification should result in
-// the timer being removed.
-// Flaky. See https://crbug.com/1196564.
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantTimersBrowserTest,
-                       ShouldRemoveTimerWhenStoppingViaNotification) {
-  tester()->StartAssistantAndWaitForReady();
-
-  ShowAssistantUi();
-  EXPECT_TRUE(tester()->IsVisible());
-
-  // Confirm no Assistant notifications are currently being shown.
-  EXPECT_TRUE(FindAssistantNotifications().empty());
-
-  // Start a timer for five minutes.
-  tester()->SendTextQuery("Set a timer for 5 minutes");
-  tester()->ExpectTextResponse("5 min.");
-
-  // Confirm that an Assistant timer notification is now showing.
-  EXPECT_VISIBLE_NOTIFICATIONS_BY_PREFIXED_ID("assistant/timer");
-  auto notifications = FindVisibleNotificationsByPrefixedId("assistant/timer");
-  ASSERT_EQ(1u, notifications.size());
-
-  // Find the action buttons for our notification.
-  // NOTE: We expect action buttons for "Pause" and "Cancel".
-  auto action_buttons = FindActionButtonsForNotification(notifications.at(0));
-  EXPECT_EQ(2u, action_buttons.size());
-
-  // Tap the "Cancel" action button in the notification.
-  EXPECT_EQ(u"Cancel", action_buttons.at(1)->GetText());
-  TapOnAndWait(action_buttons.at(1));
-
-  ShowAssistantUi();
-  EXPECT_TRUE(tester()->IsVisible());
-
-  // Confirm that no timers exist anymore.
-  tester()->SendTextQuery("Show my timers");
-  tester()->ExpectAnyOfTheseTextResponses({
-      "It looks like you don't have any timers set at the moment.",
-  });
-}
-
-// Verifies that timer notifications are ticked at regular intervals.
-IN_PROC_BROWSER_TEST_F(DISABLED_AssistantTimersBrowserTest,
-                       ShouldTickNotificationsAtRegularIntervals) {
-  // Observe notifications.
-  MockMessageCenterObserver mock;
-  base::ScopedObservation<MessageCenter, MessageCenterObserver>
-      scoped_observation{&mock};
-  scoped_observation.Observe(MessageCenter::Get());
-
-  // Show Assistant UI (once ready).
-  tester()->StartAssistantAndWaitForReady();
-  ShowAssistantUi();
-  EXPECT_TRUE(tester()->IsVisible());
-
-  // Start a timer for five seconds.
-  tester()->SendTextQuery("Set a timer for 5 seconds");
-  tester()->ExpectTextResponse("5 sec.");
-
-  // We're going to cache the time of the last notification update so that we
-  // can verify updates occur within an expected time frame.
-  base::Time last_update;
-
-  // Expect and wait for our five second timer notification to be created.
-  EXPECT_VISIBLE_NOTIFICATIONS_BY_PREFIXED_ID("assistant/timer");
-  last_update = base::Time::Now();
-
-  auto* notification = FindVisibleNotificationById("assistant");
-  auto* title_label = FindTitleLabelForNotification(notification);
-  auto title = base::UTF16ToUTF8(title_label->GetText());
-  EXPECT_EQ("0:05", title);
-
-  // We are going to assert that updates to our notification occur within an
-  // expected time frame, allowing a degree of tolerance to reduce flakiness.
-  constexpr auto kExpectedMillisBetweenUpdates = 1000;
-  constexpr auto kMillisBetweenUpdatesTolerance = 100;
-
-  // We're going to watch notification updates until 5 seconds past fire time.
-  std::deque<std::string> expected_titles = {"0:04",  "0:03",  "0:02",  "0:01",
-                                             "0:00",  "-0:01", "-0:02", "-0:03",
-                                             "-0:04", "-0:05"};
-  bool is_first_update = true;
-
-  // Watch |title_label| and await all expected notification updates.
-  base::RunLoop notification_update_run_loop;
-  auto notification_update_subscription =
-      title_label->AddTextChangedCallback(base::BindLambdaForTesting([&]() {
-        base::Time now = base::Time::Now();
-
-        // Assert that the update was received within our expected time frame.
-        if (is_first_update) {
-          is_first_update = false;
-          // Our updates are synced to the nearest full second, meaning our
-          // first update can come anywhere from 1 ms to 1000 ms from the time
-          // our notification was shown.
-          EXPECT_LE((now - last_update).InMilliseconds(),
-                    1000 + kMillisBetweenUpdatesTolerance);
-        } else {
-          // Consecutive updates must come regularly.
-          EXPECT_NEAR((now - last_update).InMilliseconds(),
-                      kExpectedMillisBetweenUpdates,
-                      kMillisBetweenUpdatesTolerance);
-        }
-
-        // Assert that the notification has the expected title.
-        auto title = base::UTF16ToUTF8(title_label->GetText());
-        EXPECT_EQ(expected_titles.front(), title);
-
-        // Update time of |last_update|.
-        last_update = now;
-
-        // When |expected_titles| is empty, our test is finished.
-        expected_titles.pop_front();
-        if (expected_titles.empty()) {
-          notification_update_run_loop.QuitClosure().Run();
-        }
-      }));
-  notification_update_run_loop.Run();
-}
-
-}  // namespace ash::assistant
diff --git a/chrome/browser/ui/autofill/BUILD.gn b/chrome/browser/ui/autofill/BUILD.gn
index 3508281..777ac61d 100644
--- a/chrome/browser/ui/autofill/BUILD.gn
+++ b/chrome/browser/ui/autofill/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/ui.gni")
-import("//build/util/branding.gni")
 import("//components/signin/features.gni")
 
 assert(is_win || is_mac || is_linux || is_chromeos || is_android)
diff --git a/chrome/browser/ui/autofill/autofill_keyboard_accessory_controller_impl.cc b/chrome/browser/ui/autofill/autofill_keyboard_accessory_controller_impl.cc
index 096f40e..dac0dd4 100644
--- a/chrome/browser/ui/autofill/autofill_keyboard_accessory_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_keyboard_accessory_controller_impl.cc
@@ -359,6 +359,7 @@
     case FillingProduct::kPlusAddresses:
     case FillingProduct::kAutofillAi:
     case FillingProduct::kLoyaltyCard:
+    case FillingProduct::kIdentityCredential:
       break;
   }
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 66869d54..1621c2c 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -511,6 +511,7 @@
     case FillingProduct::kCompose:
     case FillingProduct::kPlusAddresses:
     case FillingProduct::kAutofillAi:
+    case FillingProduct::kIdentityCredential:
       break;
   }
 
diff --git a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
index 5c8c844b..4fdbf5db 100644
--- a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
@@ -303,7 +303,8 @@
 
   // Log save IBAN prompt result according to the closed reason.
   if (current_bubble_type_ == IbanBubbleType::kLocalSave ||
-      current_bubble_type_ == IbanBubbleType::kUploadSave) {
+      current_bubble_type_ == IbanBubbleType::kUploadSave ||
+      current_bubble_type_ == IbanBubbleType::kUploadInProgress) {
     autofill_metrics::SaveIbanPromptResult metric;
     switch (closed_reason) {
       case PaymentsUiClosedReason::kAccepted:
@@ -326,7 +327,9 @@
     }
     autofill_metrics::LogSaveIbanPromptResultMetric(
         metric, is_reshow_,
-        /*is_upload_save=*/current_bubble_type_ == IbanBubbleType::kUploadSave);
+        /*is_upload_save=*/
+        (current_bubble_type_ == IbanBubbleType::kUploadSave ||
+         current_bubble_type_ == IbanBubbleType::kUploadInProgress));
   }
 
   if (current_bubble_type_ == IbanBubbleType::kUploadCompleted) {
diff --git a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl_unittest.cc
index ef635f3..d008eb18 100644
--- a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "components/autofill/core/browser/data_model/payments/iban.h"
 #include "components/autofill/core/browser/metrics/payments/iban_metrics.h"
+#include "components/autofill/core/browser/payments/test_legal_message_line.h"
 #include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -48,7 +49,16 @@
   void ShowLocalSaveBubble(const Iban& iban) {
     controller()->OfferLocalSave(
         iban, /*should_show_prompt=*/true,
-        base::BindOnce(&IbanBubbleControllerImplTest::LocalSaveIbanCallback,
+        base::BindOnce(&IbanBubbleControllerImplTest::SaveIbanCallback,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void ShowUploadSaveBubble(const Iban& iban) {
+    LegalMessageLines legal_message = {
+        TestLegalMessageLine("google_test_legal_message")};
+    controller()->OfferUploadSave(
+        iban, legal_message, /*should_show_prompt=*/true,
+        base::BindOnce(&IbanBubbleControllerImplTest::SaveIbanCallback,
                        weak_ptr_factory_.GetWeakPtr()));
   }
 
@@ -78,7 +88,7 @@
   }
 
  private:
-  void LocalSaveIbanCallback(
+  void SaveIbanCallback(
       payments::PaymentsAutofillClient::SaveIbanOfferUserDecision user_decision,
       std::u16string_view nickname) {
     saved_nickname_ = nickname;
@@ -96,6 +106,14 @@
   EXPECT_EQ(nickname, saved_nickname());
 }
 
+TEST_F(IbanBubbleControllerImplTest, UploadIbanSavedSuccessfully) {
+  std::u16string nickname = u"My doctor's IBAN";
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  ClickSaveButton(nickname);
+
+  EXPECT_EQ(nickname, saved_nickname());
+}
+
 TEST_F(IbanBubbleControllerImplTest, Metrics_LocalIbanOffered) {
   base::HistogramTester histogram_tester;
   ShowLocalSaveBubble(autofill::test::GetLocalIban());
@@ -163,6 +181,73 @@
       "Autofill.SaveIbanPromptResult.Local.SavedWithNickname", false, 1);
 }
 
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanOffered) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+
+  histogram_tester.ExpectBucketCount(
+      "Autofill.SaveIbanPromptOffer.Upload.FirstShow",
+      autofill_metrics::SaveIbanPromptOffer::kShown, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanResult_Accepted) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  CloseBubble(PaymentsUiClosedReason::kAccepted);
+
+  histogram_tester.ExpectBucketCount(
+      "Autofill.SaveIbanPromptResult.Upload.FirstShow",
+      autofill_metrics::SaveIbanPromptResult::kAccepted, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanResult_Cancelled) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  CloseBubble(PaymentsUiClosedReason::kCancelled);
+
+  histogram_tester.ExpectBucketCount(
+      "Autofill.SaveIbanPromptResult.Upload.FirstShow",
+      autofill_metrics::SaveIbanPromptResult::kCancelled, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanResult_NotInteracted) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  CloseBubble(PaymentsUiClosedReason::kNotInteracted);
+
+  histogram_tester.ExpectBucketCount(
+      "Autofill.SaveIbanPromptResult.Upload.FirstShow",
+      autofill_metrics::SaveIbanPromptResult::kNotInteracted, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanResult_LostFocus) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  CloseBubble(PaymentsUiClosedReason::kLostFocus);
+
+  histogram_tester.ExpectBucketCount(
+      "Autofill.SaveIbanPromptResult.Upload.FirstShow",
+      autofill_metrics::SaveIbanPromptResult::kLostFocus, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanSaved_WithNickname) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  ClickSaveButton(u"My doctor's IBAN");
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveIbanPromptResult.Upload.SavedWithNickname", true, 1);
+}
+
+TEST_F(IbanBubbleControllerImplTest, Metrics_UploadIbanSaved_NoNickname) {
+  base::HistogramTester histogram_tester;
+  ShowUploadSaveBubble(autofill::test::GetServerIban());
+  ClickSaveButton(u"");
+
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.SaveIbanPromptResult.Upload.SavedWithNickname", false, 1);
+}
+
 // Test that confirmation prompt is auto-closed in 3 sec if the IBAN was
 // successfully saved to the server.
 TEST_F(IbanBubbleControllerImplTest, OnConfirmationPromptAutoClosed_Success) {
diff --git a/chrome/browser/ui/blocked_content/blocked_window_params.cc b/chrome/browser/ui/blocked_content/blocked_window_params.cc
index ed31f12..1910931 100644
--- a/chrome/browser/ui/blocked_content/blocked_window_params.cc
+++ b/chrome/browser/ui/blocked_content/blocked_window_params.cc
@@ -49,7 +49,7 @@
   nav_params.referrer = referrer_;
   nav_params.frame_name = frame_name_;
   nav_params.source_contents = web_contents;
-  nav_params.is_renderer_initiated = true;
+  nav_params.is_renderer_initiated = false;
   nav_params.window_action = NavigateParams::SHOW_WINDOW;
   nav_params.user_gesture = user_gesture_;
   nav_params.opened_by_another_window = !opener_suppressed_;
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 030f19fe..b3cf950 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -33,6 +33,7 @@
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/test_future.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
@@ -1396,8 +1397,8 @@
 
   // Set last What's New version to the current version so there is no What's
   // New tab shown on launch (for the non-first-run case).
-  g_browser_process->local_state()->SetInteger(prefs::kLastWhatsNewVersion,
-                                               CHROME_VERSION_MAJOR);
+  g_browser_process->local_state()->SetInteger(
+      prefs::kLastWhatsNewVersion, version_info::GetMajorVersionNumberAsInt());
 
   // Close the browser window.
   browser()->window()->Close();
diff --git a/chrome/browser/ui/browser_window/browser_window_features.cc b/chrome/browser/ui/browser_window/browser_window_features.cc
index 5dc0b4f..7b158e3 100644
--- a/chrome/browser/ui/browser_window/browser_window_features.cc
+++ b/chrome/browser/ui/browser_window/browser_window_features.cc
@@ -52,7 +52,7 @@
 #include "chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.h"
 #include "chrome/browser/ui/views/side_panel/history/history_side_panel_coordinator.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
-#include "chrome/browser/ui/views/tabs/glic_button.h"
+#include "chrome/browser/ui/views/tabs/tab_strip_action_container.h"
 #include "chrome/browser/ui/views/toolbar/chrome_labs/chrome_labs_coordinator.h"
 #include "chrome/browser/ui/views/translate/translate_bubble_controller.h"
 #include "chrome/common/chrome_features.h"
@@ -286,7 +286,7 @@
             browser_view->browser()->profile())) {
       glic_button_controller_ = std::make_unique<glic::GlicButtonController>(
           browser_view->GetProfile(),
-          browser_view->tab_strip_region_view()->GetGlicButton(),
+          browser_view->tab_strip_region_view()->GetTabStripActionContainer(),
           glic::GlicKeyedServiceFactory::GetGlicKeyedService(
               browser_view->GetProfile()));
     }
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc
index 7764a9e..1ab42cf 100644
--- a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc
+++ b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc
@@ -1513,25 +1513,6 @@
   testing::Mock::VerifyAndClearExpectations(mock());
 }
 
-TEST_F(CookieControlsUserBypassTest,
-       BlockingStatusLimitedWhenCookieControlsModePrefIsLimited) {
-  NavigateAndCommit(GURL("https://cool.things.com"));
-  EXPECT_CALL(*mock(),
-              OnStatusChanged(
-                  /*controls_visible=*/true, /*protections_on=*/true,
-                  CookieControlsEnforcement::kNoEnforcement,
-                  CookieBlocking3pcdStatus::kLimited, zero_expiration()));
-  EXPECT_CALL(*mock(), OnCookieControlsIconStatusChanged(
-                           /*icon_visible=*/false, /*protections_on=*/true,
-                           CookieBlocking3pcdStatus::kLimited,
-                           /*should_highlight=*/false));
-  profile()->GetPrefs()->SetInteger(
-      prefs::kCookieControlsMode,
-      static_cast<int>(content_settings::CookieControlsMode::kLimited));
-  cookie_controls()->Update(web_contents());
-  testing::Mock::VerifyAndClearExpectations(mock());
-}
-
 class CookieControlsUserBypassIncognitoTest
     : public CookieControlsUserBypassTest {
  public:
diff --git a/chrome/browser/ui/lens/BUILD.gn b/chrome/browser/ui/lens/BUILD.gn
index df718f8c..7dea46b0 100644
--- a/chrome/browser/ui/lens/BUILD.gn
+++ b/chrome/browser/ui/lens/BUILD.gn
@@ -199,7 +199,9 @@
 
   deps = [
     ":lens",
+    "//base/test:test_support",
     "//google_apis/common",
+    "//testing/gtest",
   ]
 }
 
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc
index 3993299..38beec27 100644
--- a/chrome/browser/ui/lens/lens_overlay_controller.cc
+++ b/chrome/browser/ui/lens/lens_overlay_controller.cc
@@ -3641,6 +3641,20 @@
           feature_engagement::kIPHLensOverlayUrlBlockFilters.Get()),
       &iph_url_filters_);
 
+  auto force_allow_url_strings = JSONArrayToVector(
+      feature_engagement::kIPHLensOverlayUrlForceAllowedUrlMatchPatterns.Get());
+  std::vector<base::MatcherStringPattern> force_allow_url_patterns;
+  std::vector<const base::MatcherStringPattern*> force_allow_url_pointers;
+  force_allow_url_patterns.reserve(force_allow_url_strings.size());
+  force_allow_url_pointers.reserve(force_allow_url_strings.size());
+  for (const std::string& entry : force_allow_url_strings) {
+    force_allow_url_patterns.emplace_back(entry, ++id);
+    force_allow_url_pointers.push_back(&force_allow_url_patterns.back());
+  }
+  forced_url_matcher_ = std::make_unique<url_matcher::RegexSetMatcher>();
+  // Pointers will not be referenced after AddPatterns() completes.
+  forced_url_matcher_->AddPatterns(force_allow_url_pointers);
+
   auto allow_strings = JSONArrayToVector(
       feature_engagement::kIPHLensOverlayUrlPathMatchAllowPatterns.Get());
   std::vector<base::MatcherStringPattern> allow_patterns;
@@ -3701,10 +3715,16 @@
   if (!tutorial_iph_url_matcher_) {
     return false;
   }
+
+  // Check if the URL matches any of the allow filters. If it does not,
+  // return false immediately as this should not be a shown match.
   auto matches = tutorial_iph_url_matcher_.get()->MatchURL(url);
   if (!matches.size()) {
     return false;
   }
+
+  // Now that the URL is allowed, check if it matches any of the block filters.
+  // If it does, return false as to block this URL from showing the IPH.
   for (auto match : matches) {
     // Blocks take precedence over allows.
     if (!iph_url_filters_[match].allow) {
@@ -3712,14 +3732,34 @@
     }
   }
 
+  // Now that the URL is an allowed URL, verify the match is not blocked by
+  // the block matcher. If it does contain blocked words in its path, return
+  // false to prevent the IPH from being shown.
   if (page_path_block_matcher_ && !page_path_block_matcher_->IsEmpty() &&
       page_path_block_matcher_->Match(url.path(), &matches)) {
     return false;
   }
+
+  // Check if the URL matches any of the forced allowed URLs. If it does, return
+  // true as this should be a shown match even if the path does not contain an
+  // allowlisted pattern (below).
+  if (forced_url_matcher_ && !forced_url_matcher_->IsEmpty() &&
+      forced_url_matcher_->Match(url.spec(), &matches)) {
+    return true;
+  }
+
+  // Finally, check if the URL matches any of the allowed patterns. If it
+  // doesn't, return false to prevent the IPH from being shown.
   if (page_path_allow_matcher_ && !page_path_allow_matcher_->IsEmpty() &&
       !page_path_allow_matcher_->Match(url.path(), &matches)) {
     return false;
   }
+
+  // Finally if all checks pass, this must be a valid match. I.e.:
+  // 1. The URL matches at least one of the allowed URLs.
+  // 2. The URL does not match any of the blocked URLs.
+  // 3. The URL does not match any of the block path patterns.
+  // 4. The URL matches at least one of the allowed path patterns.
   return true;
 }
 
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.h b/chrome/browser/ui/lens/lens_overlay_controller.h
index fc3da6e9..f2c10352 100644
--- a/chrome/browser/ui/lens/lens_overlay_controller.h
+++ b/chrome/browser/ui/lens/lens_overlay_controller.h
@@ -1411,6 +1411,11 @@
   // Matcher for URLs that are eligible to have the tutorial IPH shown.
   std::unique_ptr<url_matcher::URLMatcher> tutorial_iph_url_matcher_;
 
+  // Matcher for URLs that are do not need to pass the check for allowed paths.
+  // Instead, if they match the tutorial_iph_url_matcher_` and do not contain
+  // any of the blocked paths, they are considered matches.
+  std::unique_ptr<url_matcher::RegexSetMatcher> forced_url_matcher_;
+
   // Matcher for URL paths that are eligible to have the tutorial IPH shown.
   std::unique_ptr<url_matcher::RegexSetMatcher> page_path_allow_matcher_;
 
diff --git a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
index a2254625..927b693 100644
--- a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
+++ b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
@@ -8327,10 +8327,11 @@
          {feature_engagement::kIPHLensOverlayFeature,
           {
               {"x_url_allow_filters", "[\"*\"]"},
-              {"x_url_block_filters", "[\"a.com/login\",\"d.com\"]"},
+              {"x_url_block_filters", "[\"a.com/login\",\"d.com\",\"e.edu\"]"},
               {"x_url_path_match_allow_patterns",
                "[\"assignment\",\"homework\"]"},
               {"x_url_path_match_block_patterns", "[\"tutor\"]"},
+              {"x_url_forced_allowed_match_patterns", "[\"edu/.+\"]"},
           }}},
         /*disabled_features=*/{});
   }
@@ -8372,6 +8373,23 @@
       GURL("https://www.a.com/login/assignments")));
   EXPECT_FALSE(controller->IsUrlEligibleForTutorialIPHForTesting(
       GURL("https://www.d.com/homework")));
+
+  // x_url_forced_allowed_match_patterns is blocked by the block url filters.
+  EXPECT_FALSE(controller->IsUrlEligibleForTutorialIPHForTesting(
+      GURL("https://www.e.edu/tutor")));
+  // x_url_forced_allowed_match_patterns is blocked by the block path filters.
+  EXPECT_FALSE(controller->IsUrlEligibleForTutorialIPHForTesting(
+      GURL("https://www.d.edu/tutor")));
+  // x_url_forced_allowed_match_patterns skips the allowed path filters.
+  EXPECT_TRUE(controller->IsUrlEligibleForTutorialIPHForTesting(
+      GURL("https://www.d.edu/something")));
+  // URL not in x_url_forced_allowed_match_patterns and not in allowed path
+  // filters.
+  EXPECT_FALSE(controller->IsUrlEligibleForTutorialIPHForTesting(
+      GURL("https://www.d.edu/")));
+  // URL in x_url_forced_allowed_match_patterns and in allowed path filters.
+  EXPECT_TRUE(controller->IsUrlEligibleForTutorialIPHForTesting(
+      GURL("https://www.d.edu/homework")));
 }
 
 class LensOverlayControllerBrowserSimplifiedSelectionTest
diff --git a/chrome/browser/ui/lens/lens_overlay_query_controller.cc b/chrome/browser/ui/lens/lens_overlay_query_controller.cc
index bacd895f..21b98407 100644
--- a/chrome/browser/ui/lens/lens_overlay_query_controller.cc
+++ b/chrome/browser/ui/lens/lens_overlay_query_controller.cc
@@ -562,6 +562,16 @@
   return payload;
 }
 
+std::string Base64EncodeRequestId(lens::LensOverlayRequestId request_id) {
+  std::string serialized_request_id;
+  CHECK(request_id.SerializeToString(&serialized_request_id));
+  std::string encoded_request_id;
+  base::Base64UrlEncode(serialized_request_id,
+                        base::Base64UrlEncodePolicy::OMIT_PADDING,
+                        &encoded_request_id);
+  return encoded_request_id;
+}
+
 }  // namespace
 
 PageContent::PageContent() : content_type_(lens::MimeType::kUnknown) {}
@@ -875,6 +885,23 @@
   SendSemanticEventGen204IfEnabled(event, request_id);
 }
 
+void LensOverlayQueryController::RunSuggestInputsCallback() {
+  suggest_inputs_.set_send_gsession_vsrid_for_contextual_suggest(
+      lens::features::GetLensOverlaySendLensInputsForContextualSuggest());
+  suggest_inputs_.set_send_gsession_vsrid_vit_for_lens_suggest(
+      lens::features::GetLensOverlaySendLensInputsForLensSuggest());
+  suggest_inputs_.set_send_vsint_for_lens_suggest(
+      lens::features::
+          GetLensOverlaySendLensVisualInteractionDataForLensSuggest());
+  if (cluster_info_.has_value()) {
+    suggest_inputs_.set_search_session_id(cluster_info_->search_session_id());
+  } else {
+    suggest_inputs_.clear_search_session_id();
+  }
+  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE, base::BindOnce(suggest_inputs_callback_, suggest_inputs_));
+}
+
 void LensOverlayQueryController::ResetRequestClusterInfoStateForTesting() {
   ResetRequestClusterInfoState();
 }
@@ -945,13 +972,7 @@
   std::unique_ptr<lens::LensOverlayRequestId> request_id =
       request_id_generator_->GetNextRequestId(
           RequestIdUpdateMode::kOpenInNewTab);
-  std::string serialized_request_id;
-  CHECK(request_id->SerializeToString(&serialized_request_id));
-  std::string encoded_request_id;
-  base::Base64UrlEncode(serialized_request_id,
-                        base::Base64UrlEncodePolicy::OMIT_PADDING,
-                        &encoded_request_id);
-  return encoded_request_id;
+  return Base64EncodeRequestId(*request_id);
 }
 
 std::unique_ptr<lens::LensOverlayRequestId>
@@ -961,12 +982,7 @@
   latest_request_id_ = *request_id.get();
   latest_encoded_analytics_id_ =
       request_id_generator_->GetBase32EncodedAnalyticsId();
-  std::string serialized_request_id;
-  CHECK(request_id->SerializeToString(&serialized_request_id));
-  std::string encoded_request_id;
-  base::Base64UrlEncode(serialized_request_id,
-                        base::Base64UrlEncodePolicy::OMIT_PADDING,
-                        &encoded_request_id);
+  std::string encoded_request_id = Base64EncodeRequestId(*request_id);
   suggest_inputs_.set_encoded_request_id(encoded_request_id);
   RunSuggestInputsCallback();
   return request_id;
@@ -1050,17 +1066,19 @@
   cluster_info_->set_server_session_id(server_response.server_session_id());
   cluster_info_->set_search_session_id(server_response.search_session_id());
 
-  // Update the suggest inputs with the cluster info's search session id.
-  RunSuggestInputsCallback();
-
   // If routing info is enabled, store the routing info to be included in
   // followup requests.
   if (lens::features::IsLensOverlayRoutingInfoEnabled() &&
       server_response.has_routing_info() &&
       !request_id_generator_->HasRoutingInfo()) {
-    request_id_generator_->SetRoutingInfo(server_response.routing_info());
+    std::unique_ptr<lens::LensOverlayRequestId> request_id =
+        request_id_generator_->SetRoutingInfo(server_response.routing_info());
+    suggest_inputs_.set_encoded_request_id(Base64EncodeRequestId(*request_id));
   }
 
+  // Update the suggest inputs with the cluster info's search session id.
+  RunSuggestInputsCallback();
+
   // Clear the cluster info after its lifetime expires.
   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
       FROM_HERE,
@@ -1334,7 +1352,10 @@
     if (lens::features::IsLensOverlayRoutingInfoEnabled() &&
         cluster_info_->has_routing_info() &&
         !request_id_generator_->HasRoutingInfo()) {
-      request_id_generator_->SetRoutingInfo(cluster_info_->routing_info());
+      std::unique_ptr<lens::LensOverlayRequestId> new_request_id =
+          request_id_generator_->SetRoutingInfo(cluster_info_->routing_info());
+      suggest_inputs_.set_encoded_request_id(
+          Base64EncodeRequestId(*new_request_id));
     }
   }
 
@@ -2016,6 +2037,7 @@
     // enabled and the image signals feature flag is disabled.
     suggest_inputs_.set_encoded_image_signals(
         server_response.interaction_response().encoded_response());
+    RunSuggestInputsCallback();
   }
 
   if (lens::features::IsSimplifiedSelectionEnabled() &&
@@ -2333,28 +2355,13 @@
   cluster_info_.reset();
   query_controller_state_ = QueryControllerState::kClusterInfoExpired;
   request_id_generator_->ResetRequestId();
+  suggest_inputs_.Clear();
+  RunSuggestInputsCallback();
   parent_query_sent_ = false;
   is_first_page_contents_request_ = true;
   is_first_partial_page_contents_request_ = true;
 }
 
-void LensOverlayQueryController::RunSuggestInputsCallback() {
-  suggest_inputs_.set_send_gsession_vsrid_for_contextual_suggest(
-      lens::features::GetLensOverlaySendLensInputsForContextualSuggest());
-  suggest_inputs_.set_send_gsession_vsrid_vit_for_lens_suggest(
-      lens::features::GetLensOverlaySendLensInputsForLensSuggest());
-  suggest_inputs_.set_send_vsint_for_lens_suggest(
-      lens::features::
-          GetLensOverlaySendLensVisualInteractionDataForLensSuggest());
-  if (cluster_info_.has_value()) {
-    suggest_inputs_.set_search_session_id(cluster_info_->search_session_id());
-  } else {
-    suggest_inputs_.clear_search_session_id();
-  }
-  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(suggest_inputs_callback_, suggest_inputs_));
-}
-
 void LensOverlayQueryController::OnFullImageEndpointFetcherCreated(
     lens::LensOverlayRequestId request_id,
     std::unique_ptr<EndpointFetcher> endpoint_fetcher) {
diff --git a/chrome/browser/ui/lens/lens_overlay_query_controller.h b/chrome/browser/ui/lens/lens_overlay_query_controller.h
index a7766fe..c235423 100644
--- a/chrome/browser/ui/lens/lens_overlay_query_controller.h
+++ b/chrome/browser/ui/lens/lens_overlay_query_controller.h
@@ -211,6 +211,14 @@
     return partial_page_contents_request_start_time_;
   }
 
+  lens::LensOverlayRequestIdGenerator* request_id_generator_for_testing() {
+    return request_id_generator_.get();
+  }
+
+  lens::proto::LensOverlaySuggestInputs suggest_inputs_for_testing() {
+    return suggest_inputs_;
+  }
+
  protected:
   // Returns the EndpointFetcher to use with the given params. Protected to
   // allow overriding in tests to mock server responses.
@@ -250,6 +258,11 @@
       lens::mojom::SemanticEvent event,
       std::optional<lens::LensOverlayRequestId> request_id);
 
+  // Updates the suggest inputs with the feature params and latest cluster info
+  // response, then runs the callback. The request id in the suggest inputs will
+  // if the parameter is not null.
+  virtual void RunSuggestInputsCallback();
+
   // The callback for full image requests, including upon query flow start
   // and interaction retries.
   LensOverlayFullImageResponseCallback full_image_callback_;
@@ -594,11 +607,6 @@
   // Resets the request cluster info state.
   void ResetRequestClusterInfoState();
 
-  // Updates the suggest inputs with the feature params and latest cluster info
-  // response, then runs the callback. The request id in the suggest inputs will
-  // if the parameter is not null.
-  void RunSuggestInputsCallback();
-
   // Callback for when the interaction response returned text that should be
   // passed to the overlay.
   void RunInteractionResponseTextReceivedCallback(lens::mojom::TextPtr text);
diff --git a/chrome/browser/ui/lens/lens_overlay_request_id_generator.cc b/chrome/browser/ui/lens/lens_overlay_request_id_generator.cc
index 88171d34..6239c898 100644
--- a/chrome/browser/ui/lens/lens_overlay_request_id_generator.cc
+++ b/chrome/browser/ui/lens/lens_overlay_request_id_generator.cc
@@ -77,15 +77,9 @@
     }
   }
 
-  auto request_id = std::make_unique<lens::LensOverlayRequestId>();
-  request_id->set_uuid(uuid_);
-  request_id->set_sequence_id(sequence_id_);
+  std::unique_ptr<lens::LensOverlayRequestId> request_id =
+      GetCurrentRequestId();
   request_id->set_analytics_id(analytics_id_to_set);
-  request_id->set_long_context_id(long_context_id_);
-  request_id->set_image_sequence_id(image_sequence_id_);
-  if (routing_info_.has_value()) {
-    request_id->mutable_routing_info()->CopyFrom(routing_info_.value());
-  }
   return request_id;
 }
 
@@ -94,9 +88,24 @@
                               base32::Base32EncodePolicy::OMIT_PADDING);
 }
 
-void LensOverlayRequestIdGenerator::SetRoutingInfo(
+std::unique_ptr<lens::LensOverlayRequestId>
+LensOverlayRequestIdGenerator::SetRoutingInfo(
     lens::LensOverlayRoutingInfo routing_info) {
   routing_info_ = routing_info;
+  return GetCurrentRequestId();
 }
 
+std::unique_ptr<lens::LensOverlayRequestId>
+LensOverlayRequestIdGenerator::GetCurrentRequestId() {
+  auto request_id = std::make_unique<lens::LensOverlayRequestId>();
+  request_id->set_uuid(uuid_);
+  request_id->set_sequence_id(sequence_id_);
+  request_id->set_analytics_id(analytics_id_);
+  request_id->set_long_context_id(long_context_id_);
+  request_id->set_image_sequence_id(image_sequence_id_);
+  if (routing_info_.has_value()) {
+    request_id->mutable_routing_info()->CopyFrom(routing_info_.value());
+  }
+  return request_id;
+}
 }  // namespace lens
diff --git a/chrome/browser/ui/lens/lens_overlay_request_id_generator.h b/chrome/browser/ui/lens/lens_overlay_request_id_generator.h
index 30287f8..0370144 100644
--- a/chrome/browser/ui/lens/lens_overlay_request_id_generator.h
+++ b/chrome/browser/ui/lens/lens_overlay_request_id_generator.h
@@ -11,8 +11,11 @@
 #include "third_party/lens_server_proto/lens_overlay_server.pb.h"
 #include "third_party/lens_server_proto/lens_overlay_service_deps.pb.h"
 
+
 namespace lens {
 
+class TestLensOverlayQueryController;
+
 // The update modes for the request id generator.
 enum class RequestIdUpdateMode {
   // Indicates that the request should be modified for the initial set of
@@ -63,12 +66,26 @@
   // Returns the current analytics id as a base32 encoded string.
   std::string GetBase32EncodedAnalyticsId();
 
-  // Sets the routing info to be included in the request id.
-  void SetRoutingInfo(lens::LensOverlayRoutingInfo routing_info);
+  // Sets the routing info to be included in the request id and returns the new
+  // request id with this routing info.
+  std::unique_ptr<lens::LensOverlayRequestId> SetRoutingInfo(
+      lens::LensOverlayRoutingInfo routing_info);
 
   bool HasRoutingInfo() { return routing_info_.has_value(); }
 
+ protected:
+  friend class TestLensOverlayQueryController;
+  // Returns the request id of the current requests stored in the request id
+  // generator.
+  std::unique_ptr<lens::LensOverlayRequestId> GetCurrentRequestIdForTesting() {
+    return GetCurrentRequestId();
+  }
+
  private:
+  // Returns the request id of the current requests stored in the request id
+  // generator.
+  std::unique_ptr<lens::LensOverlayRequestId> GetCurrentRequestId();
+
   // The current uuid. Valid for the duration of a Lens overlay session.
   uint64_t uuid_;
 
diff --git a/chrome/browser/ui/lens/test_lens_overlay_query_controller.cc b/chrome/browser/ui/lens/test_lens_overlay_query_controller.cc
index f734a5eb..425a98b 100644
--- a/chrome/browser/ui/lens/test_lens_overlay_query_controller.cc
+++ b/chrome/browser/ui/lens/test_lens_overlay_query_controller.cc
@@ -4,13 +4,18 @@
 
 #include "test_lens_overlay_query_controller.h"
 
+#include "base/base64url.h"
 #include "base/containers/span.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/protobuf_matchers.h"
 #include "components/lens/lens_features.h"
 #include "components/lens/lens_overlay_mime_type.h"
 #include "google_apis/common/api_error_codes.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/lens_server_proto/lens_overlay_service_deps.pb.h"
 
+using base::test::EqualsProto;
+
 namespace lens {
 
 constexpr char kPdfMimeType[] = "application/pdf";
@@ -70,7 +75,6 @@
                                  invocation_source,
                                  use_dark_mode,
                                  gen204_controller) {}
-
 TestLensOverlayQueryController::~TestLensOverlayQueryController() = default;
 
 void TestLensOverlayQueryController::StartQueryFlow(
@@ -329,4 +333,35 @@
   last_semantic_event_ = event;
   last_semantic_event_gen204_request_id_ = request_id;
 }
+
+void TestLensOverlayQueryController::RunSuggestInputsCallback() {
+  const lens::proto::LensOverlaySuggestInputs& last_suggest_inputs =
+      suggest_inputs_for_testing();
+  if (last_suggest_inputs.encoded_request_id().empty()) {
+    LensOverlayQueryController::RunSuggestInputsCallback();
+    return;
+  }
+
+  // Decode the request id from the SuggestInputs callback.
+  lens::LensOverlayRequestId latest_request_id;
+  std::string serialized_proto;
+  EXPECT_TRUE(base::Base64UrlDecode(
+      last_suggest_inputs.encoded_request_id(),
+      base::Base64UrlDecodePolicy::DISALLOW_PADDING, &serialized_proto));
+  EXPECT_TRUE(latest_request_id.ParseFromString(serialized_proto));
+
+  // Get the current request id from the request id generator.
+  std::unique_ptr<lens::LensOverlayRequestId> current_request_id =
+      request_id_generator_for_testing()->GetCurrentRequestIdForTesting();
+  // Verifies that the last request ids passed in the SuggestInputs callback are
+  // the same as current request id in the request id generator.
+  // This is to ensure the LensOverlayController is always updated with the
+  // latest request ids.
+  EXPECT_THAT(latest_request_id, EqualsProto(*current_request_id))
+      << "The latest request id passed in the SuggestInputs callback is not "
+         "the same as the current request id in the request id generator. Did "
+         "you call RunSuggestInputsCallback() after updating the request id?";
+
+  LensOverlayQueryController::RunSuggestInputsCallback();
+}
 }  // namespace lens
diff --git a/chrome/browser/ui/lens/test_lens_overlay_query_controller.h b/chrome/browser/ui/lens/test_lens_overlay_query_controller.h
index d2ff206..27949a1 100644
--- a/chrome/browser/ui/lens/test_lens_overlay_query_controller.h
+++ b/chrome/browser/ui/lens/test_lens_overlay_query_controller.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_LENS_TEST_LENS_OVERLAY_QUERY_CONTROLLER_H_
 #define CHROME_BROWSER_UI_LENS_TEST_LENS_OVERLAY_QUERY_CONTROLLER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "components/endpoint_fetcher/endpoint_fetcher.h"
 #include "lens_overlay_query_controller.h"
 
@@ -281,6 +282,8 @@
       lens::mojom::SemanticEvent event,
       std::optional<lens::LensOverlayRequestId> request_id) override;
 
+  void RunSuggestInputsCallback() override;
+
   // The fake response to return for cluster info requests.
   lens::LensOverlayServerClusterInfoResponse fake_cluster_info_response_;
 
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index b2aba90..e4b81bc 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -19,6 +19,7 @@
 #include "base/rand_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/trace_event/typed_macros.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
@@ -62,6 +63,8 @@
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.h"
 #include "chrome/browser/ui/omnibox/omnibox_tab_helper.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/pref_names.h"
 #include "components/bookmarks/browser/bookmark_model.h"
@@ -429,11 +432,24 @@
       omnibox_feature_configs::HappinessTrackingSurveyForOmniboxOnFocusZps::
           Get()
               .survey_delay;
-  HatsService* hats_service =
-      HatsServiceFactory::GetForProfile(profile_, /*create_if_necessary=*/true);
+  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&ChromeOmniboxClient::CheckConditionsAndLaunchSurvey,
+                     weak_factory_.GetWeakPtr()),
+      base::Milliseconds(survey_delay_time_ms));
+}
+
+void ChromeOmniboxClient::CheckConditionsAndLaunchSurvey() {
   // Roll the dice as we want to show one of two surveys to the treatment
   // group but only one survey to the control group.
   bool show_happiness_survey = base::RandInt(0, 1) == 0;
+
+  // Don't show the suggestions utility survey to control group.
+  if (!omnibox_feature_configs::OmniboxUrlSuggestionsOnFocus::Get().enabled &&
+      !show_happiness_survey) {
+    return;
+  }
+
   // Get channel string to return as PSD.
   std::string channel;
   switch (chrome::GetChannel()) {
@@ -452,35 +468,36 @@
     default:
       channel = "unknown";
   }
-  if (omnibox_feature_configs::OmniboxUrlSuggestionsOnFocus::Get().enabled) {
-    if (show_happiness_survey) {
-      hats_service->LaunchDelayedSurvey(
-          kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness,
-          survey_delay_time_ms, {},
-          {{"page classification",
-            metrics::OmniboxEventProto::PageClassification_Name(
-                classification)},
-           {"channel", channel}});
-    } else {
-      hats_service->LaunchDelayedSurvey(
-          kHatsSurveyTriggerOnFocusZpsSuggestionsUtility, survey_delay_time_ms,
-          {},
-          {{"page classification",
-            metrics::OmniboxEventProto::PageClassification_Name(
-                classification)},
-           {"channel", channel}});
-    }
-  } else {
-    // Control
-    if (show_happiness_survey) {
-      hats_service->LaunchDelayedSurvey(
-          kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness,
-          survey_delay_time_ms, {},
-          {{"page classification",
-            metrics::OmniboxEventProto::PageClassification_Name(
-                classification)},
-           {"channel", channel}});
-    }
+
+  const std::string& survey_trigger =
+      show_happiness_survey ? kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness
+                            : kHatsSurveyTriggerOnFocusZpsSuggestionsUtility;
+
+  HatsService* hats_service =
+      HatsServiceFactory::GetForProfile(profile_, /*create_if_necessary=*/true);
+
+  if (!browser_) {
+    return;
+  }
+
+  auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
+
+  if (!browser_view) {
+    return;
+  }
+
+  auto* location_bar_view = browser_view->GetLocationBarView();
+
+  // Don't show the HaTS survey if the location bar has focus.
+  if (location_bar_view &&
+      !location_bar_view->Contains(
+          location_bar_view->GetFocusManager()->GetFocusedView())) {
+    hats_service->LaunchSurvey(
+        survey_trigger, base::DoNothing(), base::DoNothing(), {},
+        {{"page classification",
+          metrics::OmniboxEventProto::PageClassification_Name(
+              GetPageClassification(/*is_prefetch=*/false))},
+         {"channel", channel}});
   }
 }
 
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
index b20f314..1156032 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -77,6 +77,7 @@
   void OnKeywordModeChanged(bool entered,
                             const std::u16string& keyword) override;
   void MaybeShowOnFocusHatsSurvey(AutocompleteProviderClient* client) override;
+  void CheckConditionsAndLaunchSurvey();
   void OnResultChanged(const AutocompleteResult& result,
                        bool default_match_changed,
                        bool should_prerender,
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
index 1160ab4..77fbd80 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -52,6 +52,7 @@
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tab_dialogs.h"
 #include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/user_education/browser_user_education_interface.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
@@ -83,6 +84,7 @@
 #include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/user_education/common/feature_promo/feature_promo_controller.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -215,10 +217,21 @@
     return;
   }
 
-  if (!IsSavingPromptBlockedExplicitlyOrImplicitly()) {
+  const auto saving_prompt_status = GetSavingPromptStatus();
+  if (saving_prompt_status == SavingPromptStatus::kCanShow) {
     bubble_status_ = BubbleStatus::SHOULD_POP_UP;
   }
   UpdateBubbleAndIconVisibility();
+  const GURL url = web_contents()->GetLastCommittedURL();
+  if (saving_prompt_status == SavingPromptStatus::kExplicitlyBlocklisted &&
+      ChromePasswordManagerClient::CanShowBubbleOnURL(url)) {
+    if (auto* const user_education =
+            BrowserUserEducationInterface::MaybeGetForWebContentsInTab(
+                web_contents())) {
+      user_education->MaybeShowFeaturePromo(
+          feature_engagement::kIPHPasswordsSaveRecoveryPromoFeature);
+    }
+  }
 }
 
 void ManagePasswordsUIController::OnUpdatePasswordSubmitted(
@@ -1031,15 +1044,15 @@
     return;
   }
   if (GetState() == password_manager::ui::PENDING_PASSWORD_STATE) {
-    if (!IsSavingPromptBlockedExplicitlyOrImplicitly()) {
+    if (GetSavingPromptStatus() == SavingPromptStatus::kCanShow) {
       bubble_status_ = BubbleStatus::SHOULD_POP_UP;
     }
     UpdateBubbleAndIconVisibility();
   }
 }
 
-bool ManagePasswordsUIController::IsSavingPromptBlockedExplicitlyOrImplicitly()
-    const {
+ManagePasswordsUIController::SavingPromptStatus
+ManagePasswordsUIController::GetSavingPromptStatus() const {
   PasswordFormManagerForUI* form_manager = passwords_data_.form_manager();
   DCHECK(form_manager);
   auto logger = GetSaveProgressLogger(passwords_data_.client());
@@ -1048,19 +1061,20 @@
     if (logger.has_value()) {
       logger->LogMessage(Logger::STRING_SAVING_BLOCKLISTED_EXPLICITLY);
     }
-    return true;
+    return SavingPromptStatus::kExplicitlyBlocklisted;
   }
 
   const password_manager::InteractionsStats* stats =
       GetCurrentInteractionStats();
   const int show_threshold =
       password_bubble_experiment::GetSmartBubbleDismissalThreshold();
-  const bool is_implicitly_blocklisted =
+  const bool is_implicitly_blocked =
       stats && show_threshold > 0 && stats->dismissal_count >= show_threshold;
-  if (is_implicitly_blocklisted && logger.has_value()) {
+  if (is_implicitly_blocked && logger.has_value()) {
     logger->LogMessage(Logger::STRING_SAVING_BLOCKLISTED_BY_SMART_BUBBLE);
   }
-  return is_implicitly_blocklisted;
+  return is_implicitly_blocked ? SavingPromptStatus::kImplicitlyBlocked
+                               : SavingPromptStatus::kCanShow;
 }
 
 void ManagePasswordsUIController::AuthenticateUserWithMessage(
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
index 2f05162..3e18afa9 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -295,12 +295,22 @@
     SHOULD_POP_UP_WITH_FOCUS,
   };
 
+  // The status of the saving prompt.
+  enum class SavingPromptStatus {
+    // The prompt can show.
+    kCanShow,
+    // The current site is explicitly blocklisted.
+    kExplicitlyBlocklisted,
+    // The bubble for the current site is implicitly blocked.
+    kImplicitlyBlocked
+  };
+
   // Returns whether saving credentials prompts for the current form in
   // |passwords_data_| is blocked due to explicit action of the user asking to
   // never save passwords for this form, or because the user ignored the bubble
   // multiple times that the browser will automatically suppress further save
   // prompts.
-  bool IsSavingPromptBlockedExplicitlyOrImplicitly() const;
+  SavingPromptStatus GetSavingPromptStatus() const;
 
   // Returns the timeout for the manual save fallback.
   static base::TimeDelta GetTimeoutForSaveFallback();
diff --git a/chrome/browser/ui/safety_hub/revoked_permissions_service.cc b/chrome/browser/ui/safety_hub/revoked_permissions_service.cc
index 5a39c56..511388f 100644
--- a/chrome/browser/ui/safety_hub/revoked_permissions_service.cc
+++ b/chrome/browser/ui/safety_hub/revoked_permissions_service.cc
@@ -756,11 +756,12 @@
       static_cast<RevokedPermissionsService::RevokedPermissionsResult*>(
           result.get());
   recently_unused_permissions_ = interim_result->GetRecentlyUnusedPermissions();
-  RevokeUnusedPermissions();
-  if (disruptive_notification_manager_) {
-    disruptive_notification_manager_->RevokeDisruptiveNotifications();
+  if (IsUnusedSiteAutoRevocationEnabled()) {
+    RevokeUnusedPermissions();
+    if (disruptive_notification_manager_) {
+      disruptive_notification_manager_->RevokeDisruptiveNotifications();
+    }
   }
-  // TODO(crbug.com/40250875): Clean up these checks.
   if (IsAbusiveNotificationAutoRevocationEnabled()) {
     abusive_notification_manager_->CheckNotificationPermissionOrigins();
   }
@@ -919,9 +920,7 @@
 }
 
 void RevokedPermissionsService::RevokeUnusedPermissions() {
-  if (!IsUnusedSiteAutoRevocationEnabled()) {
-    return;
-  }
+  CHECK(IsUnusedSiteAutoRevocationEnabled());
 
   // Set this to true to prevent `OnContentSettingChanged` from removing
   // revoked setting values during auto-revocation.
diff --git a/chrome/browser/ui/safety_hub/revoked_permissions_service_unittest.cc b/chrome/browser/ui/safety_hub/revoked_permissions_service_unittest.cc
index bd10cb5c..5b6f0ee 100644
--- a/chrome/browser/ui/safety_hub/revoked_permissions_service_unittest.cc
+++ b/chrome/browser/ui/safety_hub/revoked_permissions_service_unittest.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/safety_hub/abusive_notification_permissions_manager.h"
 #include "chrome/browser/ui/safety_hub/mock_safe_browsing_database_manager.h"
 #include "chrome/browser/ui/safety_hub/revoked_permissions_service_factory.h"
+#include "chrome/browser/ui/safety_hub/safety_hub_constants.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_prefs.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_service.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_test_util.h"
@@ -399,6 +400,22 @@
         constraint);
   }
 
+  void SetupProposedRevokedDisruptiveNotificationSite(
+      std::string url,
+      base::TimeDelta lifetime =
+          content_settings::features::
+              kSafetyCheckUnusedSitePermissionsRevocationCleanUpThreshold
+                  .Get()) {
+    content_settings::ContentSettingConstraints constraint(clock()->Now());
+    constraint.set_lifetime(lifetime);
+    hcsm()->SetWebsiteSettingDefaultScope(
+        GURL(url), GURL(url),
+        ContentSettingsType::REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS,
+        base::Value(base::Value::Dict().Set(
+            safety_hub::kRevokedStatusDictKeyStr, safety_hub::kProposedStr)),
+        constraint);
+  }
+
   void UndoRegrantPermissionsForUrl(
       std::string url,
       std::set<ContentSettingsType> permission_types,
@@ -468,6 +485,19 @@
         CONTENT_SETTING_ASK);
   }
 
+  void ExpectProposedRevokedDisruptiveNotificationSettingValues(
+      std::string url) {
+    base::Value stored_value = hcsm()->GetWebsiteSetting(
+        GURL(url), GURL(url),
+        ContentSettingsType::REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS);
+    EXPECT_FALSE(stored_value.is_none());
+    ASSERT_TRUE(stored_value.is_dict());
+    EXPECT_EQ(safety_hub::kProposedStr,
+              stored_value.GetDict()
+                  .Find(safety_hub::kRevokedStatusDictKeyStr)
+                  ->GetString());
+  }
+
   void ExpectCleanedUpDisruptiveNotificationSettingValues(
       std::string url,
       bool is_regranted = false) {
@@ -713,6 +743,56 @@
   }
 }
 
+TEST_P(RevokedPermissionsServiceTest,
+       UnusedSitePermissionsRevocationDisabledTest) {
+  base::test::ScopedFeatureList scoped_feature;
+  scoped_feature.InitAndEnableFeature(
+      content_settings::features::kSafetyCheckUnusedSitePermissions);
+
+  // Disable auto-revocation by setting kUnusedSitePermissionsRevocationEnabled
+  // pref to false and turning off safe browsing. This should stop the repeated
+  // timer.
+  prefs()->SetBoolean(safety_hub_prefs::kUnusedSitePermissionsRevocationEnabled,
+                      false);
+
+  auto* history_service = HistoryServiceFactory::GetForProfile(
+      profile(), ServiceAccessType::EXPLICIT_ACCESS);
+  history_service->AddPage(GURL(url1), clock()->Now(),
+                           history::VisitSource::SOURCE_BROWSED);
+  if (ShouldSetupUnusedSites()) {
+    SetTrackedContentSettingForType(url1, geolocation_type);
+  }
+
+  // Travel through time for 70 days so that permissions would be revoked (if
+  // the check was enabled).
+  clock()->Advance(base::Days(70));
+
+  if (ShouldSetupAbusiveNotificationSites()) {
+    SetupAbusiveNotificationSite(url2, ContentSetting::CONTENT_SETTING_ALLOW);
+  }
+
+  if (ShouldSetupDisruptiveSites()) {
+    SetupProposedRevokedDisruptiveNotificationSite(url3);
+  }
+
+  safety_hub_test_util::UpdateRevokedPermissionsServiceAsync(service());
+
+  // Abusive notification permissions should be revoked (the setting doesn't
+  // change that).
+  if (ShouldSetupAbusiveNotificationSites()) {
+    ExpectRevokedAbusiveNotificationPermissionSize(1U);
+    ExpectRevokedAbusiveNotificationSettingValues(url2);
+  } else {
+    ExpectRevokedAbusiveNotificationPermissionSize(0U);
+  }
+
+  // Permissions should not be revoked.
+  EXPECT_EQ(GetRevokedUnusedPermissions(hcsm()).size(), 0u);
+  if (ShouldSetupDisruptiveSites()) {
+    ExpectProposedRevokedDisruptiveNotificationSettingValues(url3);
+  }
+}
+
 TEST_P(RevokedPermissionsServiceTest, TrackOnlySingleOriginTest) {
   std::string example_url1 = "https://example1.com";
   std::string example_url2 = "https://[*.]example2.com";
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index e107551f..a0758be 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/test/mock_log.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -178,7 +179,8 @@
 
 void DisableWhatsNewPage() {
   PrefService* pref_service = g_browser_process->local_state();
-  pref_service->SetInteger(prefs::kLastWhatsNewVersion, CHROME_VERSION_MAJOR);
+  pref_service->SetInteger(prefs::kLastWhatsNewVersion,
+                           version_info::GetMajorVersionNumberAsInt());
 }
 
 Browser* OpenNewBrowser(Profile* profile) {
diff --git a/chrome/browser/ui/tabs/BUILD.gn b/chrome/browser/ui/tabs/BUILD.gn
index 61b3a98c..f74a0325 100644
--- a/chrome/browser/ui/tabs/BUILD.gn
+++ b/chrome/browser/ui/tabs/BUILD.gn
@@ -261,6 +261,7 @@
       "split_tab_data.h",
       "split_tab_visual_data.h",
       "tab_collection.h",
+      "tab_collection_node.h",
       "tab_collection_storage.h",
       "tab_renderer_data.h",
       "tab_style.h",
@@ -313,6 +314,7 @@
       "split_tab_data.cc",
       "split_tab_visual_data.cc",
       "tab_collection.cc",
+      "tab_collection_node.cc",
       "tab_collection_storage.cc",
       "tab_dialog_manager.cc",
       "tab_features.cc",
diff --git a/chrome/browser/ui/tabs/tab_collection_node.cc b/chrome/browser/ui/tabs/tab_collection_node.cc
new file mode 100644
index 0000000..0bba0a2
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_collection_node.cc
@@ -0,0 +1,43 @@
+// Copyright 2025 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/tab_collection_node.h"
+
+#include <memory>
+#include <variant>
+
+#include "base/check.h"
+#include "chrome/browser/ui/tabs/tab_collection.h"
+#include "components/tabs/public/tab_collection_node_interface.h"
+#include "components/tabs/public/tab_interface.h"
+
+namespace tabs {
+
+TabCollectionNode::TabCollectionNode(
+    std::unique_ptr<TabInterface> tab_interface)
+    : holder_(std::move(tab_interface)) {}
+
+TabCollectionNode::TabCollectionNode(
+    std::unique_ptr<TabCollection> tab_collection)
+    : holder_(std::move(tab_collection)) {}
+
+TabCollectionNode::~TabCollectionNode() = default;
+
+TabCollectionNode::Type TabCollectionNode::GetType() const {
+  return std::holds_alternative<std::unique_ptr<TabInterface>>(holder_)
+             ? TabCollectionNode::Type::kTabInterface
+             : TabCollectionNode::Type::kTabCollection;
+}
+
+TabInterface* TabCollectionNode::GetTabInterface() const {
+  CHECK_EQ(GetType(), Type::kTabInterface);
+  return std::get<std::unique_ptr<TabInterface>>(holder_).get();
+}
+
+TabCollection* TabCollectionNode::GetTabCollection() const {
+  CHECK_EQ(GetType(), Type::kTabCollection);
+  return std::get<std::unique_ptr<TabCollection>>(holder_).get();
+}
+
+}  // namespace tabs
diff --git a/chrome/browser/ui/tabs/tab_collection_node.h b/chrome/browser/ui/tabs/tab_collection_node.h
new file mode 100644
index 0000000..f02e213
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_collection_node.h
@@ -0,0 +1,38 @@
+// Copyright 2025 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_TAB_COLLECTION_NODE_H_
+#define CHROME_BROWSER_UI_TABS_TAB_COLLECTION_NODE_H_
+
+#include <memory>
+#include <variant>
+
+#include "components/tabs/public/tab_collection_node_interface.h"
+
+namespace tabs {
+
+class TabCollection;
+class TabInterface;
+
+class TabCollectionNode : public TabCollectionNodeInterface {
+ public:
+  explicit TabCollectionNode(std::unique_ptr<TabInterface> tab_interface);
+  explicit TabCollectionNode(std::unique_ptr<TabCollection> tab_collection);
+  ~TabCollectionNode() override;
+
+  TabCollectionNode(const TabCollectionNode&) = delete;
+  void operator=(const TabCollectionNode&) = delete;
+
+  Type GetType() const override;
+  TabInterface* GetTabInterface() const override;
+  TabCollection* GetTabCollection() const override;
+
+ private:
+  std::variant<std::unique_ptr<TabInterface>, std::unique_ptr<TabCollection>>
+      holder_;
+};
+
+}  // namespace tabs
+
+#endif  // CHROME_BROWSER_UI_TABS_TAB_COLLECTION_NODE_H_
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 0d222b1a..94d1542 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -1937,7 +1937,7 @@
   AddItemWithStringIdAndVectorIcon(this, IDC_PRINT, IDS_PRINT, kPrintMenuIcon);
 
 #if BUILDFLAG(ENABLE_GLIC)
-  if (glic::GlicEnabling::IsProfileEligible(browser_->profile())) {
+  if (glic::GlicEnabling::IsEnabledForProfile(browser_->profile())) {
     AddItemWithStringIdAndVectorIcon(this, IDC_OPEN_GLIC,
                                      IDS_GLIC_THREE_DOT_MENU_ITEM,
                                      glic::GlicVectorIconManager::GetVectorIcon(
diff --git a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
index cffa0a2f..33686bee 100644
--- a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
+++ b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
@@ -47,7 +47,7 @@
     // the entry in the Extensions Menu.
     kMenuEntry = 2,
 
-    // The action was invoked by the user activiating (via mouse or keyboard)
+    // The action was invoked by the user activating (via mouse or keyboard)
     // the entry in the legacy overflow (3-dot) menu.
     // Removed 2021/04.
     // kLegacyOverflowedEntry = 3,
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc
index a7c593cf..d0a3fa4 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc
@@ -151,6 +151,7 @@
     case FillingProduct::kAutofillAi:
     case FillingProduct::kPlusAddresses:
     case FillingProduct::kLoyaltyCard:
+    case FillingProduct::kIdentityCredential:
       label.SetMaximumWidthSingleLine(maximum_width_single_line);
       break;
     case FillingProduct::kCreditCard:
diff --git a/chrome/browser/ui/views/chrome_layout_provider.cc b/chrome/browser/ui/views/chrome_layout_provider.cc
index 1de71f8..749c84e 100644
--- a/chrome/browser/ui/views/chrome_layout_provider.cc
+++ b/chrome/browser/ui/views/chrome_layout_provider.cc
@@ -166,7 +166,7 @@
     case DISTANCE_RICH_HOVER_BUTTON_ICON_HORIZONTAL:
       return 8;
     case DISTANCE_TASK_MANAGER_SEARCH_BAR_ICON_AND_BUTTON_HORIZONTAL_SPACING:
-      return 12;
+      return 4;
     case DISTANCE_TASK_MANAGER_SEARCH_ICON_SIZE:
       return 20;
     case DISTANCE_TASK_MANAGER_SEARCH_BAR_MIN_WIDTH:
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1581303..2348b4c 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1518,6 +1518,17 @@
   multi_contents_view_->SetActiveIndex(relative_active_position);
 }
 
+void BrowserView::SwapTabsInActiveSplit() {
+  CHECK(multi_contents_view_);
+  const int active_index = browser_->tab_strip_model()->active_index();
+
+  std::optional<split_tabs::SplitTabId> split_tab_id =
+      browser_->tab_strip_model()->GetTabAtIndex(active_index)->GetSplit();
+
+  CHECK(split_tab_id.has_value());
+  browser_->tab_strip_model()->SwapTabsInSplit(split_tab_id.value());
+}
+
 bool BrowserView::IsTabChangeInSplitView(content::WebContents* old_contents,
                                          content::WebContents* new_contents) {
   return multi_contents_view_ && multi_contents_view_->IsInSplitView() &&
@@ -3818,6 +3829,38 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, TabStripModelObserver implementation:
 
+void BrowserView::OnSplitTabContentsUpdated(
+    split_tabs::SplitTabId split_id,
+    std::vector<std::pair<tabs::TabInterface*, int>> prev_tabs,
+    std::vector<std::pair<tabs::TabInterface*, int>> new_tabs) {
+  // If the updated split is not active, do nothing.
+  if (const tabs::TabInterface* active_tab = browser_->GetActiveTabInterface();
+      !active_tab || !active_tab->IsSplit() ||
+      active_tab->GetSplit().value() != split_id) {
+    return;
+  }
+
+  split_tabs::SplitTabData* split_data =
+      browser_->tab_strip_model()->GetSplitData(split_id);
+  const int first_split_tab_index =
+      browser_->tab_strip_model()->GetIndexOfTab(split_data->ListTabs()[0]);
+  // Clear web contents for prev_tabs in preparation to reset for new_tabs.
+  for (std::pair<tabs::TabInterface*, int> split_tab_with_index : prev_tabs) {
+    int relative_index = split_tab_with_index.second - first_split_tab_index;
+    multi_contents_view_->SetWebContentsAtIndex(nullptr, relative_index);
+  }
+  // Set web contents in multi_contents_view_ to match new_tabs and update the
+  // active multi_contents_view_ index.
+  for (std::pair<tabs::TabInterface*, int> split_tab_with_index : new_tabs) {
+    int relative_index = split_tab_with_index.second - first_split_tab_index;
+    multi_contents_view_->SetWebContentsAtIndex(
+        split_tab_with_index.first->GetContents(), relative_index);
+    if (split_tab_with_index.first->IsActivated()) {
+      multi_contents_view_->SetActiveIndex(relative_index);
+    }
+  }
+}
+
 void BrowserView::TabChangedAt(content::WebContents* contents,
                                int index,
                                TabChangeType change_type) {
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 2127ff0..776dffd 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -487,6 +487,9 @@
   // Update the index of the active split based on the active tab's web contents
   void UpdateActiveSplitView();
 
+  // Reverses the order of the tabs in the active split.
+  void SwapTabsInActiveSplit();
+
   // True if an activation from `old_contents` to `new_contents` happens between
   // tabs that are already in a split-view configuration.
   bool IsTabChangeInSplitView(content::WebContents* old_contents,
@@ -715,6 +718,10 @@
       TabStripModel* tab_strip_model,
       const TabStripModelChange& change,
       const TabStripSelectionChange& selection) override;
+  void OnSplitTabContentsUpdated(
+      split_tabs::SplitTabId split_id,
+      std::vector<std::pair<tabs::TabInterface*, int>> prev_tabs,
+      std::vector<std::pair<tabs::TabInterface*, int>> new_tabs) override;
   void TabChangedAt(content::WebContents* contents,
                     int index,
                     TabChangeType change_type) override;
diff --git a/chrome/browser/ui/views/frame/multi_contents_resize_area.cc b/chrome/browser/ui/views/frame/multi_contents_resize_area.cc
index 123cde2b..de05c58d 100644
--- a/chrome/browser/ui/views/frame/multi_contents_resize_area.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_resize_area.cc
@@ -86,6 +86,13 @@
   SetPreferredSize(gfx::Size(kHandleWidth + kHandlePadding, kHandleHeight));
 }
 
+void MultiContentsResizeArea::OnMouseReleased(const ui::MouseEvent& event) {
+  ResizeArea::OnMouseReleased(event);
+  if (event.IsLeftMouseButton() && event.GetClickCount() == 2) {
+    multi_contents_view_->OnSwap();
+  }
+}
+
 bool MultiContentsResizeArea::OnKeyPressed(const ui::KeyEvent& event) {
   const int resize_increment = 50;
   if (event.key_code() == ui::VKEY_LEFT) {
diff --git a/chrome/browser/ui/views/frame/multi_contents_resize_area.h b/chrome/browser/ui/views/frame/multi_contents_resize_area.h
index a34d1f7..fa291687 100644
--- a/chrome/browser/ui/views/frame/multi_contents_resize_area.h
+++ b/chrome/browser/ui/views/frame/multi_contents_resize_area.h
@@ -43,6 +43,8 @@
 
   explicit MultiContentsResizeArea(MultiContentsView* multi_contents_view);
 
+  // views::ResizeArea:
+  void OnMouseReleased(const ui::MouseEvent& event) override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   void OnMouseMoved(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
diff --git a/chrome/browser/ui/views/frame/multi_contents_view.cc b/chrome/browser/ui/views/frame/multi_contents_view.cc
index 8aa2e87..7d489e9 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/frame/multi_contents_view.h"
 
+#include <algorithm>
+
 #include "base/feature_list.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
@@ -22,15 +24,6 @@
 #include "ui/views/layout/flex_layout_types.h"
 #include "ui/views/view_class_properties.h"
 
-namespace {
-constexpr int kMinWebContentsWidth = 20;
-constexpr int kContentCornerRadius = 6;
-constexpr int kContentOutlineCornerRadius = 8;
-constexpr int kContentOutlineThickness = 1;
-constexpr int kSplitViewContentInset = 8;
-constexpr int kSplitViewContentPadding = 4;
-}  // namespace
-
 DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(MultiContentsView,
                                       kMultiContentsViewElementId);
 
@@ -87,7 +80,6 @@
 void MultiContentsView::SetWebContentsAtIndex(
     content::WebContents* web_contents,
     int index) {
-  CHECK(web_contents);
   CHECK(index >= 0 && index < 2);
   contents_container_views_[index]->GetContentsView()->SetWebContents(
       web_contents);
@@ -148,6 +140,20 @@
   }
 }
 
+void MultiContentsView::OnSwap() {
+  CHECK(IsInSplitView());
+  browser_view_->SwapTabsInActiveSplit();
+}
+
+void MultiContentsView::UpdateSplitRatio(double ratio) {
+  if (start_ratio_ == ratio) {
+    return;
+  }
+
+  start_ratio_ = ratio;
+  InvalidateLayout();
+}
+
 void MultiContentsView::OnResize(int resize_amount, bool done_resizing) {
   if (!initial_start_width_on_resize_.has_value()) {
     initial_start_width_on_resize_ =
@@ -166,15 +172,6 @@
   }
 }
 
-void MultiContentsView::UpdateSplitRatio(double ratio) {
-  if (start_ratio_ == ratio) {
-    return;
-  }
-
-  start_ratio_ = ratio;
-  InvalidateLayout();
-}
-
 // TODO(crbug.com/397777917): Consider using FlexSpecification weights and
 // interior margins instead of overriding layout once this bug is resolved.
 void MultiContentsView::Layout(PassKey) {
@@ -243,17 +240,23 @@
 
 MultiContentsView::ViewWidths MultiContentsView::ClampToMinWidth(
     ViewWidths widths) {
+  const int min_percentage =
+      kMinWebContentsWidthPercentage * browser_view_->GetBounds().width();
+  const int min_fixed_value = min_contents_width_for_testing_.has_value()
+                                  ? min_contents_width_for_testing_.value()
+                                  : kMinWebContentsWidth;
+  const int min_width = std::min(min_fixed_value, min_percentage);
   if (!IsInSplitView()) {
     // Don't clamp if in a single-view state, where other views should be 0
     // width.
     return widths;
   }
-  if (widths.start_width < kMinWebContentsWidth) {
-    const double diff = kMinWebContentsWidth - widths.start_width;
+  if (widths.start_width < min_width) {
+    const double diff = min_width - widths.start_width;
     widths.start_width += diff;
     widths.end_width -= diff;
-  } else if (widths.end_width < kMinWebContentsWidth) {
-    const double diff = kMinWebContentsWidth - widths.end_width;
+  } else if (widths.end_width < min_width) {
+    const double diff = min_width - widths.end_width;
     widths.end_width += diff;
     widths.start_width -= diff;
   }
diff --git a/chrome/browser/ui/views/frame/multi_contents_view.h b/chrome/browser/ui/views/frame/multi_contents_view.h
index a4300f6..8559c274 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view.h
+++ b/chrome/browser/ui/views/frame/multi_contents_view.h
@@ -92,6 +92,9 @@
   void ExecuteOnEachVisibleContentsView(
       base::RepeatingCallback<void(ContentsWebView*)> callback);
 
+  // If in a split view, swaps the order of the two contents views.
+  void OnSwap();
+
   void UpdateSplitRatio(double ratio);
 
   // views::ResizeAreaDelegate:
@@ -101,6 +104,10 @@
   void Layout(PassKey) override;
   void OnPaint(gfx::Canvas* canvas) override;
 
+  void SetMinWidthForTesting(int width) {
+    min_contents_width_for_testing_ = std::make_optional(width);
+  }
+
   ContentsWebView* start_contents_view_for_testing() const {
     return contents_container_views_[0]->GetContentsView();
   }
@@ -113,7 +120,17 @@
     return contents_container_views_[1]->GetContentsView();
   }
 
+  static int contents_inset_for_testing() { return kSplitViewContentInset; }
+
  private:
+  static constexpr int kMinWebContentsWidth = 200;
+  static constexpr double kMinWebContentsWidthPercentage = 0.1;
+  static constexpr int kContentCornerRadius = 6;
+  static constexpr int kContentOutlineCornerRadius = 8;
+  static constexpr int kContentOutlineThickness = 1;
+  static constexpr int kSplitViewContentInset = 8;
+  static constexpr int kSplitViewContentPadding = 4;
+
   // ContentsContainerView holds the ContentsWebView and the outlines and
   // minitoolbar when in split view.
   class ContentsContainerView : public views::View {
@@ -135,6 +152,9 @@
 
   ViewWidths GetViewWidths(gfx::Rect available_space);
 
+  // Clamps to the minimum of kMinWebContentsWidth or
+  // kMinWebContentsWidthPercentage multiplied by the window width. This allows
+  // for some flexibility when it comes to particularly narrow windows.
   ViewWidths ClampToMinWidth(ViewWidths widths);
 
   void UpdateContentsBorder();
@@ -170,6 +190,8 @@
   // Width of `start_contents_.contents_view_` when a resize action began.
   // Nullopt if not currently resizing.
   std::optional<double> initial_start_width_on_resize_;
+
+  std::optional<int> min_contents_width_for_testing_ = std::nullopt;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_MULTI_CONTENTS_VIEW_H_
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
index 163f479..4eb5bb2 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/numerics/clamped_math.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -18,6 +19,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/event_modifiers.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/views/test/views_test_utils.h"
@@ -39,8 +41,7 @@
     return result;
   }
 
-  auto CheckResizeKey(ui::KeyboardCode key_code,
-                      base::RepeatingCallback<bool(double, double)> check) {
+  auto CheckResizeValues(base::RepeatingCallback<bool(double, double)> check) {
     // MultiContentsView overrides Layout, causing an edge case where resizes
     // don't take effect until the next layout pass. Use PollView and
     // WaitForState to wait for the expected layout pass to be completed.
@@ -50,29 +51,69 @@
                                         kMultiContentsViewLayoutObserver);
 
     auto result = Steps(
-        FocusElement(
-            MultiContentsResizeHandle::kMultiContentsResizeHandleElementId),
-        SendKeyPress(
-            MultiContentsResizeHandle::kMultiContentsResizeHandleElementId,
-            key_code),
         PollView(kMultiContentsViewLayoutObserver,
                  MultiContentsView::kMultiContentsViewElementId,
                  [check](const MultiContentsView* multi_contents_view) -> bool {
                    double start_width =
                        multi_contents_view->start_contents_view_for_testing()
+                           ->parent()
                            ->size()
                            .width();
                    double end_width =
                        multi_contents_view->end_contents_view_for_testing()
+                           ->parent()
                            ->size()
                            .width();
                    return check.Run(start_width, end_width);
                  }),
         WaitForState(kMultiContentsViewLayoutObserver, true));
+    AddDescriptionPrefix(result, "CheckResizeValues()");
+    return result;
+  }
+
+  // Perform a check on the contents view sizes following a direct resize call
+  auto CheckResize(int resize_amount,
+                   base::RepeatingCallback<bool(double, double)> check) {
+    auto result = Steps(Do([resize_amount, this]() {
+                          multi_contents_view()->OnResize(resize_amount, true);
+                        }),
+                        CheckResizeValues(check));
+    AddDescriptionPrefix(result, "CheckResize()");
+    return result;
+  }
+
+  // Perform a check on the contents view sizes following a keyboard-triggered
+  // resize
+  auto CheckResizeKey(ui::KeyboardCode key_code,
+                      base::RepeatingCallback<bool(double, double)> check) {
+    auto result = Steps(
+        FocusElement(
+            MultiContentsResizeHandle::kMultiContentsResizeHandleElementId),
+        SendKeyPress(
+            MultiContentsResizeHandle::kMultiContentsResizeHandleElementId,
+            key_code),
+        CheckResizeValues(check));
     AddDescriptionPrefix(result, "CheckResizeKey()");
     return result;
   }
 
+  auto ResizeWindow(int width) {
+    auto result = Steps(Do([width, this]() {
+      BrowserView::GetBrowserViewForBrowser(browser())->SetContentsSize(
+          gfx::Size(width, 1000));
+    }));
+    AddDescriptionPrefix(result, "ResizeWindow()");
+    return result;
+  }
+
+  auto SetMinWidth(int width) {
+    auto result = Steps(Do([width, this]() {
+      multi_contents_view()->SetMinWidthForTesting(width);
+    }));
+    AddDescriptionPrefix(result, "SetMinWidth()");
+    return result;
+  }
+
   auto CheckTabIsActive(int index) {
     return CheckResult([this]() { return tab_strip_model()->active_index(); },
                        index);
@@ -138,6 +179,41 @@
       EnterSplitView(2, 0), CheckTabIsActive(2), CheckActiveContentsHasFocus());
 }
 
+IN_PROC_BROWSER_TEST_F(MultiContentsViewUiTest, ResizesToMinWidth) {
+  RunTestSequence(
+      CreateTabsAndEnterSplitView(), ResizeWindow(1000),
+      // Artificially lower min width so that testing on smaller devices does
+      // not affect results.
+      SetMinWidth(60),
+      CheckResize(10000,
+                  base::BindRepeating([](double start_width, double end_width) {
+                    // On large window, uses flat min width.
+                    return end_width ==
+                           60 - MultiContentsView::contents_inset_for_testing();
+                  })));
+}
+
+// TODO(crbug.com/399212996): Flaky on linux_chromium_asan_rel_ng, linux-rel
+// and linux-chromeos-rel.
+#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
+#define MAYBE_ResizesToMinWidthPercentage DISABLED_ResizesToMinWidthPercentage
+#else
+#define MAYBE_ResizesToMinWidthPercentage ResizesToMinWidthPercentage
+#endif
+IN_PROC_BROWSER_TEST_F(MultiContentsViewUiTest,
+                       MAYBE_ResizesToMinWidthPercentage) {
+  RunTestSequence(
+      CreateTabsAndEnterSplitView(), ResizeWindow(500), SetMinWidth(60),
+      CheckResize(
+          10000, base::BindRepeating([](double start_width, double end_width) {
+            // On small window, uses percentage of window size vs. flat width
+            // for min. Don't check exact number to avoid rounding issues.
+            return end_width <
+                       (60 - MultiContentsView::contents_inset_for_testing()) &&
+                   end_width > 0;
+          })));
+}
+
 // TODO(crbug.com/399212996): Flaky on linux_chromium_asan_rel_ng and
 // chromium/ci/Linux Chromium OS ASan LSan Tests (1).
 #if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER)) && \
@@ -215,3 +291,65 @@
       SelectTab(kTabStripElementId, 1, InputType::kMouse, 0),
       CheckTabIsActive(0));
 }
+
+IN_PROC_BROWSER_TEST_F(MultiContentsViewUiTest,
+                       ResizeDoubleClickSwapsSplitViews) {
+  using MultiContentsViewSwapObserver =
+      views::test::PollingViewObserver<bool, MultiContentsView>;
+  DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(MultiContentsViewSwapObserver,
+                                      kMultiContentsViewSwapObserver);
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebContentsId);
+  RunTestSequence(
+      // Create a split view with and verify web contents are as expected and
+      // the active index is correct.
+      InstrumentTab(kWebContentsId),
+      NavigateWebContents(kWebContentsId, GURL(chrome::kChromeUINewTabURL)),
+      CreateTabsAndEnterSplitView(), Check([&]() {
+        return multi_contents_view()
+                   ->start_contents_view_for_testing()
+                   ->GetWebContents()
+                   ->GetVisibleURL() == GURL(chrome::kChromeUISettingsURL);
+      }),
+      Check([&]() {
+        return multi_contents_view()
+                   ->end_contents_view_for_testing()
+                   ->GetWebContents()
+                   ->GetVisibleURL() == GURL(chrome::kChromeUINewTabURL);
+      }),
+      CheckResult([this]() { return tab_strip_model()->active_index(); }, 0),
+      // Simulate a double click on the resize area to trigger the split tabs to
+      // swap.
+      Do([&]() {
+        auto* resize_area = multi_contents_view()->resize_area_for_testing();
+        gfx::Point center(resize_area->width() / 2, resize_area->height() / 2);
+        ui::MouseEvent press_event(
+            ui::EventType::kMousePressed, center, center, ui::EventTimeForNow(),
+            ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+        ui::MouseEvent release_event(ui::EventType::kMouseReleased, center,
+                                     center, ui::EventTimeForNow(),
+                                     ui::EF_LEFT_MOUSE_BUTTON,
+                                     ui::EF_LEFT_MOUSE_BUTTON);
+        press_event.SetClickCount(2);
+        release_event.SetClickCount(2);
+        resize_area->OnMousePressed(press_event);
+        resize_area->OnMouseReleased(release_event);
+      }),
+      // Verify the web contents in the split have swapped and the active index
+      // is correct.
+      PollView(kMultiContentsViewSwapObserver,
+               MultiContentsView::kMultiContentsViewElementId,
+               [&](const MultiContentsView* multi_contents_view) -> bool {
+                 bool first_web_contents_set =
+                     multi_contents_view->start_contents_view_for_testing()
+                         ->GetWebContents()
+                         ->GetVisibleURL() == GURL(chrome::kChromeUINewTabURL);
+                 bool second_web_contents_set =
+                     multi_contents_view->end_contents_view_for_testing()
+                         ->GetWebContents()
+                         ->GetVisibleURL() ==
+                     GURL(chrome::kChromeUISettingsURL);
+                 return first_web_contents_set && second_web_contents_set;
+               }),
+      WaitForState(kMultiContentsViewSwapObserver, true),
+      CheckResult([this]() { return tab_strip_model()->active_index(); }, 1));
+}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
index 0f84fb2..b5f74b0 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -26,23 +26,32 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "chrome/browser/ui/hats/mock_hats_service.h"
+#include "chrome/browser/ui/hats/survey_config.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_view_views.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/omnibox_controller.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_triggered_feature_service.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
+#include "components/omnibox/common/omnibox_feature_configs.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "components/security_interstitials/core/omnibox_https_upgrade_metrics.h"
+#include "components/unified_consent/pref_names.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test.h"
@@ -50,6 +59,7 @@
 #include "content/public/test/no_renderer_crashes_assertion.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/url_loader_interceptor.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/accessibility/ax_action_data.h"
@@ -88,6 +98,9 @@
 #include "ui/views/win/hwnd_util.h"
 #endif
 
+using ::testing::_;
+using ::testing::Return;
+
 namespace {
 
 void SetClipboardText(ui::ClipboardBuffer buffer, const std::u16string& text) {
@@ -105,6 +118,12 @@
   OmniboxViewViewsTest() = default;
   ~OmniboxViewViewsTest() override = default;
 
+  void SetUpOnMainThread() override {
+    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+    chrome::FocusLocationBar(browser());
+    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
+  }
+
   OmniboxTriggeredFeatureService* triggered_feature_service() {
     return &triggered_feature_service_;
   }
@@ -179,12 +198,6 @@
     command_line->AppendSwitchASCII(::switches::kForceDeviceScaleFactor, "1");
   }
 
-  void SetUpOnMainThread() override {
-    ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
-    chrome::FocusLocationBar(browser());
-    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX));
-  }
-
   gfx::NativeWindow GetRootWindow() const {
     gfx::NativeWindow native_window = browser()->window()->GetNativeWindow();
 #if defined(USE_AURA)
@@ -1273,3 +1286,99 @@
   histograms.ExpectTotalCount(
       security_interstitials::omnibox_https_upgrades::kEventHistogram, 0);
 }
+
+class OmniboxViewViewsOnFocusZpsTest : public OmniboxViewViewsTest {
+ public:
+  OmniboxViewViewsOnFocusZpsTest() = default;
+
+  // OmniboxViewViewsTest:
+  void SetUp() override {
+    omnibox_feature_configs::ScopedConfigForTesting<
+        omnibox_feature_configs::HappinessTrackingSurveyForOmniboxOnFocusZps>
+        survey_config;
+    survey_config.Get().enabled = true;
+    survey_config.Get().survey_delay = 0;
+
+    omnibox_feature_configs::ScopedConfigForTesting<
+        omnibox_feature_configs::OmniboxUrlSuggestionsOnFocus>
+        suggest_config;
+    suggest_config.Get().enabled = true;
+
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeature(
+        omnibox::kFocusTriggersWebAndSRPZeroSuggest);
+
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    OmniboxViewViewsTest::SetUpOnMainThread();
+    mock_hats_service_ = static_cast<MockHatsService*>(
+        HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+            browser()->profile(), base::BindRepeating(&BuildMockHatsService)));
+    ON_CALL(*mock_hats_service_, CanShowAnySurvey(_))
+        .WillByDefault(Return(true));
+    browser()->profile()->GetPrefs()->SetBoolean(
+        unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true);
+    browser()->profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled,
+                                                 true);
+  }
+
+  void TearDownOnMainThread() override { mock_hats_service_ = nullptr; }
+
+ protected:
+  MockHatsService* mock_hats_service() { return mock_hats_service_.get(); }
+
+ private:
+  raw_ptr<MockHatsService> mock_hats_service_;
+};
+
+IN_PROC_BROWSER_TEST_F(OmniboxViewViewsOnFocusZpsTest, ShowHatsSurvey) {
+  EXPECT_CALL(*mock_hats_service(), LaunchSurvey(_, _, _, _, _, _, _))
+      .Times(1)
+      .WillOnce(testing::Invoke(
+          [](const std::string& trigger, base::OnceClosure success_callback,
+             base::OnceClosure failure_callback,
+             const SurveyBitsData& product_specific_bits_data,
+             const SurveyStringData& product_specific_string_data,
+             const std::optional<std::string>& supplied_trigger_id,
+             const HatsService::SurveyOptions& survey_options) -> void {
+            EXPECT_TRUE(
+                trigger == kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness ||
+                trigger == kHatsSurveyTriggerOnFocusZpsSuggestionsUtility);
+          }));
+
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), GURL("https://test.com/")));
+
+  auto* location_bar = BrowserView::GetBrowserViewForBrowser(browser())
+                           ->toolbar()
+                           ->location_bar();
+
+  // After 5 focuses of the omnibox, the HaTS survey should show if the omnibox
+  // isn't still focused after the survey delay.
+  for (int i = 0; i < 5; i++) {
+    location_bar->omnibox_view()->RequestFocus();
+    location_bar->GetFocusManager()->ClearFocus();
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(OmniboxViewViewsOnFocusZpsTest,
+                       DontShowHatsSurveyIfOmniboxFocused) {
+  EXPECT_CALL(*mock_hats_service(), LaunchSurvey(_, _, _, _, _, _, _)).Times(0);
+
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), GURL("https://test.com/")));
+
+  auto* location_bar = BrowserView::GetBrowserViewForBrowser(browser())
+                           ->toolbar()
+                           ->location_bar();
+
+  for (int i = 0; i < 4; i++) {
+    location_bar->omnibox_view()->RequestFocus();
+    location_bar->GetFocusManager()->ClearFocus();
+  }
+  // On the fifth focus of the omnibox, the HaTS survey should not show since
+  // the omnibox is still focused.
+  location_bar->omnibox_view()->RequestFocus();
+}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index f3f595f58..38fa3108 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -32,10 +32,6 @@
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_test_util.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/hats/hats_service.h"
-#include "chrome/browser/ui/hats/hats_service_factory.h"
-#include "chrome/browser/ui/hats/mock_hats_service.h"
-#include "chrome/browser/ui/hats/survey_config.h"
 #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
@@ -337,7 +333,6 @@
   TestLocationBarModel* location_bar_model() { return &location_bar_model_; }
   CommandUpdaterImpl* command_updater() { return &command_updater_; }
   TestingOmniboxView* omnibox_view() const { return omnibox_view_; }
-  MockHatsService* mock_hats_service() { return mock_hats_service_.get(); }
 
   // TODO(tommycli): These base class accessors exist because Textfield and
   // OmniboxView both hide member functions that were public in base classes.
@@ -405,7 +400,6 @@
   std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<TestBrowserWindow> browser_window_;
   std::unique_ptr<Browser> browser_;
-  raw_ptr<MockHatsService> mock_hats_service_;
   std::unique_ptr<TemplateURLServiceFactoryTestUtil> util_;
   CommandUpdaterImpl command_updater_;
   TestLocationBarModel location_bar_model_;
@@ -471,10 +465,6 @@
   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
       profile_.get(),
       base::BindRepeating(&AutocompleteClassifierFactory::BuildInstanceFor));
-  mock_hats_service_ = static_cast<MockHatsService*>(
-      HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-          profile(), base::BindRepeating(&BuildMockHatsService)));
-  ON_CALL(*mock_hats_service_, CanShowAnySurvey(_)).WillByDefault(Return(true));
   auto omnibox_view = std::make_unique<TestingOmniboxView>(
       std::make_unique<ChromeOmniboxClient>(&location_bar_, browser(),
                                             profile()),
@@ -492,7 +482,6 @@
 
   location_bar()->set_omnibox_view(nullptr);
   omnibox_view_ = nullptr;
-  mock_hats_service_ = nullptr;
   browser_->tab_strip_model()->CloseAllTabs();
   browser_ = nullptr;
   browser_window_ = nullptr;
@@ -1140,45 +1129,6 @@
             node_data.GetStringAttribute(ax::mojom::StringAttribute::kValue));
 }
 
-TEST_F(OmniboxViewViewsTest, ShowHatsSurvey) {
-  profile()->GetPrefs()->SetBoolean(
-      unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true);
-  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
-
-  omnibox_feature_configs::ScopedConfigForTesting<
-      omnibox_feature_configs::HappinessTrackingSurveyForOmniboxOnFocusZps>
-      survey_config;
-  survey_config.Get().enabled = true;
-  survey_config.Get().survey_delay = 0;
-
-  omnibox_feature_configs::ScopedConfigForTesting<
-      omnibox_feature_configs::OmniboxUrlSuggestionsOnFocus>
-      suggest_config;
-  suggest_config.Get().enabled = true;
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      omnibox::kFocusTriggersWebAndSRPZeroSuggest);
-
-  EXPECT_CALL(*mock_hats_service(), LaunchDelayedSurvey(_, _, _, _))
-      .Times(1)
-      .WillOnce(testing::Invoke(
-          [](const std::string& trigger, int timeout_ms,
-             const SurveyBitsData& survey_specific_bits_data,
-             const SurveyStringData& survey_specific_string_data) -> bool {
-            EXPECT_TRUE(
-                trigger == kHatsSurveyTriggerOnFocusZpsSuggestionsHappiness ||
-                trigger == kHatsSurveyTriggerOnFocusZpsSuggestionsUtility);
-            return true;
-          }));
-
-  location_bar_model()->set_url(GURL("https://test.com/"));
-  for (int i = 0; i < 5; i++) {
-    omnibox_textfield()->OnFocus();
-    omnibox_textfield()->OnBlur();
-  }
-}
-
 class OmniboxViewViewsClipboardTest
     : public OmniboxViewViewsTest,
       public ::testing::WithParamInterface<ui::TextEditCommand> {
diff --git a/chrome/browser/ui/views/page_action/page_action_controller.cc b/chrome/browser/ui/views/page_action/page_action_controller.cc
index ba263bb..9456040b 100644
--- a/chrome/browser/ui/views/page_action/page_action_controller.cc
+++ b/chrome/browser/ui/views/page_action/page_action_controller.cc
@@ -42,12 +42,18 @@
       tab_interface.RegisterWillDeactivate(base::BindRepeating(
           &PageActionController::OnTabWillDeactivate, base::Unretained(this)));
   for (actions::ActionId id : action_ids) {
-    Register(id, tab_interface.IsActivated());
+    const PageActionProperties& properties =
+        properties_provider.GetProperties(id);
+    Register(id, tab_interface.IsActivated(), properties.is_ephemeral);
 
+    // It's safe to use base::Unretained here since the recorded is owned by
+    // this object.
     std::unique_ptr<PageActionMetricsRecorderInterface> metrics_recorder =
-        CreateMetricsRecorder(tab_interface,
-                              properties_provider.GetProperties(id),
-                              FindPageActionModel(id));
+        CreateMetricsRecorder(
+            tab_interface, properties, FindPageActionModel(id),
+            base::BindRepeating(
+                &PageActionController::GetVisibleEphemeralPageActionsCount,
+                base::Unretained(this)));
     metrics_recorders_.emplace(id, std::move(metrics_recorder));
   }
   if (pinned_actions_observation_.GetSource()) {
@@ -56,8 +62,10 @@
 }
 
 void PageActionController::Register(actions::ActionId action_id,
-                                    bool is_tab_active) {
-  std::unique_ptr<PageActionModelInterface> model = CreateModel(action_id);
+                                    bool is_tab_active,
+                                    bool is_ephemeral) {
+  std::unique_ptr<PageActionModelInterface> model =
+      CreateModel(action_id, is_ephemeral);
   model->SetTabActive(PassKey(), is_tab_active);
   page_actions_.emplace(action_id, std::move(model));
 }
@@ -197,11 +205,12 @@
 }
 
 std::unique_ptr<PageActionModelInterface> PageActionController::CreateModel(
-    actions::ActionId action_id) {
+    actions::ActionId action_id,
+    bool is_ephemeral) {
   if (page_action_model_factory_ != nullptr) {
-    return page_action_model_factory_->Create(action_id);
+    return page_action_model_factory_->Create(action_id, is_ephemeral);
   } else {
-    return std::make_unique<PageActionModel>();
+    return std::make_unique<PageActionModel>(is_ephemeral);
   }
 }
 
@@ -209,13 +218,17 @@
 PageActionController::CreateMetricsRecorder(
     tabs::TabInterface& tab_interface,
     const PageActionProperties& properties,
-    PageActionModelInterface& model) {
+    PageActionModelInterface& model,
+    VisibleEphemeralPageActionsCountCallback
+        visible_ephemeral_page_actions_count_callback) {
   if (page_action_metrics_recorder_factory_ != nullptr) {
-    return page_action_metrics_recorder_factory_->Create(tab_interface,
-                                                         properties, model);
+    return page_action_metrics_recorder_factory_->Create(
+        tab_interface, properties, model,
+        std::move(visible_ephemeral_page_actions_count_callback));
   } else {
-    return std::make_unique<PageActionMetricsRecorder>(tab_interface,
-                                                       properties, model);
+    return std::make_unique<PageActionMetricsRecorder>(
+        tab_interface, properties, model,
+        std::move(visible_ephemeral_page_actions_count_callback));
   }
 }
 
@@ -233,6 +246,17 @@
   id_and_recorder->second->RecordClick(trigger_source);
 }
 
+int PageActionController::GetVisibleEphemeralPageActionsCount() const {
+  int visible_ephemeral_page_actions_count = 0;
+  for (auto& [id, model] : page_actions_) {
+    CHECK(metrics_recorders_.contains(id));
+    if (model->GetVisible() && model->IsEphemeral()) {
+      ++visible_ephemeral_page_actions_count;
+    }
+  }
+  return visible_ephemeral_page_actions_count;
+}
+
 std::ostream& operator<<(std::ostream& os, const SuggestionChipConfig& config) {
   os << "{ should_animate: " << config.should_animate
      << ", should_announce_chip: " << config.should_announce_chip << " }";
diff --git a/chrome/browser/ui/views/page_action/page_action_controller.h b/chrome/browser/ui/views/page_action/page_action_controller.h
index d711f72..f32d537a 100644
--- a/chrome/browser/ui/views/page_action/page_action_controller.h
+++ b/chrome/browser/ui/views/page_action/page_action_controller.h
@@ -154,7 +154,9 @@
                std::unique_ptr<PageActionMetricsRecorderInterface>>;
 
   // Creates a page action model for the given id, and initializes it's values.
-  void Register(actions::ActionId action_id, bool is_tab_active);
+  void Register(actions::ActionId action_id,
+                bool is_tab_active,
+                bool is_ephemeral);
 
   PageActionModelInterface& FindPageActionModel(
       actions::ActionId action_id) const;
@@ -167,16 +169,23 @@
   void PinnedActionsModelChanged();
 
   std::unique_ptr<PageActionModelInterface> CreateModel(
-      actions::ActionId action_id);
+      actions::ActionId action_id,
+      bool is_ephemeral);
   std::unique_ptr<PageActionMetricsRecorderInterface> CreateMetricsRecorder(
       tabs::TabInterface& tab_interface,
       const PageActionProperties& properties,
-      PageActionModelInterface& model);
+      PageActionModelInterface& model,
+      VisibleEphemeralPageActionsCountCallback
+          visible_ephemeral_page_actions_count_callback);
 
   // Issues internally a metric recording for the provided `action_id`.
   void RecordClickMetric(actions::ActionId action_id,
                          PageActionTrigger trigger_source);
 
+  // Returns the number of page actions currently visual in the actual tab that
+  // are ephemeral.
+  int GetVisibleEphemeralPageActionsCount() const;
+
   const raw_ptr<PageActionModelFactory> page_action_model_factory_ = nullptr;
   const raw_ptr<PageActionMetricsRecorderFactory>
       page_action_metrics_recorder_factory_ = nullptr;
diff --git a/chrome/browser/ui/views/page_action/page_action_metric_recorder_unittest.cc b/chrome/browser/ui/views/page_action/page_action_metric_recorder_unittest.cc
index 9ded5ef..1289238 100644
--- a/chrome/browser/ui/views/page_action/page_action_metric_recorder_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_metric_recorder_unittest.cc
@@ -43,8 +43,10 @@
     properties_.type = PageActionIconType::kLensOverlay;
     properties_.is_ephemeral = is_ephemeral;
     properties_.histogram_name = "LensOverlay";
-    recorder_ = std::make_unique<PageActionMetricsRecorder>(tab_, properties_,
-                                                            mock_model_);
+    recorder_ = std::make_unique<PageActionMetricsRecorder>(
+        tab_, properties_, mock_model_,
+        base::BindRepeating(&PageActionMetricsRecorderTest::GetVisibleCount,
+                            base::Unretained(this)));
   }
 
   void FireModelChanged() { recorder_->OnPageActionModelChanged(mock_model_); }
@@ -53,6 +55,8 @@
     recorder_->RecordClick(trigger);
   }
 
+  int GetVisibleCount() const { return visible_count_; }
+
  protected:
   content::BrowserTaskEnvironment task_environment_;
   TestingProfile profile_;
@@ -60,6 +64,8 @@
   FakeTabInterface tab_;
   PageActionProperties properties_;
   std::unique_ptr<PageActionMetricsRecorder> recorder_;
+
+  int visible_count_ = 1;
 };
 
 TEST_F(PageActionMetricsRecorderTest, NoRecordIfNotEphemeral) {
@@ -223,5 +229,58 @@
                                      PageActionCTREvent::kClicked, 3);
 }
 
+TEST_F(PageActionMetricsRecorderTest,
+       NumberActionsShownWhenClicked_OneVisibleAction) {
+  base::HistogramTester histogram_tester;
+  CreateRecorder(/*is_ephemeral=*/true);
+
+  constexpr char kHistogram[] =
+      "PageActionController.Icon.NumberActionsShownWhenClicked";
+
+  // Simulate a click when exactly one ephemeral page action is visible.
+  visible_count_ = 1;
+  recorder_->RecordClick(PageActionTrigger::kMouse);
+
+  histogram_tester.ExpectTotalCount(kHistogram, 1);
+  histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/1,
+                                     /*expected_count=*/1);
+}
+
+TEST_F(PageActionMetricsRecorderTest,
+       NumberActionsShownWhenClicked_VariousVisibleCounts) {
+  base::HistogramTester histogram_tester;
+  CreateRecorder(/*is_ephemeral=*/true);
+
+  constexpr char kHistogram[] =
+      "PageActionController.Icon.NumberActionsShownWhenClicked";
+
+  // First click with 2 visible actions.
+  visible_count_ = 2;
+  recorder_->RecordClick(PageActionTrigger::kMouse);
+
+  // Second click with 5 visible actions.
+  visible_count_ = 5;
+  recorder_->RecordClick(PageActionTrigger::kKeyboard);
+
+  // Third click with 2 visible actions again.
+  visible_count_ = 2;
+  recorder_->RecordClick(PageActionTrigger::kGesture);
+
+  histogram_tester.ExpectTotalCount(kHistogram, 3);
+  histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/2,
+                                     /*expected_count=*/2);
+  histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/5,
+                                     /*expected_count=*/1);
+
+  // No other buckets should be populated.
+  for (int bucket = 0; bucket <= 20; ++bucket) {
+    if (bucket == 2 || bucket == 5) {
+      continue;
+    }
+    histogram_tester.ExpectBucketCount(kHistogram, bucket,
+                                       /*expected_count=*/0);
+  }
+}
+
 }  // namespace
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_metrics_recorder.cc b/chrome/browser/ui/views/page_action/page_action_metrics_recorder.cc
index 015a4fa3..b44f029 100644
--- a/chrome/browser/ui/views/page_action/page_action_metrics_recorder.cc
+++ b/chrome/browser/ui/views/page_action/page_action_metrics_recorder.cc
@@ -17,10 +17,14 @@
 PageActionMetricsRecorder::PageActionMetricsRecorder(
     tabs::TabInterface& tab_interface,
     const PageActionProperties& properties,
-    PageActionModelInterface& model)
+    PageActionModelInterface& model,
+    VisibleEphemeralPageActionsCountCallback
+        visible_ephemeral_page_actions_count_callback)
     : is_ephemeral_(properties.is_ephemeral),
       page_action_type_(properties.type),
       histogram_name_(properties.histogram_name),
+      visible_ephemeral_page_actions_count_callback_(
+          std::move(visible_ephemeral_page_actions_count_callback)),
       tab_interface_(tab_interface) {
   scoped_observation_.Observe(&model);
 }
@@ -76,6 +80,9 @@
   base::UmaHistogramEnumeration(
       base::StrCat({"PageActionController.", histogram_name_, ".Icon.CTR2"}),
       PageActionCTREvent::kClicked);
+  base::UmaHistogramExactLinear(
+      "PageActionController.Icon.NumberActionsShownWhenClicked",
+      visible_ephemeral_page_actions_count_callback_.Run(), 20);
 }
 
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_metrics_recorder.h b/chrome/browser/ui/views/page_action/page_action_metrics_recorder.h
index 47e672b..b67dacd 100644
--- a/chrome/browser/ui/views/page_action/page_action_metrics_recorder.h
+++ b/chrome/browser/ui/views/page_action/page_action_metrics_recorder.h
@@ -7,6 +7,8 @@
 
 #include <set>
 
+#include "base/functional/callback.h"
+#include "base/functional/callback_forward.h"
 #include "base/memory/raw_ref.h"
 #include "base/scoped_observation.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
@@ -22,6 +24,14 @@
 
 struct PageActionProperties;
 
+// Metrics may need to know the number of visible ephemeral page actions.
+// This information is not available to the local instance of the metrics
+// recorder, as it does not have visibility into the page action state. However,
+// the `PageActionController`, which owns the metrics recorder instance, can
+// determine that count. Therefore, a callback is used to retrieve the count
+// from the `PageActionController`.
+using VisibleEphemeralPageActionsCountCallback = base::RepeatingCallback<int()>;
+
 // Interface for PageActionMetricsRecorder, used for concrete implementation or
 // a mock for testing.
 class PageActionMetricsRecorderInterface {
@@ -39,7 +49,9 @@
   virtual std::unique_ptr<PageActionMetricsRecorderInterface> Create(
       tabs::TabInterface& tab_interface,
       const PageActionProperties& properties,
-      PageActionModelInterface& model) = 0;
+      PageActionModelInterface& model,
+      VisibleEphemeralPageActionsCountCallback
+          visible_ephemeral_page_actions_count_callback) = 0;
 };
 
 // Records visibility metrics for a specific page action, scoped to a single
@@ -48,9 +60,12 @@
 class PageActionMetricsRecorder : public PageActionMetricsRecorderInterface,
                                   public PageActionModelObserver {
  public:
-  explicit PageActionMetricsRecorder(tabs::TabInterface& tab_interface,
-                                     const PageActionProperties& properties,
-                                     PageActionModelInterface& model);
+  explicit PageActionMetricsRecorder(
+      tabs::TabInterface& tab_interface,
+      const PageActionProperties& properties,
+      PageActionModelInterface& model,
+      VisibleEphemeralPageActionsCountCallback
+          visible_ephemeral_page_actions_count_callback);
 
   PageActionMetricsRecorder(const PageActionMetricsRecorder&) = delete;
   PageActionMetricsRecorder operator=(const PageActionMetricsRecorder&) =
@@ -78,6 +93,11 @@
   PageActionIconType page_action_type_;
   std::string histogram_name_;
 
+  // Used to get count of visible ephemeral page actions from the
+  // `PageActionController`.
+  VisibleEphemeralPageActionsCountCallback
+      visible_ephemeral_page_actions_count_callback_;
+
   // The TabInterface is guaranteed valid for this object’s lifetime.
   const raw_ref<tabs::TabInterface> tab_interface_;
 
diff --git a/chrome/browser/ui/views/page_action/page_action_model.cc b/chrome/browser/ui/views/page_action/page_action_model.cc
index 6cf3af2b..a3c1cacb 100644
--- a/chrome/browser/ui/views/page_action/page_action_model.cc
+++ b/chrome/browser/ui/views/page_action/page_action_model.cc
@@ -15,7 +15,8 @@
 using ::actions::ActionItem;
 }  // namespace
 
-PageActionModel::PageActionModel() = default;
+PageActionModel::PageActionModel(bool is_ephemeral)
+    : is_ephemeral_(is_ephemeral) {}
 
 PageActionModel::~PageActionModel() {
   observer_list_.Notify(
@@ -216,4 +217,8 @@
                         *this);
 }
 
+bool PageActionModel::IsEphemeral() const {
+  return is_ephemeral_;
+}
+
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_model.h b/chrome/browser/ui/views/page_action/page_action_model.h
index 1397b25c..c57bf49 100644
--- a/chrome/browser/ui/views/page_action/page_action_model.h
+++ b/chrome/browser/ui/views/page_action/page_action_model.h
@@ -71,12 +71,14 @@
   virtual const std::u16string& GetTooltipText() const = 0;
   virtual const std::u16string& GetAccessibleName() const = 0;
   virtual bool GetActionItemIsShowingBubble() const = 0;
+
+  virtual bool IsEphemeral() const = 0;
 };
 
 // PageActionModel represents the page action's state, scoped to a single tab.
 class PageActionModel : public PageActionModelInterface {
  public:
-  PageActionModel();
+  explicit PageActionModel(bool is_ephemeral = false);
   PageActionModel(const PageActionModel&) = delete;
   PageActionModel& operator=(const PageActionModel&) = delete;
   ~PageActionModel() override;
@@ -130,10 +132,15 @@
   const std::u16string& GetTooltipText() const override;
   bool GetActionItemIsShowingBubble() const override;
 
+  bool IsEphemeral() const override;
+
  private:
   // Notifies observers of a model change.
   void NotifyChange();
 
+  // Represents whether this page action will be always visible or not.
+  const bool is_ephemeral_ = false;
+
   // Represents whether the tab this model belongs to is active.
   bool is_tab_active_ = false;
 
@@ -188,7 +195,9 @@
  public:
   virtual ~PageActionModelFactory() = default;
 
-  virtual std::unique_ptr<PageActionModelInterface> Create(int action_id) = 0;
+  virtual std::unique_ptr<PageActionModelInterface> Create(
+      int action_id,
+      bool is_ephemeral) = 0;
 };
 
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_view.cc b/chrome/browser/ui/views/page_action/page_action_view.cc
index 3d49e2a9..d2a0d7f 100644
--- a/chrome/browser/ui/views/page_action/page_action_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_view.cc
@@ -215,6 +215,21 @@
          observation_.GetSource()->GetActionItemIsShowingBubble();
 }
 
+bool PageActionView::IsTriggerableEvent(const ui::Event& event) {
+  // Returns whether the bubble should be shown given the event. Only trigger an
+  // action when action UI isn't already showing (managed at the
+  // IconLabelBubbleView level), and if mouse input, when event is a left button
+  // click.
+  if (event.IsMouseEvent()) {
+    // IconLabelBubbleView allows any mouse click to be triggerable event so
+    // need to manually check here.
+    return IconLabelBubbleView::IsTriggerableEvent(event) &&
+           ((GetTriggerableEventFlags() & event.flags()) != 0);
+  }
+
+  return IconLabelBubbleView::IsTriggerableEvent(event);
+}
+
 void PageActionView::OnLabelVisibilityChanged() {
   UpdateBackground();
   UpdateLabelColors();
diff --git a/chrome/browser/ui/views/page_action/page_action_view.h b/chrome/browser/ui/views/page_action/page_action_view.h
index 6e1ec60..1b6549b 100644
--- a/chrome/browser/ui/views/page_action/page_action_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_view.h
@@ -73,6 +73,7 @@
   void NotifyClick(const ui::Event& event) override;
   gfx::Size GetMinimumSize() const override;
   bool IsBubbleShowing() const override;
+  bool IsTriggerableEvent(const ui::Event& event) override;
 
   actions::ActionId GetActionId() const;
 
diff --git a/chrome/browser/ui/views/page_action/page_action_view_unittest.cc b/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
index c1857e64..045daf3 100644
--- a/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
@@ -34,6 +34,7 @@
 #include "ui/actions/actions.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/interaction/interaction_test_util.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/events/test/test_event.h"
 #include "ui/gfx/animation/animation.h"
@@ -508,6 +509,14 @@
   EXPECT_EQ(1, TotalTriggerCount());
 }
 
+TEST_F(PageActionViewTriggerTest, PageActionTriggersOnKeyboardClick) {
+  EXPECT_CALL(*model(), GetActionItemIsShowingBubble())
+      .WillRepeatedly(Return(false));
+  views::test::InteractionTestUtilSimulatorViews::PressButton(
+      page_action_view(), ui::test::InteractionTestUtil::InputType::kKeyboard);
+  EXPECT_EQ(1, TotalTriggerCount());
+}
+
 TEST_F(PageActionViewTriggerTest, PageActionTriggersOnMouseClick) {
   EXPECT_CALL(*model(), GetActionItemIsShowingBubble())
       .WillRepeatedly(Return(false));
@@ -516,8 +525,22 @@
   EXPECT_EQ(1, TotalTriggerCount());
 }
 
+TEST_F(PageActionViewTriggerTest, PageActionMouseRightClickIgnored) {
+  ui::MouseEvent mouse_press(ui::EventType::kMousePressed, gfx::Point(),
+                             gfx::Point(), ui::EventTimeForNow(),
+                             ui::EF_RIGHT_MOUSE_BUTTON,
+                             ui::EF_RIGHT_MOUSE_BUTTON);
+  ui::MouseEvent mouse_release(ui::EventType::kMouseReleased, gfx::Point(),
+                               gfx::Point(), ui::EventTimeForNow(),
+                               ui::EF_RIGHT_MOUSE_BUTTON,
+                               ui::EF_RIGHT_MOUSE_BUTTON);
+  page_action_view()->OnMouseEvent(&mouse_press);
+  page_action_view()->OnMouseEvent(&mouse_release);
+  EXPECT_EQ(0, TotalTriggerCount());
+}
+
 // Action invocations are suppressed when the ActionItem is displaying UI.
-TEST_F(PageActionViewTriggerTest, PageActionDoesNotTriggersIfBubbleShowing) {
+TEST_F(PageActionViewTriggerTest, PageActionDoesNotTriggerIfBubbleShowing) {
   EXPECT_CALL(*model(), GetActionItemIsShowingBubble())
       .WillRepeatedly(Return(true));
   views::test::InteractionTestUtilSimulatorViews::PressButton(
diff --git a/chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h b/chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h
index c792833..d1ebd82 100644
--- a/chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h
+++ b/chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h
@@ -86,12 +86,15 @@
               SetShouldHidePageAction,
               (base::PassKey<PageActionController>, bool should_hide),
               (override));
+  MOCK_METHOD(bool, IsEphemeral, (), (const, override));
 };
 
 template <typename PageActionModelType>
 class FakePageActionModelFactory : public PageActionModelFactory {
  public:
-  std::unique_ptr<PageActionModelInterface> Create(int action_id) override {
+  std::unique_ptr<PageActionModelInterface> Create(
+      int action_id,
+      bool /*is_ephemeral*/) override {
     auto model = std::make_unique<PageActionModelType>();
     model_map_.emplace(action_id, model.get());
     return model;
diff --git a/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.cc b/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.cc
index 6021122..9b7bc5a2 100644
--- a/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.cc
+++ b/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.cc
@@ -10,7 +10,9 @@
 NoopPageActionMetricsRecorderFactory::Create(
     tabs::TabInterface& tab_interface,
     const PageActionProperties& properties,
-    PageActionModelInterface& model) {
+    PageActionModelInterface& model,
+    VisibleEphemeralPageActionsCountCallback
+        visible_ephemeral_page_actions_count_callback) {
   return std::make_unique<NoopPageActionMetricsRecorder>();
 }
 
diff --git a/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.h b/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.h
index 37b54ff..4e1e978d 100644
--- a/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.h
+++ b/chrome/browser/ui/views/page_action/test_support/noop_page_action_metrics_recorder.h
@@ -29,7 +29,9 @@
   std::unique_ptr<PageActionMetricsRecorderInterface> Create(
       tabs::TabInterface& tab_interface,
       const PageActionProperties& properties,
-      PageActionModelInterface& model) override;
+      PageActionModelInterface& model,
+      VisibleEphemeralPageActionsCountCallback
+          visible_ephemeral_page_actions_count_callback) override;
 };
 
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
index 5e981585..18807036 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
@@ -115,7 +115,11 @@
 }
 
 void ManagePasswordsIconViews::OnExecuting(
-    PageActionIconView::ExecuteSource source) {}
+    PageActionIconView::ExecuteSource source) {
+  browser()->window()->NotifyFeaturePromoFeatureUsed(
+      feature_engagement::kIPHPasswordsSaveRecoveryPromoFeature,
+      FeaturePromoFeatureUsedAction::kClosePromoIfPresent);
+}
 
 bool ManagePasswordsIconViews::OnMousePressed(const ui::MouseEvent& event) {
   bool result = PageActionIconView::OnMousePressed(event);
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_icon_views.cc b/chrome/browser/ui/views/passwords/password_change/password_change_icon_views.cc
index 70764f0c..4c0bb65 100644
--- a/chrome/browser/ui/views/passwords/password_change/password_change_icon_views.cc
+++ b/chrome/browser/ui/views/passwords/password_change/password_change_icon_views.cc
@@ -13,11 +13,13 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_actions.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
 #include "chrome/browser/ui/views/passwords/password_bubble_view_base.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
@@ -109,7 +111,11 @@
 }
 
 void PasswordChangeIconViews::OnExecuting(
-    PageActionIconView::ExecuteSource source) {}
+    PageActionIconView::ExecuteSource source) {
+  browser()->window()->NotifyFeaturePromoFeatureUsed(
+      feature_engagement::kIPHPasswordsSaveRecoveryPromoFeature,
+      FeaturePromoFeatureUsedAction::kClosePromoIfPresent);
+}
 
 bool PasswordChangeIconViews::OnMousePressed(const ui::MouseEvent& event) {
   bool result = PageActionIconView::OnMousePressed(event);
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc
index e42793b..1a92844 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_view.cc
+++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/debug/stack_trace.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/password_manager/password_store_utils.h"
 #include "chrome/browser/profiles/profile.h"
@@ -67,6 +68,9 @@
          controller_.state() ==
              password_manager::ui::PENDING_PASSWORD_UPDATE_STATE);
 
+  LOG(WARNING) << "-------------------\n"
+               << base::debug::StackTrace(20).ToString();
+
   const password_manager::PasswordForm& password_form =
       controller_.pending_password();
   if (password_form.IsFederatedCredential()) {
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
index ea3a247..9db8c07 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/test/test_future.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_browser_main.h"
@@ -400,8 +401,9 @@
 
     // Avoid showing the What's New page. These tests assume this isn't the
     // first update and the NTP opens after sign in.
-    g_browser_process->local_state()->SetInteger(prefs::kLastWhatsNewVersion,
-                                                 CHROME_VERSION_MAJOR);
+    g_browser_process->local_state()->SetInteger(
+        prefs::kLastWhatsNewVersion,
+        version_info::GetMajorVersionNumberAsInt());
   }
 
   virtual void OnWillCreateBrowserContextServices(
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
index 1ab5ed0..4b208868 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
@@ -517,6 +517,8 @@
     model = empty_menu_.get();
   }
 
+  // `menu_` keeps a raw pointer to `click_action_menu_`. Clear that pointer.
+  menu_->SetModel(nullptr, /*send_signal=*/false);
   click_action_menu_ = std::make_unique<ui::SimpleMenuModel>(this);
   if (delegate_->HasClickAction() && !delegate_->GetToolTip().empty()) {
     click_action_menu_->AddItem(0, delegate_->GetToolTip());
diff --git a/chrome/browser/ui/views/tabs/glic_button.cc b/chrome/browser/ui/views/tabs/glic_button.cc
index dcecc2e42..1225954 100644
--- a/chrome/browser/ui/views/tabs/glic_button.cc
+++ b/chrome/browser/ui/views/tabs/glic_button.cc
@@ -85,17 +85,6 @@
 
 GlicButton::~GlicButton() = default;
 
-void GlicButton::SetShowState(bool show) {
-  show_state_ = show;
-
-  SetVisible(show_state_);
-
-  PreferredSizeChanged();
-}
-
-void GlicButton::SetIcon(const gfx::VectorIcon& icon) {
-  SetVectorIcon(icon);
-}
 
 void GlicButton::SetIsShowingNudge(bool is_showing) {
   if (is_showing) {
diff --git a/chrome/browser/ui/views/tabs/glic_button.h b/chrome/browser/ui/views/tabs/glic_button.h
index 6a1f1d98..dcddf49e 100644
--- a/chrome/browser/ui/views/tabs/glic_button.h
+++ b/chrome/browser/ui/views/tabs/glic_button.h
@@ -22,7 +22,6 @@
 // TabSearchButton for sizing and appropriate theming.
 
 class GlicButton : public TabStripNudgeButton,
-                   public GlicButtonControllerDelegate,
                    public views::ContextMenuController,
                    public ui::SimpleMenuModel::Delegate {
   METADATA_HEADER(GlicButton, TabStripNudgeButton)
@@ -39,10 +38,6 @@
   GlicButton& operator=(const GlicButton&) = delete;
   ~GlicButton() override;
 
-  // GlicButtonControllerDelegate:
-  void SetShowState(bool show) override;
-  void SetIcon(const gfx::VectorIcon& icon) override;
-
   // TabStripNudgeButton:
   void SetIsShowingNudge(bool is_showing) override;
 
@@ -104,10 +99,6 @@
   // Tab strip that contains this button.
   raw_ptr<TabStripController> tab_strip_controller_;
 
-  // Represents the show state of the button. Visibility of the button
-  // is reflected by the show state except when the nudge is showing.
-  bool show_state_ = true;
-
   // Callback which is invoked when the button is hovered (i.e., the user is
   // more likely to interact with it soon).
   base::RepeatingClosure hovered_callback_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc
index df7fe30..119ceb3 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_features.h"
+#include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/tabs/organization/tab_declutter_controller.h"
 #include "chrome/browser/ui/tabs/organization/tab_organization_service.h"
@@ -47,6 +48,7 @@
 #include "chrome/browser/glic/glic_profile_manager.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
 #include "chrome/browser/glic/resources/grit/glic_browser_resources.h"
+#include "chrome/browser/ui/tabs/tab_style.h"
 #endif  // BUILDFLAG(ENABLE_GLIC)
 namespace {
 
@@ -72,7 +74,7 @@
     "Tab.Organization.Declutter.Trigger.BucketedCTR";
 
 #if BUILDFLAG(ENABLE_GLIC)
-constexpr int kLargeSpaceBetweenButtons = 4;
+constexpr int kLargeSpaceBetweenButtons = 6;
 #endif  // BUILDFLAG(ENABLE_GLIC)
 
 }  // namespace
@@ -274,8 +276,26 @@
     glic_button_ = AddChildView(CreateGlicButton(tab_strip_controller));
 
     SetupButtonProperties(glic_button_);
+#if !BUILDFLAG(IS_MAC)
+    std::unique_ptr<views::Separator> separator =
+        std::make_unique<views::Separator>();
+    separator->SetBorderRadius(TabStyle::Get()->GetSeparatorMargins().right());
+    separator->SetPreferredSize(TabStyle::Get()->GetSeparatorSize());
+
+    separator->SetColorId(kColorTabDividerFrameActive);
+
+    subscriptions_.push_back(browser_window_interface->RegisterDidBecomeActive(
+        base::BindRepeating(&TabStripActionContainer::DidBecomeActive,
+                            base::Unretained(this))));
+    subscriptions_.push_back(
+        browser_window_interface->RegisterDidBecomeInactive(
+            base::BindRepeating(&TabStripActionContainer::DidBecomeInactive,
+                                base::Unretained(this))));
+    separator_ = AddChildView(std::move(separator));
+#endif  // !BUILDFLAG(IS_MAC)
   }
 #endif  // BUILDFLAG(ENABLE_GLIC)
+
   auto* const layout_manager =
       SetLayoutManager(std::make_unique<views::BoxLayout>());
   layout_manager->set_main_axis_alignment(
@@ -755,5 +775,30 @@
     glic_button_->SetBorder(views::CreateEmptyBorder(glic_border));
   }
 }
+
+void TabStripActionContainer::SetGlicShowState(bool show) {
+  if (glic_button_) {
+    glic_button_->SetVisible(show);
+  }
+  if (separator_) {
+    separator_->SetVisible(show);
+  }
+}
+
+void TabStripActionContainer::SetGlicIcon(const gfx::VectorIcon& icon) {
+  if (glic_button_) {
+    glic_button_->SetVectorIcon(icon);
+  }
+}
+
+void TabStripActionContainer::DidBecomeActive(BrowserWindowInterface* browser) {
+  separator_->SetColorId(kColorTabDividerFrameActive);
+}
+
+void TabStripActionContainer::DidBecomeInactive(
+    BrowserWindowInterface* browser) {
+  separator_->SetColorId(kColorTabDividerFrameInactive);
+}
+
 BEGIN_METADATA(TabStripActionContainer)
 END_METADATA
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container.h b/chrome/browser/ui/views/tabs/tab_strip_action_container.h
index a7d5b0b..7e03ba1b 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_action_container.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_action_container.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_ACTION_CONTAINER_H_
 
 #include "base/gtest_prod_util.h"
+#include "chrome/browser/glic/browser_ui/glic_button_controller_delegate.h"
 #include "chrome/browser/ui/tabs/glic_nudge_controller.h"
 #include "chrome/browser/ui/tabs/glic_nudge_observer.h"
 #include "chrome/browser/ui/tabs/organization/tab_declutter_controller.h"
@@ -16,6 +17,7 @@
 #include "ui/gfx/animation/animation.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/views/animation/animation_delegate_views.h"
+#include "ui/views/controls/separator.h"
 #include "ui/views/mouse_watcher.h"
 #include "ui/views/view.h"
 
@@ -32,7 +34,8 @@
                                 public views::AnimationDelegateViews,
                                 public views::MouseWatcherListener,
                                 public TabOrganizationObserver,
-                                public GlicNudgeObserver {
+                                public GlicNudgeObserver,
+                                public glic::GlicButtonControllerDelegate {
   METADATA_HEADER(TabStripActionContainer, views::View)
 
  public:
@@ -118,8 +121,15 @@
   // GlicNudgeObserver
   void OnTriggerGlicNudgeUI(std::string label) override;
 
+  // GlicButtonControllerDelegate:
+  void SetGlicShowState(bool show) override;
+  void SetGlicIcon(const gfx::VectorIcon& icon) override;
+
   void UpdateButtonBorders(gfx::Insets button_insets);
 
+  void DidBecomeActive(BrowserWindowInterface* browser);
+  void DidBecomeInactive(BrowserWindowInterface* browser);
+
  private:
   friend class TabStripActionContainerBrowserTest;
 
@@ -186,6 +196,7 @@
   raw_ptr<TabOrganizationService> tab_organization_service_ = nullptr;
   raw_ptr<tabs::TabDeclutterController> tab_declutter_controller_ = nullptr;
   raw_ptr<tabs::GlicNudgeController> glic_nudge_controller_ = nullptr;
+  raw_ptr<views::Separator> separator_ = nullptr;
 
   raw_ptr<glic::GlicButton> glic_button_ = nullptr;
 
@@ -212,6 +223,8 @@
   // Prevents other features from showing tabstrip-modal UI.
   std::unique_ptr<ScopedTabStripModalUI> scoped_tab_strip_modal_ui_;
 
+  std::list<base::CallbackListSubscription> subscriptions_;
+
   std::unique_ptr<TabStripNudgeAnimationSession> animation_session_;
 };
 
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 0504d40..8f458af 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
@@ -670,6 +670,18 @@
               "Triggered when the user navigates a page with an eligible login "
               "form, and they have no saved passwords.")));
 
+  // kIPHPasswordsSavePrimingPromo:
+  registry.RegisterFeature(
+      std::move(FeaturePromoSpecification::CreateForToastPromo(
+                    feature_engagement::kIPHPasswordsSaveRecoveryPromoFeature,
+                    kPasswordsOmniboxKeyIconElementId,
+                    IDS_PASSWORDS_SAVE_RECOVERY_PROMO_BODY,
+                    IDS_PASSWORDS_SAVE_RECOVERY_PROMO_SCREENREADER,
+                    FeaturePromoSpecification::AcceleratorInfo())
+                    .SetMetadata(137, "dfried@chromium.org",
+                                 "Triggered when the user logs into a page "
+                                 "they have blocklisted")));
+
   // kIPHPasswordsManagementBubbleAfterSaveFeature:
   registry.RegisterFeature(std::move(
       FeaturePromoSpecification::CreateForToastPromo(
diff --git a/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc b/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
index eb74a2e..cb83869 100644
--- a/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
+++ b/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
@@ -68,15 +68,9 @@
     return Do([&]() { SetZoomLevel(content::PAGE_ZOOM_RESET); });
   }
 
-  auto EnsureZoomBubblePresent() {
-    return CheckResult([&]() { return ZoomBubbleView::GetZoomBubble(); },
-                       testing::Ne(nullptr));
-  }
+  auto WaitForZoomBubbleShow() { return WaitForZoomBubble(/*visible=*/true); }
 
-  auto EnsureZoomBubbleNotPresent() {
-    return CheckResult([&]() { return ZoomBubbleView::GetZoomBubble(); },
-                       testing::Eq(nullptr));
-  }
+  auto WaitForZoomBubbleHide() { return WaitForZoomBubble(/*visible=*/false); }
 
   MultiStep WaitForZoomBubble(bool visible) {
     DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<bool>,
@@ -100,9 +94,8 @@
   // image.
   ui::ImageModel zoom_in_image;
   RunTestSequence(
-      EnsureZoomBubbleNotPresent(), DoZoomIn(),
-      CheckViewProperty(kActionItemZoomElementId,
-                        &page_actions::PageActionView::GetVisible, true),
+      WaitForZoomBubbleHide(), DoZoomIn(),
+      WaitForShow(kActionItemZoomElementId),
       CheckViewProperty(kActionItemZoomElementId,
                         &page_actions::PageActionView::GetTooltipText,
                         u"Zoom: 110%"),
@@ -114,11 +107,9 @@
                          ->GetImageModel(views::Button::STATE_NORMAL)
                          .value();
                }),
-      EnsureZoomBubblePresent(), DoZoomReset(), EnsureZoomBubblePresent(),
+      WaitForZoomBubbleShow(), DoZoomReset(), WaitForZoomBubbleShow(),
       CheckResult([&]() { return GetZoomPercent(); }, testing::Eq(100)),
-      DoZoomOut(),
-      CheckViewProperty(kActionItemZoomElementId,
-                        &page_actions::PageActionView::GetVisible, true),
+      DoZoomOut(), WaitForShow(kActionItemZoomElementId),
       CheckViewProperty(kActionItemZoomElementId,
                         &page_actions::PageActionView::GetTooltipText,
                         u"Zoom: 90%"),
@@ -129,31 +120,29 @@
                              ->GetImageModel(views::Button::STATE_NORMAL)
                              .value() != zoom_in_image;
                 }),
-      EnsureZoomBubblePresent());
+      WaitForZoomBubbleShow());
 }
 
 IN_PROC_BROWSER_TEST_F(ZoomViewInteractiveUiTest,
                        ShowAndHideZoomBubbleByClickWithMouse) {
-  RunTestSequence(WaitForZoomBubble(/*visible=*/false), DoZoomIn(),
-                  EnsurePresent(kActionItemZoomElementId),
+  RunTestSequence(WaitForZoomBubbleHide(), DoZoomIn(),
+                  WaitForShow(kActionItemZoomElementId),
                   MoveMouseTo(kActionItemZoomElementId), ClickMouse(),
-                  WaitForZoomBubble(/*visible=*/true),
+                  WaitForZoomBubbleShow(),
                   MoveMouseTo(kActionItemZoomElementId), ClickMouse(),
-                  WaitForZoomBubble(/*visible=*/false),
+                  WaitForZoomBubbleHide(),
                   MoveMouseTo(kActionItemZoomElementId), ClickMouse(),
-                  WaitForZoomBubble(/*visible=*/true));
+                  WaitForZoomBubbleShow());
 }
 
 IN_PROC_BROWSER_TEST_F(ZoomViewInteractiveUiTest,
                        ShowAndHideZoomBubbleByClickWithKeyboardPress) {
-  RunTestSequence(WaitForZoomBubble(/*visible=*/false), DoZoomIn(),
-                  EnsurePresent(kActionItemZoomElementId),
-                  PressButton(kActionItemZoomElementId),
-                  WaitForZoomBubble(/*visible=*/true),
-                  PressButton(kActionItemZoomElementId),
-                  WaitForZoomBubble(/*visible=*/false),
-                  PressButton(kActionItemZoomElementId),
-                  WaitForZoomBubble(/*visible=*/true));
+  RunTestSequence(
+      WaitForZoomBubbleHide(), DoZoomIn(),
+      WaitForShow(kActionItemZoomElementId),
+      PressButton(kActionItemZoomElementId), WaitForZoomBubbleShow(),
+      PressButton(kActionItemZoomElementId), WaitForZoomBubbleHide(),
+      PressButton(kActionItemZoomElementId), WaitForZoomBubbleShow());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/new_tab_footer/BUILD.gn b/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
index 56478d82..2270c12 100644
--- a/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
+++ b/chrome/browser/ui/webui/new_tab_footer/BUILD.gn
@@ -14,8 +14,6 @@
   public_deps = [
     ":mojo_bindings",
     "//chrome/browser/ui/webui/top_chrome",
-    "//chrome/common",
-    "//content/public/browser",
     "//ui/webui",
   ]
 }
@@ -30,7 +28,9 @@
     "//chrome/browser/extensions",
     "//chrome/browser/profiles",
     "//chrome/browser/resources/new_tab_footer:resources_grit",
+    "//chrome/common",
     "//components/search:search",
+    "//content/public/browser",
   ]
 }
 
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.cc b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.cc
index 252b82e..5eef058 100644
--- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.cc
@@ -20,6 +20,10 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/webui/webui_util.h"
 
+NewTabFooterUIConfig::NewTabFooterUIConfig()
+    : DefaultTopChromeWebUIConfig(content::kChromeUIScheme,
+                                  chrome::kChromeUINewTabFooterHost) {}
+
 bool NewTabFooterUIConfig::IsWebUIEnabled(
     content::BrowserContext* browser_context) {
   return base::FeatureList::IsEnabled(ntp_features::kNtpFooter);
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.h b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.h
index bc42f22..f1430574 100644
--- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.h
+++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_ui.h
@@ -11,8 +11,6 @@
 #include "chrome/browser/ui/webui/new_tab_footer/new_tab_footer.mojom.h"
 #include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
 #include "chrome/browser/ui/webui/top_chrome/top_chrome_webui_config.h"
-#include "chrome/common/webui_url_constants.h"
-#include "content/public/browser/webui_config.h"
 
 class NewTabFooterHandler;
 class NewTabFooterUI;
@@ -21,9 +19,7 @@
 class NewTabFooterUIConfig
     : public DefaultTopChromeWebUIConfig<NewTabFooterUI> {
  public:
-  NewTabFooterUIConfig()
-      : DefaultTopChromeWebUIConfig(content::kChromeUIScheme,
-                                    chrome::kChromeUINewTabFooterHost) {}
+  NewTabFooterUIConfig();
 
   // DefaultTopChromeWebUIConfig:
   bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
diff --git a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
index cbc4e29..7371767 100644
--- a/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
+++ b/chrome/browser/ui/webui/settings/privacy_sandbox_handler.cc
@@ -7,7 +7,6 @@
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_countries.h"
-#include "chrome/browser/privacy_sandbox/privacy_sandbox_countries_impl.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -227,8 +226,7 @@
 }
 
 PrivacySandboxCountries* PrivacySandboxHandler::GetPrivacySandboxCountries() {
-  static PrivacySandboxCountriesImpl instance;
-  return &instance;
+  return GetSingletonPrivacySandboxCountries();
 }
 
 PrivacySandboxService* PrivacySandboxHandler::GetPrivacySandboxService() {
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 5fbf229..2816e92e 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -512,10 +512,6 @@
   html_source->AddString("aiPageMainManagedLearnMoreUrl",
                          chrome::kAiSettingsLearnMorePageManagedUrl);
 
-  html_source->AddString("glicKeyboardShortcutLearnMoreUrl",
-                         chrome::kGlicKeyboardShortcutLearnMoreURL);
-  html_source->AddString("glicKeyboardShortcutLearnMoreManagedUrl",
-                         chrome::kGlicKeyboardShortcutLearnMoreManagedURL);
   html_source->AddString("historySearchLearnMoreUrl",
                          chrome::kHistorySearchLearnMorePageURL);
   html_source->AddString("historySearchLearnMoreManagedUrl",
@@ -771,6 +767,14 @@
       {"glicTabAccessConsider2", IDS_SETTINGS_GLIC_DATA_TAB_ACCESS_CONSIDER_2},
   };
   html_source->AddLocalizedStrings(kLocalizedStrings);
+
+  auto* command_line = base::CommandLine::ForCurrentProcess();
+  bool has_url =
+      command_line->HasSwitch(::switches::kGlicShortcutsLearnMoreURL);
+  const std::string url = has_url ? command_line->GetSwitchValueASCII(
+                                        ::switches::kGlicShortcutsLearnMoreURL)
+                                  : features::kGlicLearnMoreURL.Get();
+  html_source->AddString("glicKeyboardShortcutLearnMoreUrl", url);
 }
 #endif  // BUILDFLAG(ENABLE_GLIC)
 
@@ -1444,7 +1448,10 @@
   html_source->AddString(
       "cardBenefitsToggleSublabel",
       l10n_util::GetStringFUTF16(
-          IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_LEARN_LINK,
+          base::FeatureList::IsEnabled(
+              autofill::features::kAutofillEnableNewCardBenefitsToggleText)
+              ? IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_ISSUER_TERMS_APPLY_TEXT_AND_LEARN_LINK
+              : IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_LEARN_LINK,
           chrome::kCardBenefitsLearnMoreURL,
           l10n_util::GetStringUTF16(IDS_SETTINGS_OPENS_IN_NEW_TAB)));
 
@@ -1922,7 +1929,6 @@
       {"safeBrowsingEnableExtendedReportingDesc",
        IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING_DESC},
       {"safeBrowsingEnhanced", IDS_SETTINGS_SAFEBROWSING_ENHANCED},
-      {"safeBrowsingEnhancedDesc", IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC},
       {"safeBrowsingEnhancedDescUpdated",
        IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC_UPDATED},
       {"safeBrowsingEnhancedExpandA11yLabel",
@@ -1945,8 +1951,6 @@
        IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_THREE},
       {"safeBrowsingEnhancedWhenOnBulFour",
        IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FOUR},
-      {"safeBrowsingEnhancedWhenOnBulFive",
-       IDS_SETTINGS_SAFEBROWSING_ENHANCED_WHEN_ON_BULLET_FIVE},
       {"safeBrowsingEnhancedThingsToConsiderBulOne",
        IDS_SETTINGS_SAFEBROWSING_ENHANCED_THINGS_TO_CONSIDER_BULLET_ONE},
       {"safeBrowsingEnhancedThingsToConsiderBulTwo",
@@ -2570,12 +2574,6 @@
        IDS_SETTINGS_TRACKING_PROTECTION_THIRD_PARTY_COOKIES_TOGGLE_SUB_LABEL},
       {"trackingProtectionThirdPartyCookiesLearnMoreAriaLabel",
        IDS_SETTINGS_TRACKING_PROTECTION_THIRD_PARTY_COOKIES_LEARN_MORE_ARIA_LABEL},
-      {"trackingProtectionIpProtectionToggleLabel",
-       IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LABEL},
-      {"trackingProtectionFingerprintingProtectionToggleLabel",
-       IDS_SETTINGS_TRACKING_PROTECTION_FINGERPRINTING_PROTECTION_TOGGLE_LABEL},
-      {"trackingProtectionFingerprintingProtectionToggleSubLabel",
-       IDS_SETTINGS_TRACKING_PROTECTION_FINGERPRINTING_PROTECTION_TOGGLE_SUB_LABEL},
       {"trackingProtectionDoNotTrackToggleSubLabel",
        IDS_SETTINGS_TRACKING_PROTECTION_DO_NOT_TRACK_TOGGLE_SUB_LABEL},
       {"trackingProtectionSitesAllowedCookiesTitle",
@@ -3441,13 +3439,6 @@
           l10n_util::GetStringUTF16(IDS_SETTINGS_OPENS_IN_NEW_TAB)));
   html_source->AddString("trackingProtectionThirdPartyCookiesLearnMoreUrl",
                          chrome::kManage3pcHelpCenterURL);
-  html_source->AddString(
-      "trackingProtectionIpProtectionToggleSubLabel",
-      l10n_util::GetStringFUTF16(
-          IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL,
-          l10n_util::GetStringUTF16(
-              IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LEARN_MORE_ARIA_LABEL),
-          l10n_util::GetStringUTF16(IDS_SETTINGS_OPENS_IN_NEW_TAB)));
   html_source->AddString("ipProtectionLearnMoreUrl",
                          chrome::kIpProtectionHelpCenterURL);
 
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
index 3afa777..2781efa 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
@@ -509,9 +509,14 @@
       features::IsWasmTtsComponentUpdaterEnabled()
           ? extension_misc::kComponentUpdaterTTSEngineExtensionId
           : extension_misc::kTTSEngineExtensionId;
-  if (extension->id() != extensionId) {
+  if (extension->id() != extensionId || extension_installed_) {
     return;
   }
+  // Keep track of whether or not we've gotten a signal for installing the
+  // extension. Otherwise, if reading mode is opened simultaneously in
+  // multiple profiles, there can be an infinite loop of trying to install
+  // and uninstall voices.
+  extension_installed_ = true;
   page_->OnTtsEngineInstalled();
 }
 #endif
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h
index b1096ab..f635c47c 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h
@@ -251,6 +251,8 @@
 
   const bool use_screen_ai_service_;
 
+  bool extension_installed_ = false;
+
   void OnScreenAIServiceInitialized(bool successful);
 
   // Observes LanguageDetectionObserver, which notifies us when the language of
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index cb8eeef..6cc8482 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1745582325-287da6a2c3c6b90e780426395cce81f6afa5e0ca-a0039c24ffa93e9bc6b9966fd076450d79b52310.profdata
+chrome-android32-main-1745603681-43df19a3fc5b182951a697dff118a7eda0d57ae1-4985c214a5d99bb709aa3d59dda04a3bdb883c5e.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 9edb5791..7822e94b 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1745582732-a1d0556dab10db0d3325b42a753ba1ef9ffd00aa-81a47570f4fd5b425edaaf5f48af4a4d1b76e639.profdata
+chrome-android64-main-1745600425-b69182464eedc563976a07674dc2bf546f3ab95e-7cbf7c73195c6b9d7a1d0ac1747e8e41dbebe2a6.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 3882f6b..c3cf1529 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1745560604-81bca531ca25fd1605d5ee6f34db51b94d960b2e-035d05bd372ccf966bb8d6178c5bdaa14da93498.profdata
+chrome-linux-main-1745582325-1ce377e0ed62c188b22bb0612d73c3b375ae51c2-a0039c24ffa93e9bc6b9966fd076450d79b52310.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 4828ecfde..d3320fd9 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1745582325-f93f85959935d6d5a59f77c94b2fca294965f533-a0039c24ffa93e9bc6b9966fd076450d79b52310.profdata
+chrome-mac-arm-main-1745603681-68c3cd00f65a53f6cd3fa18f4bf1023c5f99b774-4985c214a5d99bb709aa3d59dda04a3bdb883c5e.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 2660daa..ae0dad9e 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1745539166-ec2345123193f059901a20d3b51513a871273b54-685559fead00f88eb29e163580aa82068408626d.profdata
+chrome-mac-main-1745582325-0b63dcb8bf03071347ecbf24c53df44e9c31c5a2-a0039c24ffa93e9bc6b9966fd076450d79b52310.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 19ca2964..8171081 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1745549882-105a137f86f5aa2cfb66de130ef3928759f95460-bcc2d0f3e1e40eaee211f8ff04d0cd4293750f14.profdata
+chrome-win64-main-1745560604-cf3a700b1f3d645b464cc1b0f8eeaa87ccadf1f2-035d05bd372ccf966bb8d6178c5bdaa14da93498.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index a71b042..6fc52b4 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -375,6 +375,15 @@
                    "glic-fre-url",
                    "");
 
+BASE_FEATURE(kGlicLearnMoreURLConfig,
+             "GlicLearnMoreURLConfig",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE_PARAM(std::string,
+                   kGlicLearnMoreURL,
+                   &kGlicLearnMoreURLConfig,
+                   "glic-shortcuts-learn-more-url",
+                   "");
+
 BASE_FEATURE(kGlicCSPConfig,
              "GlicCSPConfig",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index e3031e46..7e07d92f 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -221,6 +221,10 @@
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::FeatureParam<std::string> kGlicFreURL;
 
+COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicLearnMoreURLConfig);
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::FeatureParam<std::string> kGlicLearnMoreURL;
+
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicCSPConfig);
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::FeatureParam<std::string> kGlicAllowedOriginsOverride;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 2e3469d..d2e2f5c3 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -899,6 +899,7 @@
 const char kGlicGuestURL[] = "glic-guest-url";
 const char kGlicAlwaysOpenFre[] = "glic-always-open-fre";
 const char kGlicFreURL[] = "glic-fre-url";
+const char kGlicShortcutsLearnMoreURL[] = "glic-shortcuts-learn-more-url";
 // Use --glic-open-on-startup=attached or --glic-open-on-startup=detached.
 const char kGlicOpenOnStartup[] = "glic-open-on-startup";
 // List of allowed origins in the glic webview, as a space-separated list.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 5f25fb2..d615165 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -283,6 +283,7 @@
 extern const char kGlicGuestURL[];
 extern const char kGlicAlwaysOpenFre[];
 extern const char kGlicFreURL[];
+extern const char kGlicShortcutsLearnMoreURL[];
 extern const char kGlicOpenOnStartup[];
 extern const char kGlicAllowedOrigins[];
 extern const char kGlicAutomation[];
diff --git a/chrome/common/notifications/notification_operation.h b/chrome/common/notifications/notification_operation.h
index 791e72c..253b30d 100644
--- a/chrome/common/notifications/notification_operation.h
+++ b/chrome/common/notifications/notification_operation.h
@@ -11,7 +11,10 @@
   kClose = 1,
   kDisablePermission = 2,
   kSettings = 3,
-  kMaxValue = kSettings,
+  kReportAsSafe = 4,
+  kReportWarnedAsSpam = 5,
+  kReportUnwarnedAsSpam = 6,
+  kMaxValue = kReportUnwarnedAsSpam,
 };
 
 #endif  // CHROME_COMMON_NOTIFICATIONS_NOTIFICATION_OPERATION_H_
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index c2d4209..dfc4fd7 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -571,16 +571,6 @@
 inline constexpr char kHistorySearchLearnMorePageURL[] =
     "https://support.google.com/chrome?p=ai_history_search";
 
-// The URL for the "Learn more about shortcuts" page for Glic.
-// TODO(crbug.com/409588999): Update this link with the actual link when ready.
-inline constexpr char kGlicKeyboardShortcutLearnMoreURL[] =
-    "https://google.com/";
-
-// The URL for the "Learn more about shortcuts" page for Glic for managed users.
-// TODO(crbug.com/409588999): Update this link with the actual link when ready.
-inline constexpr char kGlicKeyboardShortcutLearnMoreManagedURL[] =
-    "https://google.com/";
-
 // The URL for the "Learn more" links for pages related to History search for
 // managed users.
 inline constexpr char kHistorySearchLearnMorePageManagedURL[] =
diff --git a/chrome/release_scripts b/chrome/release_scripts
index 6e0c25f..2dd15ef 160000
--- a/chrome/release_scripts
+++ b/chrome/release_scripts
@@ -1 +1 @@
-Subproject commit 6e0c25fb2cf1d16a46c03138d9745536a185e93e
+Subproject commit 2dd15ef4b070d15f38ca3a4238d8de7095557bed
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
index 6e8ad3b..5612e79 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
@@ -809,10 +809,11 @@
   }
   // Skip drawing the selection in the side panel if the selection originally
   // came from there.
-  if (!model_.selection_from_reading_mode()) {
+  if (model_.unprocessed_selections_from_reading_mode() == 0) {
     DrawSelection();
+  } else {
+    model_.decrement_selections_from_reading_mode();
   }
-  model_.set_selection_from_reading_mode(false);
   return did_draw;
 }
 
@@ -1712,7 +1713,7 @@
   // clears the selection, so we should tell the main page to clear too.
   if ((anchor_offset == focus_offset) && (anchor_node_id == focus_node_id)) {
     if (model_.has_selection()) {
-      model_.set_selection_from_reading_mode(true);
+      model_.increment_selections_from_reading_mode();
       OnCollapseSelection();
     }
     return;
@@ -1748,7 +1749,7 @@
     return;
   }
 
-  model_.set_selection_from_reading_mode(true);
+  model_.increment_selections_from_reading_mode();
   page_handler_->OnSelectionChange(model_.active_tree_id(), anchor_node_id,
                                    anchor_offset, focus_node_id, focus_offset);
 }
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
index 7e1987d..1baaeacd 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
@@ -2097,7 +2097,7 @@
       .Times(1);
   controller().OnSelectionChange(anchor_node_id, anchor_offset, focus_node_id,
                                  focus_offset);
-  ASSERT_TRUE(model().selection_from_reading_mode());
+  ASSERT_EQ(1, model().unprocessed_selections_from_reading_mode());
   Mock::VerifyAndClearExpectations(distiller_);
 }
 
@@ -2129,11 +2129,70 @@
 
   EXPECT_CALL(page_handler_, OnSelectionChange).Times(0);
   controller().OnSelectionChange(3, 5, 3, 5);
-  ASSERT_FALSE(model().selection_from_reading_mode());
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
   page_handler_.FlushForTesting();
 }
 
 TEST_F(ReadAnythingAppControllerTest,
+       OnSelectionChange_MultipleTimesBeforePostProcess) {
+  ui::AXNodeData node1 = test::TextNode(/* id= */ 2);
+  ui::AXNodeData node2 = test::TextNode(/* id= */ 3);
+  SendUpdateWithNodes({std::move(node1), std::move(node2)});
+
+  EXPECT_CALL(page_handler_, OnSelectionChange).Times(2);
+  controller().OnSelectionChange(3, 5, 3, 6);
+  controller().OnSelectionChange(3, 5, 3, 10);
+
+  ASSERT_EQ(2, model().unprocessed_selections_from_reading_mode());
+  page_handler_.FlushForTesting();
+  Mock::VerifyAndClearExpectations(distiller_);
+}
+
+TEST_F(ReadAnythingAppControllerTest, OnSelectionChange_ThenPostProcess) {
+  ui::AXNodeData node1 = test::TextNode(/* id= */ 2);
+  ui::AXNodeData node2 = test::TextNode(/* id= */ 3);
+  SendUpdateWithNodes({std::move(node1), std::move(node2)});
+
+  EXPECT_CALL(page_handler_, OnSelectionChange).Times(2);
+  controller().OnSelectionChange(3, 5, 3, 6);
+  controller().OnSelectionChange(3, 5, 3, 10);
+  ASSERT_EQ(2, model().unprocessed_selections_from_reading_mode());
+
+  ui::AXTreeUpdate selection1;
+  test::SetUpdateTreeID(&selection1, tree_id_);
+  selection1.has_tree_data = true;
+  selection1.tree_data.sel_anchor_object_id = 2;
+  selection1.tree_data.sel_focus_object_id = 3;
+  selection1.tree_data.sel_anchor_offset = 0;
+  selection1.tree_data.sel_focus_offset = 1;
+  AccessibilityEventReceived({std::move(selection1)});
+  ASSERT_EQ(1, model().unprocessed_selections_from_reading_mode());
+
+  ui::AXTreeUpdate selection2;
+  test::SetUpdateTreeID(&selection2, tree_id_);
+  selection2.has_tree_data = true;
+  selection2.tree_data.sel_anchor_object_id = 2;
+  selection2.tree_data.sel_focus_object_id = 3;
+  selection2.tree_data.sel_anchor_offset = 0;
+  selection2.tree_data.sel_focus_offset = 5;
+  AccessibilityEventReceived({std::move(selection2)});
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
+
+  ui::AXTreeUpdate selection3;
+  test::SetUpdateTreeID(&selection3, tree_id_);
+  selection3.has_tree_data = true;
+  selection3.tree_data.sel_anchor_object_id = 2;
+  selection3.tree_data.sel_focus_object_id = 3;
+  selection3.tree_data.sel_anchor_offset = 0;
+  selection3.tree_data.sel_focus_offset = 7;
+  AccessibilityEventReceived({std::move(selection3)});
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
+
+  page_handler_.FlushForTesting();
+  Mock::VerifyAndClearExpectations(distiller_);
+}
+
+TEST_F(ReadAnythingAppControllerTest,
        OnSelectionChange_ClickAfterSelectionClearsSelection) {
   ui::AXNodeData node1 = test::TextNode(/* id= */ 2);
   ui::AXNodeData node2 = test::TextNode(/* id= */ 3);
@@ -2155,7 +2214,7 @@
   EXPECT_CALL(page_handler_, OnCollapseSelection()).Times(1);
   controller().OnSelectionChange(anchor_node_id, anchor_offset, focus_node_id,
                                  focus_offset);
-  ASSERT_TRUE(model().selection_from_reading_mode());
+  ASSERT_EQ(1, model().unprocessed_selections_from_reading_mode());
   page_handler_.FlushForTesting();
   Mock::VerifyAndClearExpectations(distiller_);
 }
@@ -2177,7 +2236,7 @@
   // If distillation is in progress, OnSelectionChange should not be called.
   EXPECT_CALL(page_handler_, OnSelectionChange).Times(0);
   controller().OnSelectionChange(2, 0, 3, 1);
-  ASSERT_FALSE(model().selection_from_reading_mode());
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
   page_handler_.FlushForTesting();
   Mock::VerifyAndClearExpectations(distiller_);
 }
@@ -2206,7 +2265,7 @@
       .Times(0);
   controller().OnSelectionChange(anchor_node_id, anchor_offset, focus_node_id,
                                  focus_offset);
-  ASSERT_FALSE(model().selection_from_reading_mode());
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
   page_handler_.FlushForTesting();
   Mock::VerifyAndClearExpectations(distiller_);
 }
@@ -2226,7 +2285,7 @@
   ASSERT_EQ(4, controller().EndNodeId());
   ASSERT_EQ(0, controller().StartOffset());
   ASSERT_EQ(1, controller().EndOffset());
-  ASSERT_FALSE(model().selection_from_reading_mode());
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
 }
 
 TEST_F(ReadAnythingAppControllerTest, Selection_Backward) {
@@ -2244,7 +2303,7 @@
   EXPECT_EQ(4, controller().EndNodeId());
   EXPECT_EQ(0, controller().StartOffset());
   EXPECT_EQ(1, controller().EndOffset());
-  ASSERT_FALSE(model().selection_from_reading_mode());
+  ASSERT_EQ(0, model().unprocessed_selections_from_reading_mode());
 }
 
 TEST_F(ReadAnythingAppControllerTest, Selection_IgnoredNode) {
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
index fbac48e..2ac2347 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
@@ -143,7 +143,7 @@
   display_node_ids_.clear();
   distillation_in_progress_ = false;
   requires_post_process_selection_ = false;
-  selection_from_reading_mode_ = false;
+  selections_from_reading_mode_ = 0;
   ResetSelection();
 }
 
@@ -173,7 +173,8 @@
     return display_node_ids_.contains(start_.id) &&
            display_node_ids_.contains(end_.id);
   };
-  const bool need_to_draw = !selection_from_reading_mode_ && has_selection() &&
+  const bool need_to_draw = (selections_from_reading_mode_ == 0) &&
+                            has_selection() &&
                             !selection_in_distilled_content();
   const bool was_empty = is_empty();
 
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_model.h b/chrome/renderer/accessibility/read_anything/read_anything_app_model.h
index c6532e16..a6d8181 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_model.h
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_model.h
@@ -130,11 +130,14 @@
   bool redraw_required() const { return redraw_required_; }
   void reset_redraw_required() { redraw_required_ = false; }
 
-  bool selection_from_reading_mode() const {
-    return selection_from_reading_mode_;
+  int unprocessed_selections_from_reading_mode() {
+    return selections_from_reading_mode_;
   }
-  void set_selection_from_reading_mode(bool selection_from_action) {
-    selection_from_reading_mode_ = selection_from_action;
+  void increment_selections_from_reading_mode() {
+    ++selections_from_reading_mode_;
+  }
+  void decrement_selections_from_reading_mode() {
+    --selections_from_reading_mode_;
   }
 
   const std::string& base_language_code() const { return base_language_code_; }
@@ -439,7 +442,7 @@
   bool requires_distillation_ = false;
   bool reset_draw_timer_ = false;
   bool requires_post_process_selection_ = false;
-  bool selection_from_reading_mode_ = false;
+  int selections_from_reading_mode_ = 0;
 
   // For screen2x data collection, Chrome is launched from the CLI to open one
   // webpage. We record the result of the distill() call for this entire
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_model_browsertest.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_model_browsertest.cc
index f36e29f..9d976553 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_model_browsertest.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_model_browsertest.cc
@@ -866,7 +866,7 @@
   update.tree_data.sel_is_backward = false;
   AccessibilityEventReceived({std::move(update)});
   ProcessDisplayNodes({2, 3});
-  model().set_selection_from_reading_mode(true);
+  model().increment_selections_from_reading_mode();
 
   ASSERT_FALSE(model().PostProcessSelection());
 }
diff --git a/chrome/services/mac_notifications/public/mojom/mac_notifications_mojom_traits.cc b/chrome/services/mac_notifications/public/mojom/mac_notifications_mojom_traits.cc
index 955179e..9fe5e86f 100644
--- a/chrome/services/mac_notifications/public/mojom/mac_notifications_mojom_traits.cc
+++ b/chrome/services/mac_notifications/public/mojom/mac_notifications_mojom_traits.cc
@@ -18,6 +18,9 @@
     case NotificationOperation::kSettings:
       return mac_notifications::mojom::NotificationOperation::kSettings;
     case NotificationOperation::kDisablePermission:
+    case NotificationOperation::kReportAsSafe:
+    case NotificationOperation::kReportWarnedAsSpam:
+    case NotificationOperation::kReportUnwarnedAsSpam:
       // This is not supported in macOS notifications.
       break;
   }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c510bdd..b147cb1 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -19,7 +19,6 @@
 import("//chrome/common/features.gni")
 import("//chrome/services/speech/buildflags/buildflags.gni")
 import("//chrome/test/include_js_tests.gni")
-import("//chrome/version.gni")
 import("//components/allocation_recorder/testing/testing.gni")
 import("//components/captive_portal/core/features.gni")
 import("//components/compose/features.gni")
@@ -1276,10 +1275,7 @@
 
   test("chromeos_integration_tests") {
     configs += [ "//build/config:precompiled_headers" ]
-    defines = [
-      "HAS_OUT_OF_PROC_TEST_RUNNER",
-      "CHROME_VERSION_MAJOR=" + chrome_version_major,
-    ]
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
     sources = [
       "base/chromeos/crosier/chromeos_tests_main.cc",
       "base/chromeos/crosier/demo_integration_test.cc",
@@ -1608,10 +1604,7 @@
 if (is_android) {
   test("android_browsertests") {
     configs += [ "//build/config:precompiled_headers" ]
-    defines = [
-      "HAS_OUT_OF_PROC_TEST_RUNNER",
-      "CHROME_VERSION_MAJOR=" + chrome_version_major,
-    ]
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
     use_default_launcher = false
     android_manifest =
         "${target_gen_dir}/android_browsertests_manifest/AndroidManifest.xml"
@@ -2129,10 +2122,7 @@
 
     configs += [ "//build/config:precompiled_headers" ]
     configs += [ ":disable_thinlto_cache_flags" ]
-    defines = [
-      "HAS_OUT_OF_PROC_TEST_RUNNER",
-      "CHROME_VERSION_MAJOR=" + chrome_version_major,
-    ]
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
     deps = [
       ":browser_tests_runner",
@@ -6163,6 +6153,8 @@
     "../browser/password_manager/chrome_password_change_service_unittest.cc",
     "../browser/password_manager/chrome_password_manager_client_unittest.cc",
     "../browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc",
+    "../browser/password_manager/password_change_delegate_mock.cc",
+    "../browser/password_manager/password_change_delegate_mock.h",
     "../browser/performance_manager/decorators/helpers/page_live_state_decorator_helper_unittest.cc",
     "../browser/performance_manager/metrics/metrics_provider_common_unittest.cc",
     "../browser/performance_manager/policies/discard_eligibility_policy_unittest.cc",
@@ -7731,10 +7723,9 @@
       "../browser/notifications/screen_capture_notification_blocker_unittest.cc",
       "../browser/password_manager/generated_password_leak_detection_pref_unittest.cc",
       "../browser/password_manager/password_change/change_form_submission_verifier_unittest.cc",
+      "../browser/password_manager/password_change/change_password_form_finder_unittest.cc",
       "../browser/password_manager/password_change/change_password_form_waiter_unittest.cc",
       "../browser/password_manager/password_change_delegate_impl_unittest.cc",
-      "../browser/password_manager/password_change_delegate_mock.cc",
-      "../browser/password_manager/password_change_delegate_mock.h",
       "../browser/performance_manager/execution_context_priority/side_panel_loading_voter_unittest.cc",
       "../browser/platform_util_unittest.cc",
       "../browser/policy/policy_path_parser_unittest.cc",
@@ -9492,6 +9483,7 @@
       "../browser/safe_browsing/download_protection/download_request_maker_unittest.cc",
       "../browser/safe_browsing/download_protection/file_analyzer_unittest.cc",
       "../browser/safe_browsing/download_protection/file_system_access_metadata_unittest.cc",
+      "../browser/safe_browsing/notification_content_detection/notification_content_detection_util_unittest.cc",
       "../browser/safe_browsing/threat_details_unittest.cc",
       "../common/safe_browsing/binary_feature_extractor_unittest.cc",
       "../common/safe_browsing/download_type_util_unittest.cc",
@@ -11396,6 +11388,7 @@
         "//chrome/browser/ui/commerce:test_support",
         "//chrome/browser/ui/find_bar",
         "//chrome/browser/ui/hats:hats",
+        "//chrome/browser/ui/hats:test_support",
         "//chrome/browser/ui/lens",
         "//chrome/browser/ui/media_router",
         "//chrome/browser/ui/tabs",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 89b585a..f33572c 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -267,6 +267,7 @@
     "javatests/src/org/chromium/chrome/test/transit/tabmodel/TabModelSelectorCondition.java",
     "javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailCondition.java",
     "javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailsCapturedCarryOn.java",
+    "javatests/src/org/chromium/chrome/test/transit/testhtmls/BlankPopupOnLoadPageStation.java",
     "javatests/src/org/chromium/chrome/test/transit/testhtmls/NavigatePageStations.java",
     "javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnClickPageStation.java",
     "javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnLoadPageStation.java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/MessageFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/MessageFacility.java
index 08c28abf..e257900 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/MessageFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/MessageFacility.java
@@ -84,7 +84,7 @@
         } else {
             mHostStation.exitFacilitySync(
                     this,
-                    bannerElement.performTrigger(
+                    bannerElement.getPerformTrigger(
                             ViewActions.actionWithAssertions(
                                     new GeneralSwipeAction(
                                             Swipe.FAST,
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/context_menu/LinkContextMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/context_menu/LinkContextMenuFacility.java
index f12fab6..a1bc5b9 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/context_menu/LinkContextMenuFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/context_menu/LinkContextMenuFacility.java
@@ -64,7 +64,7 @@
         mHostStation.exitFacilitiesSync(
                 List.of(this, itemOnScreen),
                 Transition.conditionOption(tabCountIncrease),
-                itemOnScreen.viewElement.clickTrigger());
+                itemOnScreen.viewElement.getClickTrigger());
         return null;
     }
 
@@ -74,6 +74,6 @@
         return mHostStation.swapFacilitySync(
                 this,
                 new TabGroupUiFacility<>(mHostStation.getActivity().getTabModelSelectorSupplier()),
-                itemOnScreen.viewElement.clickTrigger());
+                itemOnScreen.viewElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModePreferencesDialog.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModePreferencesDialog.java
index 440b1c2..a29fae2 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModePreferencesDialog.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModePreferencesDialog.java
@@ -74,21 +74,21 @@
     }
 
     public void pickColorLight(Condition condition) {
-        Condition.runAndWaitFor(lightButtonElement.clickTrigger(), condition);
+        Condition.runAndWaitFor(lightButtonElement.getClickTrigger(), condition);
     }
 
     public void pickColorDark(Condition condition) {
-        Condition.runAndWaitFor(darkButtonElement.clickTrigger(), condition);
+        Condition.runAndWaitFor(darkButtonElement.getClickTrigger(), condition);
     }
 
     public void pickColorSepia(Condition condition) {
-        Condition.runAndWaitFor(sepiaButtonElement.clickTrigger(), condition);
+        Condition.runAndWaitFor(sepiaButtonElement.getClickTrigger(), condition);
     }
 
     public void setFontSizeSliderToMin(Condition condition) {
         // Min is 50% font size.
         Condition.runAndWaitFor(
-                fontSizeSliderElement.performTrigger(
+                fontSizeSliderElement.getPerformTrigger(
                         new GeneralClickAction(
                                 Tap.SINGLE, GeneralLocation.CENTER_LEFT, Press.FINGER)),
                 condition);
@@ -96,7 +96,7 @@
 
     public void setFontSizeSliderToMax(Condition condition) {
         Condition.runAndWaitFor(
-                fontSizeSliderElement.performTrigger(
+                fontSizeSliderElement.getPerformTrigger(
                         new GeneralClickAction(
                                 Tap.SINGLE, GeneralLocation.CENTER_RIGHT, Press.FINGER)),
                 condition);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/IncognitoTabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/IncognitoTabSwitcherStation.java
index fad8197..cf7ce2c 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/IncognitoTabSwitcherStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/IncognitoTabSwitcherStation.java
@@ -51,6 +51,6 @@
                         .withIsSelectingTabs(1)
                         .build();
 
-        return travelToSync(page, newTabButtonElement.clickTrigger());
+        return travelToSync(page, newTabButtonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/NewTabGroupDialogFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/NewTabGroupDialogFacility.java
index b81c76b..7fcb0e0 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/NewTabGroupDialogFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/NewTabGroupDialogFacility.java
@@ -146,7 +146,7 @@
                 this,
                 new NewTabGroupDialogFacility(
                         mTabIdsToGroup, newTabGroupName, mSelectedColor, mSoftKeyboard),
-                titleInputElement.performTrigger(replaceText(newTabGroupName)));
+                titleInputElement.getPerformTrigger(replaceText(newTabGroupName)));
     }
 
     /** Select a color. */
@@ -154,7 +154,7 @@
         return mHostStation.swapFacilitySync(
                 this,
                 new NewTabGroupDialogFacility(mTabIdsToGroup, mTitle, newColor, mSoftKeyboard),
-                colorElements[newColor].clickTrigger());
+                colorElements[newColor].getClickTrigger());
     }
 
     /** Press "Done" to confirm the tab group name and color. */
@@ -168,7 +168,7 @@
         return mHostStation.swapFacilitySync(
                 this,
                 new TabSwitcherGroupCardFacility(expectedCardIndex, mTabIdsToGroup, mTitle),
-                doneButtonElement.clickTrigger());
+                doneButtonElement.getClickTrigger());
     }
 
     /** Press "Done" to confirm the tab group name and color, but no-op from an invalid title. */
@@ -180,7 +180,7 @@
                 new NewTabGroupDialogFacility(
                         mTabIdsToGroup, mTitle, mSelectedColor, mSoftKeyboard),
                 Transition.possiblyAlreadyFulfilledOption(),
-                doneButtonElement.clickTrigger());
+                doneButtonElement.getClickTrigger());
     }
 
     /** Press the system backpress to confirm the tab group name and color. */
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
index dd7aa1f..d2839d81 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
@@ -61,6 +61,6 @@
                         .withIsSelectingTabs(1)
                         .build();
 
-        return travelToSync(page, newTabButtonElement.clickTrigger());
+        return travelToSync(page, newTabButtonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
index 4fd0b4b9..c2a3e8c 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
@@ -144,7 +144,7 @@
                 this,
                 new TabGroupDialogFacility<>(
                         mTabIdsInGroup, newTabGroupName, mSelectedColor, mIsIncognito),
-                titleInputElement.performTrigger(replaceText(newTabGroupName)));
+                titleInputElement.getPerformTrigger(replaceText(newTabGroupName)));
     }
 
     /** Create a new tab and transition to the associated RegularNewTabPageStation. */
@@ -156,7 +156,7 @@
                         .withIsOpeningTabs(1)
                         .withIsSelectingTabs(1)
                         .build();
-        return mHostStation.travelToSync(page, newTabButtonElement.clickTrigger());
+        return mHostStation.travelToSync(page, newTabButtonElement.getClickTrigger());
     }
 
     /** Create a new incognito tab and transition to the associated IncognitoNewTabPageStation. */
@@ -168,11 +168,11 @@
                         .withIsOpeningTabs(1)
                         .withIsSelectingTabs(1)
                         .build();
-        return mHostStation.travelToSync(page, newTabButtonElement.clickTrigger());
+        return mHostStation.travelToSync(page, newTabButtonElement.getClickTrigger());
     }
 
     /** Press back to exit the facility. */
     public void pressBackArrowToExit() {
-        mHostStation.exitFacilitySync(this, backButtonElement.clickTrigger());
+        mHostStation.exitFacilitySync(this, backButtonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabListEditorAppMenu.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabListEditorAppMenu.java
index d023dbc..d792aa7 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabListEditorAppMenu.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabListEditorAppMenu.java
@@ -90,7 +90,7 @@
         mHostStation.swapFacilitiesSync(
                 List.of(this, mListEditor, itemOnScreen),
                 List.of(dialog, softKeyboard),
-                itemOnScreen.viewElement.clickTrigger());
+                itemOnScreen.viewElement.getClickTrigger());
         return dialog;
     }
 
@@ -120,7 +120,7 @@
         mHostStation.swapFacilitiesSync(
                 List.of(this, mListEditor, itemOnScreen),
                 List.of(card, undoSnackbar),
-                itemOnScreen.viewElement.clickTrigger());
+                itemOnScreen.viewElement.getClickTrigger());
         return Pair.create(card, undoSnackbar);
     }
 
@@ -142,7 +142,7 @@
         mHostStation.exitFacilitiesSync(
                 List.of(this, mListEditor, itemOnScreen),
                 Transition.conditionOption(tabCountDecreased),
-                itemOnScreen.viewElement.clickTrigger());
+                itemOnScreen.viewElement.getClickTrigger());
 
         return null;
     }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardAppMenuFacility.java
index 259c38e..10f2059 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardAppMenuFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardAppMenuFacility.java
@@ -59,7 +59,8 @@
             ItemOnScreenFacility<UndoSnackbarFacility> itemOnScreen) {
         String snackbarMessage = TabGroupUtil.getUndoCloseGroupSnackbarMessageString(mTitle);
         UndoSnackbarFacility undoSnackbar = new UndoSnackbarFacility(snackbarMessage);
-        mHostStation.swapFacilitySync(this, undoSnackbar, itemOnScreen.viewElement.clickTrigger());
+        mHostStation.swapFacilitySync(
+                this, undoSnackbar, itemOnScreen.viewElement.getClickTrigger());
         return undoSnackbar;
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardFacility.java
index 4ab9815..d278e25d 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherGroupCardFacility.java
@@ -69,7 +69,7 @@
         boolean isIncognito = mHostStation.isIncognito();
         return mHostStation.enterFacilitySync(
                 new TabGroupDialogFacility<>(mTabIdsToGroup, isIncognito),
-                titleElement.clickTrigger());
+                titleElement.getClickTrigger());
     }
 
     /** Clicks the ("...") action button on a tab group to open the overflow menu. */
@@ -77,6 +77,6 @@
         boolean isIncognito = mHostStation.isIncognito();
         return mHostStation.enterFacilitySync(
                 new TabSwitcherGroupCardAppMenuFacility(isIncognito, mTitle),
-                menuButtonElement.clickTrigger());
+                menuButtonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherListEditorFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherListEditorFacility.java
index 20e59a7..62b94a1 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherListEditorFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherListEditorFacility.java
@@ -117,7 +117,7 @@
     /** Open the app menu, which looks different while selecting tabs. */
     public TabListEditorAppMenu openAppMenuWithEditor() {
         return mHostStation.enterFacilitySync(
-                new TabListEditorAppMenu(this), mHostStation.menuButtonElement.clickTrigger());
+                new TabListEditorAppMenu(this), mHostStation.menuButtonElement.getClickTrigger());
     }
 
     /**
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherSearchStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherSearchStation.java
index 03423c6..af30dea 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherSearchStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherSearchStation.java
@@ -11,6 +11,7 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.Matchers.allOf;
 
 import static org.chromium.base.test.transit.ViewSpec.viewSpec;
@@ -25,6 +26,7 @@
 import org.chromium.base.test.transit.ViewElement;
 import org.chromium.base.test.transit.ViewSpec;
 import org.chromium.chrome.browser.omnibox.UrlBar;
+import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
 import org.chromium.chrome.browser.searchwidget.SearchActivity;
 import org.chromium.chrome.test.R;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
@@ -79,7 +81,7 @@
                 .descendant(
                         allOf(
                                 withParentIndex(index),
-                                withClassName(containsString("BaseSuggestionView")),
+                                withClassName(equalTo(BaseSuggestionView.class.getName())),
                                 hasDescendant(
                                         allOf(
                                                 withId(R.id.line_1),
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java
index 57296795..6147182b 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java
@@ -120,7 +120,7 @@
         recheckActiveConditions();
 
         return enterFacilitySync(
-                new TabSwitcherAppMenuFacility(mIsIncognito), menuButtonElement.clickTrigger());
+                new TabSwitcherAppMenuFacility(mIsIncognito), menuButtonElement.getClickTrigger());
     }
 
     /**
@@ -239,7 +239,7 @@
 
     public TabSwitcherSearchStation openTabSwitcherSearch() {
         TabSwitcherSearchStation searchStation = new TabSwitcherSearchStation(mIsIncognito);
-        travelToSync(searchStation, searchElement.clickTrigger());
+        travelToSync(searchStation, searchElement.getClickTrigger());
         searchStation.focusAndDropSoftKeyboard();
         return searchStation;
     }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherTabCardFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherTabCardFacility.java
index d9baa45b..66038e3 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherTabCardFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherTabCardFacility.java
@@ -39,6 +39,6 @@
                         .withIsSelectingTabs(isSelecting ? 1 : 0)
                         .withExpectedTitle(mTitle)
                         .build();
-        return mHostStation.travelToSync(destination, titleElement.clickTrigger());
+        return mHostStation.travelToSync(destination, titleElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/UndoSnackbarFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/UndoSnackbarFacility.java
index d91ad7cd..c98ed4a 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/UndoSnackbarFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/UndoSnackbarFacility.java
@@ -15,6 +15,6 @@
 
     /** Press undo to revert the operation. */
     public void pressUndo() {
-        mHostStation.exitFacilitySync(this, buttonElement.clickTrigger());
+        mHostStation.exitFacilitySync(this, buttonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageStation.java
index d13a727a..ffc0f59 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageStation.java
@@ -66,7 +66,7 @@
     /** Opens the app menu by pressing the toolbar "..." button */
     public IncognitoNewTabPageAppMenuFacility openAppMenu() {
         return enterFacilitySync(
-                new IncognitoNewTabPageAppMenuFacility(), menuButtonElement.clickTrigger());
+                new IncognitoNewTabPageAppMenuFacility(), menuButtonElement.getClickTrigger());
     }
 
     /** Click the URL bar to enter the Omnibox. */
@@ -75,7 +75,8 @@
         OmniboxFacility omniboxFacility =
                 new OmniboxFacility(/* incognito= */ true, fakeSuggestions);
         SoftKeyboardFacility softKeyboard = new SoftKeyboardFacility();
-        enterFacilitiesSync(List.of(omniboxFacility, softKeyboard), urlBarElement.clickTrigger());
+        enterFacilitiesSync(
+                List.of(omniboxFacility, softKeyboard), urlBarElement.getClickTrigger());
         return Pair.create(omniboxFacility, softKeyboard);
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java
index d313c40..caae0ace 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java
@@ -79,7 +79,7 @@
     /** Opens the app menu by pressing the toolbar "..." button */
     public RegularNewTabPageAppMenuFacility openAppMenu() {
         return enterFacilitySync(
-                new RegularNewTabPageAppMenuFacility(), menuButtonElement.clickTrigger());
+                new RegularNewTabPageAppMenuFacility(), menuButtonElement.getClickTrigger());
     }
 
     /**
@@ -101,7 +101,7 @@
                 new OmniboxFacility(/* incognito= */ false, fakeSuggestions);
         SoftKeyboardFacility softKeyboard = new SoftKeyboardFacility();
         enterFacilitiesSync(
-                List.of(omniboxFacility, softKeyboard), searchBoxElement.clickTrigger());
+                List.of(omniboxFacility, softKeyboard), searchBoxElement.getClickTrigger());
         return Pair.create(omniboxFacility, softKeyboard);
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxEnteredTextFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxEnteredTextFacility.java
index 309ae31..a7b0c69 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxEnteredTextFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxEnteredTextFacility.java
@@ -46,7 +46,7 @@
         return mHostStation.swapFacilitySync(
                 this,
                 new OmniboxEnteredTextFacility(mOmniboxFacility, textToExpect),
-                urlBarElement.performTrigger(ViewActions.typeText(textToType)));
+                urlBarElement.getPerformTrigger(ViewActions.typeText(textToType)));
     }
 
     /** Simulate autocomplete suggestion received from the server. */
@@ -62,6 +62,6 @@
 
     /** Click the delete button to erase the text entered. */
     public void clickDelete() {
-        mHostStation.exitFacilitySync(this, deleteButtonElement.forgivingClickTrigger());
+        mHostStation.exitFacilitySync(this, deleteButtonElement.getForgivingClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxFacility.java
index 742d97e..5a5abf1 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxFacility.java
@@ -92,7 +92,7 @@
     public OmniboxEnteredTextFacility typeText(String textToTypeAndExpect) {
         return mHostStation.enterFacilitySync(
                 new OmniboxEnteredTextFacility(this, textToTypeAndExpect),
-                urlBarElement.performTrigger(ViewActions.typeText(textToTypeAndExpect)));
+                urlBarElement.getPerformTrigger(ViewActions.typeText(textToTypeAndExpect)));
     }
 
     /** Press back expecting the Omnibox to be closed. */
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java
index fbd1ae0..b7a70a9 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java
@@ -345,7 +345,8 @@
     public TabSwitcherActionMenuFacility openTabSwitcherActionMenu() {
         recheckActiveConditions();
         return enterFacilitySync(
-                new TabSwitcherActionMenuFacility(), tabSwitcherButtonElement.longClickTrigger());
+                new TabSwitcherActionMenuFacility(),
+                tabSwitcherButtonElement.getLongPressTrigger());
     }
 
     /** Opens the app menu by pressing the toolbar "..." button */
@@ -353,7 +354,7 @@
         recheckActiveConditions();
 
         return enterFacilitySync(
-                new PageAppMenuFacility<PageStation>(), menuButtonElement.clickTrigger());
+                new PageAppMenuFacility<PageStation>(), menuButtonElement.getClickTrigger());
     }
 
     /** Shortcut to open a new tab programmatically as if selecting "New Tab" from the app menu. */
@@ -410,7 +411,7 @@
         assert !mIncognito;
         return travelToSync(
                 RegularTabSwitcherStation.from(getActivity().getTabModelSelector()),
-                tabSwitcherButtonElement.clickTrigger());
+                tabSwitcherButtonElement.getClickTrigger());
     }
 
     /** Opens the incognito tab switcher by pressing the toolbar tab switcher button. */
@@ -418,7 +419,7 @@
         assert mIncognito;
         return travelToSync(
                 IncognitoTabSwitcherStation.from(getActivity().getTabModelSelector()),
-                tabSwitcherButtonElement.clickTrigger());
+                tabSwitcherButtonElement.getClickTrigger());
     }
 
     /** Loads a |url| in the same tab and waits to transition. */
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PopupBlockedMessageFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PopupBlockedMessageFacility.java
index 65f86717..88e8782 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PopupBlockedMessageFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PopupBlockedMessageFacility.java
@@ -46,6 +46,6 @@
                         .withIsOpeningTabs(1)
                         .withIsSelectingTabs(1)
                         .build();
-        return mHostStation.travelToSync(popupPage, alwaysShowButtonElement.clickTrigger());
+        return mHostStation.travelToSync(popupPage, alwaysShowButtonElement.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/TabSwitcherActionMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/TabSwitcherActionMenuFacility.java
index 1af60c2..a11fdb4 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/TabSwitcherActionMenuFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/TabSwitcherActionMenuFacility.java
@@ -135,7 +135,7 @@
                 destination,
                 Transition.conditionOption(
                         createTabCountChangedCondition(mHostStation.isIncognito(), -1)),
-                closeTabMenuItemElement.clickTrigger());
+                closeTabMenuItemElement.getClickTrigger());
     }
 
     /** Select the "New tab" menu option to open a new Tab. */
@@ -149,7 +149,7 @@
                 destination,
                 Transition.conditionOption(
                         createTabCountChangedCondition(/* incognito= */ false, +1)),
-                newTabMenuItemElement.clickTrigger());
+                newTabMenuItemElement.getClickTrigger());
     }
 
     /** Select the "New Incognito tab" menu option to open a new incognito Tab. */
@@ -163,7 +163,7 @@
                 destination,
                 Transition.conditionOption(
                         createTabCountChangedCondition(/* incognito= */ true, +1)),
-                newIncognitoTabMenuItemElement.clickTrigger());
+                newIncognitoTabMenuItemElement.getClickTrigger());
     }
 
     /** Switches out of incognito tab model to regular tab model */
@@ -174,7 +174,7 @@
         return mHostStation.travelToSync(
                 destination,
                 Transition.conditionOption(createTabModelChangedCondition()),
-                switchOutOfIncognitoMenuItemElement.clickTrigger());
+                switchOutOfIncognitoMenuItemElement.getClickTrigger());
     }
 
     /** Switches to incognito tab model from regular tab model */
@@ -185,7 +185,7 @@
         return mHostStation.travelToSync(
                 destination,
                 Transition.conditionOption(createTabModelChangedCondition()),
-                switchToIncognitoMenuItemElement.clickTrigger());
+                switchToIncognitoMenuItemElement.getClickTrigger());
     }
 
     private Condition createTabCountChangedCondition(boolean incognito, int change) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/WebPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/WebPageStation.java
index 71782d91..8ed1822 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/WebPageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/WebPageStation.java
@@ -120,14 +120,14 @@
     public RegularWebPageAppMenuFacility openRegularTabAppMenu() {
         assert !mIncognito;
         return enterFacilitySync(
-                new RegularWebPageAppMenuFacility(), menuButtonElement.clickTrigger());
+                new RegularWebPageAppMenuFacility(), menuButtonElement.getClickTrigger());
     }
 
     /** Opens the web page app menu by pressing the toolbar "..." button */
     public IncognitoWebPageAppMenuFacility openIncognitoTabAppMenu() {
         assert mIncognito;
         return enterFacilitySync(
-                new IncognitoWebPageAppMenuFacility(), menuButtonElement.clickTrigger());
+                new IncognitoWebPageAppMenuFacility(), menuButtonElement.getClickTrigger());
     }
 
     /** Trigger to scroll WebContents to the bottom. */
@@ -149,7 +149,8 @@
         OmniboxFacility omniboxFacility =
                 new OmniboxFacility(/* incognito= */ mIncognito, fakeSuggestions);
         SoftKeyboardFacility softKeyboard = new SoftKeyboardFacility();
-        enterFacilitiesSync(List.of(omniboxFacility, softKeyboard), urlBarElement.clickTrigger());
+        enterFacilitiesSync(
+                List.of(omniboxFacility, softKeyboard), urlBarElement.getClickTrigger());
         return Pair.create(omniboxFacility, softKeyboard);
     }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java
index 45c43c7..444b7c1 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/quick_delete/QuickDeleteDialogFacility.java
@@ -93,7 +93,7 @@
 
     /** Click Cancel to close the dialog with no action. */
     public void clickCancel() {
-        mHostStation.exitFacilitySync(this, cancelButtonElement.clickTrigger());
+        mHostStation.exitFacilitySync(this, cancelButtonElement.getClickTrigger());
     }
 
     /**
@@ -106,7 +106,7 @@
         QuickDeleteSnackbarFacility snackbar = new QuickDeleteSnackbarFacility(mTimePeriod);
         tabSwitcher.addInitialFacility(snackbar);
 
-        mHostStation.travelToSync(tabSwitcher, deleteButtonElement.clickTrigger());
+        mHostStation.travelToSync(tabSwitcher, deleteButtonElement.getClickTrigger());
 
         return Pair.create(tabSwitcher, snackbar);
     }
@@ -145,7 +145,7 @@
     public SettingsStation<ClearBrowsingDataFragment> clickMoreOptions() {
         return mHostStation.travelToSync(
                 new SettingsStation<>(ClearBrowsingDataFragment.class),
-                moreOptionsElement.clickTrigger());
+                moreOptionsElement.getClickTrigger());
     }
 
     public SearchHistoryDisambiguiationFacility expectSearchHistoryDisambiguation(boolean shown) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/BlankPopupOnLoadPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/BlankPopupOnLoadPageStation.java
new file mode 100644
index 0000000..a485b08
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/BlankPopupOnLoadPageStation.java
@@ -0,0 +1,44 @@
+// Copyright 2025 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.test.transit.testhtmls;
+
+import android.util.Pair;
+
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.transit.page.PageStation;
+import org.chromium.chrome.test.transit.page.PopupBlockedMessageFacility;
+import org.chromium.chrome.test.transit.page.WebPageStation;
+
+/** PageStation for popup_blank_test.html, which opens a blank pop-up upon loading. */
+public class BlankPopupOnLoadPageStation extends WebPageStation {
+    public static final String PATH = "/chrome/test/data/android/popup_blank_test.html";
+
+    protected <T extends BlankPopupOnLoadPageStation> BlankPopupOnLoadPageStation(
+            Builder<T> builder) {
+        super(builder);
+    }
+
+    /**
+     * Load popup_blank_test.html in current tab and expect the pop-up to be blocked and a pop-up
+     * blocked message to be displayed.
+     *
+     * @return the now active BlankPopupOnLoadPageStation and the entered
+     *     PopupBlockedMessageFacility
+     */
+    public static Pair<BlankPopupOnLoadPageStation, PopupBlockedMessageFacility>
+            loadInCurrentTabExpectBlocked(
+                    ChromeTabbedActivityTestRule activityTestRule, PageStation currentPageStation) {
+        String url = activityTestRule.getTestServer().getURL(PATH);
+        PopupBlockedMessageFacility<BlankPopupOnLoadPageStation> popupBlockedMessage =
+                new PopupBlockedMessageFacility<>(1);
+        BlankPopupOnLoadPageStation newPage =
+                currentPageStation.loadPageProgrammatically(
+                        url,
+                        new Builder<BlankPopupOnLoadPageStation>(BlankPopupOnLoadPageStation::new)
+                                .withFacility(popupBlockedMessage));
+
+        return Pair.create(newPage, popupBlockedMessage);
+    }
+}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnClickPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnClickPageStation.java
index c6ffdbb..fde0b93 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnClickPageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/PopupOnClickPageStation.java
@@ -47,7 +47,7 @@
                         .withIsOpeningTabs(1)
                         .withIsSelectingTabs(1)
                         .build();
-        return travelToSync(newPage, mLinkToPopup::click);
+        return travelToSync(newPage, mLinkToPopup.getClickTrigger());
     }
 
     /**
@@ -56,6 +56,7 @@
      */
     public PopupBlockedMessageFacility clickLinkAndExpectPopupBlockedMessage() {
         return enterFacilitySync(
-                new PopupBlockedMessageFacility<PopupOnClickPageStation>(1), mLinkToPopup::click);
+                new PopupBlockedMessageFacility<PopupOnClickPageStation>(1),
+                mLinkToPopup.getClickTrigger());
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/TopBottomLinksPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/TopBottomLinksPageStation.java
index d7a80dca..4652b62 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/TopBottomLinksPageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/testhtmls/TopBottomLinksPageStation.java
@@ -81,7 +81,7 @@
         /** Open context menu on the top link. */
         public LinkContextMenuFacility openContextMenuOnTopLink() {
             return mHostStation.enterFacilitySync(
-                    new LinkContextMenuFacility(), mTopElement::longPress);
+                    new LinkContextMenuFacility(), mTopElement.getLongPressTrigger());
         }
 
         /** Scroll to the bottom of the page. */
@@ -107,7 +107,7 @@
         /** Open context menu on the bottom link. */
         public LinkContextMenuFacility openContextMenuOnBottomLink() {
             return mHostStation.enterFacilitySync(
-                    new LinkContextMenuFacility(), mBottomElement::longPress);
+                    new LinkContextMenuFacility(), mBottomElement.getLongPressTrigger());
         }
     }
 }
diff --git a/chrome/test/base/android/android_browser_test.cc b/chrome/test/base/android/android_browser_test.cc
index 84730fdb..230585d 100644
--- a/chrome/test/base/android/android_browser_test.cc
+++ b/chrome/test/base/android/android_browser_test.cc
@@ -10,6 +10,11 @@
 #include "chrome/test/base/chrome_test_utils.h"
 #include "chrome/test/base/test_launcher_utils.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/buildflags/buildflags.h"
+
+#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
+#include "extensions/common/extension_features.h"
+#endif
 
 namespace {
 AndroidBrowserTest* g_current_test = nullptr;
@@ -17,6 +22,11 @@
 
 AndroidBrowserTest::AndroidBrowserTest() {
   CreateTestServer(base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
+  // Allow unpacked extensions without developer mode for testing.
+  feature_list_.InitAndDisableFeature(
+      extensions_features::kExtensionDisableUnsupportedDeveloper);
+#endif
   g_current_test = this;
 }
 
diff --git a/chrome/test/base/android/android_browser_test.h b/chrome/test/base/android/android_browser_test.h
index 4db3709c..d66f53a 100644
--- a/chrome/test/base/android/android_browser_test.h
+++ b/chrome/test/base/android/android_browser_test.h
@@ -6,6 +6,7 @@
 #define CHROME_TEST_BASE_ANDROID_ANDROID_BROWSER_TEST_H_
 
 #include "base/files/scoped_temp_dir.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/public/test/browser_test_base.h"
 
 class PrefService;
@@ -70,6 +71,8 @@
   // Temporary user data directory. Used only when a user data directory is not
   // specified in the command line.
   base::ScopedTempDir temp_user_data_dir_;
+
+  base::test::ScopedFeatureList feature_list_;
 };
 
 #endif  // CHROME_TEST_BASE_ANDROID_ANDROID_BROWSER_TEST_H_
diff --git a/chrome/test/data/android/popup_blank_test.html b/chrome/test/data/android/popup_blank_test.html
new file mode 100644
index 0000000..406d409
--- /dev/null
+++ b/chrome/test/data/android/popup_blank_test.html
@@ -0,0 +1,8 @@
+<html>
+  <head>
+    <title>Popup test page</title>
+  </head>
+  <body onload="window.open('')">
+    Spawning a blank popup window...
+  </body>
+</html>
diff --git a/chrome/test/data/webui/glic/api_test.ts b/chrome/test/data/webui/glic/api_test.ts
index 02fb2f8..c92e57f2 100644
--- a/chrome/test/data/webui/glic/api_test.ts
+++ b/chrome/test/data/webui/glic/api_test.ts
@@ -568,10 +568,7 @@
     // The client should be able to use getDisplayMedia() to capture the glic
     // window.
     const stream = await navigator.mediaDevices.getDisplayMedia({
-      video: {
-        cursor: 'always',
-        displaySurface: 'browser',
-      } as MediaTrackConstraints,
+      video: true,
       audio: false,
       preferCurrentTab: true,
     } as any);
@@ -785,6 +782,8 @@
         location.href = '/sorry/index.html';
       });
     }
+    // This initialization is sometimes skipped depending on the type of desired
+    // failure detected above
     return super.initialize(glicBrowserHost);
   }
 }
@@ -803,22 +802,25 @@
   // testParams when `createWebClient()` is called.
   override async setUpClient() {}
 
-  async testInitializeFailsWindowClosed() {
-    // Failing initialize will tear down this web contents. Deferring that here
-    // so that our test can exit cleanly.
+  // Runs ApiTestFixtureBase.setUpClient() after 100 ms, and returns
+  // immediately. This allows the test to exit cleanly before the web contents
+  // is torn down.
+  deferredSetUpClient() {
     sleep(100).then(() => super.setUpClient());
   }
 
+  async testInitializeFailsWindowClosed() {
+    this.deferredSetUpClient();
+  }
+
   async testInitializeFailsWindowOpen() {
-    // Failing initialize will tear down this web contents. Deferring that here
-    // so that our test can exit cleanly.
-    sleep(100).then(() => super.setUpClient());
+    this.deferredSetUpClient();
   }
 
   async testReload() {
     // First run.
     if (this.getTestParams().failWith === 'reloadAfterInitialize') {
-      sleep(100).then(() => super.setUpClient());
+      this.deferredSetUpClient();
       return;
     }
 
@@ -828,15 +830,15 @@
   }
 
   async testSorryPageBeforeInitialize() {
-    sleep(100).then(() => super.setUpClient());
+    this.deferredSetUpClient();
   }
 
   async testSorryPageAfterInitialize() {
-    sleep(100).then(() => super.setUpClient());
+    this.deferredSetUpClient();
   }
 
   async testInitializeFailsAfterReload() {
-    sleep(100).then(() => super.setUpClient());
+    this.deferredSetUpClient();
   }
 
   async testInitializeTimesOut() {
diff --git a/chrome/test/data/webui/glic/test_client/test_client.ts b/chrome/test/data/webui/glic/test_client/test_client.ts
index f5eb04c..1afdbdb 100644
--- a/chrome/test/data/webui/glic/test_client/test_client.ts
+++ b/chrome/test/data/webui/glic/test_client/test_client.ts
@@ -187,8 +187,6 @@
   $.panelScreenshot.addEventListener('click', async () => {
     const stream = await navigator.mediaDevices.getDisplayMedia({
       video: {
-        cursor: 'always',
-        displaySurface: 'browser',
         height: 200,
         width: 200,
       },
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn
index 3109313..7d2c817 100644
--- a/chrome/test/data/webui/new_tab_page/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -11,7 +11,6 @@
             "background_manager_test.ts",
             "doodle_share_dialog_focus_test.ts",
             "doodle_share_dialog_test.ts",
-            "footer_test.ts",
             "image_processor_test.ts",
             "image_processor_test_support.ts",
             "lens_form_test.ts",
diff --git a/chrome/test/data/webui/new_tab_page/app_test.ts b/chrome/test/data/webui/new_tab_page/app_test.ts
index d2df90ea..44f7ccda 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.ts
+++ b/chrome/test/data/webui/new_tab_page/app_test.ts
@@ -276,8 +276,13 @@
       assertEquals(
           0xffff0000 /* red */,
           (await backgroundManager.whenCalled('setBackgroundColor')).value);
+      assertStyle(
+          $$(app, '#content')!, '--color-new-tab-page-attribution-foreground',
+          'rgba(0, 0, 255, 1.00)');
       assertEquals(1, backgroundManager.getCallCount('setShowBackgroundImage'));
       assertFalse(await backgroundManager.whenCalled('setShowBackgroundImage'));
+      assertStyle($$(app, '#backgroundImageAttribution')!, 'display', 'none');
+      assertStyle($$(app, '#backgroundImageAttribution2')!, 'display', 'none');
       assertFalse(app.$.logo.singleColored);
       assertFalse(app.$.logo.dark);
       assertEquals(0xffff0000, app.$.logo.backgroundColor.value);
@@ -304,10 +309,6 @@
       // Arrange.
       const theme = createTheme();
       theme.backgroundImage = createBackgroundImage('https://img.png');
-      const footer = $$(app, 'ntp-footer');
-      assertTrue(!!footer);
-      assertStyle(
-          footer, '--ntp-protected-icon-background-color', 'transparent');
 
       // Act.
       backgroundManager.resetResolver('setShowBackgroundImage');
@@ -320,8 +321,11 @@
 
       // Scrim removal will remove text shadows as background protection is
       // applied to the background element instead.
+      assertNotStyle(
+          $$(app, '#backgroundImageAttribution')!, 'background-color',
+          'rgba(0, 0, 0, 0)');
       assertStyle(
-          footer, '--ntp-protected-icon-background-color', 'rgba(0, 0, 0, .6)');
+          $$(app, '#backgroundImageAttribution')!, 'text-shadow', 'none');
 
       assertEquals(1, backgroundManager.getCallCount('setBackgroundImage'));
       assertEquals(
@@ -330,6 +334,31 @@
       assertEquals(null, app.$.logo.backgroundColor);
     });
 
+    test('setting attributions shows attributions', async function() {
+      // Arrange.
+      const theme = createTheme();
+      theme.backgroundImageAttribution1 = 'foo';
+      theme.backgroundImageAttribution2 = 'bar';
+      theme.backgroundImageAttributionUrl = {url: 'https://info.com'};
+
+      // Act.
+      callbackRouterRemote.setTheme(theme);
+      await callbackRouterRemote.$.flushForTesting();
+
+      // Assert.
+      assertNotStyle(
+          $$(app, '#backgroundImageAttribution')!, 'display', 'none');
+      assertNotStyle(
+          $$(app, '#backgroundImageAttribution2')!, 'display', 'none');
+      assertEquals(
+          'https://info.com',
+          $$(app, '#backgroundImageAttribution')!.getAttribute('href'));
+      assertEquals(
+          'foo', $$(app, '#backgroundImageAttribution1')!.textContent!.trim());
+      assertEquals(
+          'bar', $$(app, '#backgroundImageAttribution2')!.textContent!.trim());
+    });
+
     test('setting logo color colors logo', async function() {
       // Arrange.
       const theme = createTheme();
diff --git a/chrome/test/data/webui/new_tab_page/footer_test.ts b/chrome/test/data/webui/new_tab_page/footer_test.ts
deleted file mode 100644
index 4c4c7ce0..0000000
--- a/chrome/test/data/webui/new_tab_page/footer_test.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://new-tab-page/lazy_load.js';
-
-import type {FooterElement} from 'chrome://new-tab-page/lazy_load.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
-import {microtasksFinished} from 'chrome://webui-test/test_util.js';
-
-import {assertNotStyle, assertStyle, createTheme} from './test_support.js';
-
-suite('Footer', () => {
-  let footer: FooterElement;
-
-  setup(() => {
-    document.body.innerHTML = window.trustedTypes!.emptyHTML;
-    footer = document.createElement('ntp-footer');
-    document.body.appendChild(footer);
-    return microtasksFinished();
-  });
-
-  suite('Background Attribution', () => {
-    test('setting theme updates attribution', async () => {
-      // Arrange/Act.
-      footer.theme = createTheme();
-      await microtasksFinished();
-
-      // Assert.
-      assertStyle(
-          footer.$.footerContainer,
-          '--color-new-tab-page-attribution-foreground',
-          'rgba(0, 0, 255, 1.00)');
-      assertStyle(footer.$.backgroundImageAttribution, 'display', 'none');
-      assertStyle(footer.$.backgroundImageAttribution2, 'display', 'none');
-    });
-
-    test('setting attributions shows attributions', async function() {
-      // Arrange.
-      const theme = createTheme();
-      theme.backgroundImageAttribution1 = 'foo';
-      theme.backgroundImageAttribution2 = 'bar';
-      theme.backgroundImageAttributionUrl = {url: 'https://info.com'};
-
-      // Act.
-      footer.theme = theme;
-      await microtasksFinished();
-
-      // Assert.
-      assertNotStyle(footer.$.backgroundImageAttribution, 'display', 'none');
-      assertNotStyle(footer.$.backgroundImageAttribution2, 'display', 'none');
-      assertEquals(
-          'https://info.com',
-          footer.$.backgroundImageAttribution.getAttribute('href'));
-      assertEquals(
-          'foo', footer.$.backgroundImageAttribution1.textContent!.trim());
-      assertEquals(
-          'bar', footer.$.backgroundImageAttribution2.textContent!.trim());
-    });
-  });
-});
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
index 5546160..5115943 100644
--- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
+++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
@@ -65,10 +65,6 @@
   RunTest("new_tab_page/transparency_test.js", "mocha.run()");
 }
 
-IN_PROC_BROWSER_TEST_F(NewTabPageTest, Footer) {
-  RunTest("new_tab_page/footer_test.js", "mocha.run()");
-}
-
 using NewTabPageModulesTest = NewTabPageBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(NewTabPageModulesTest, ModuleWrapper) {
diff --git a/chrome/test/data/webui/settings/glic_page_test.ts b/chrome/test/data/webui/settings/glic_page_test.ts
index f78ad185c..ff3dc86 100644
--- a/chrome/test/data/webui/settings/glic_page_test.ts
+++ b/chrome/test/data/webui/settings/glic_page_test.ts
@@ -86,320 +86,82 @@
     return createGlicPage(/*initialShortcut=*/ '⌃A');
   });
 
-  test('LauncherToggleEnabled', () => {
-    page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
-
-    assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
-  });
-
-  test('LauncherToggleDisabled', () => {
-    page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
-
-    assertFalse($<SettingsToggleButtonElement>('launcherToggle')!.checked);
-  });
-
-  for (const clickType of [clickToggle, clickToggleRow]) {
-    const clickTypeName = clickType.name.replace('click', '');
-    test('Launcher' + clickTypeName + 'Change', async () => {
-      page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
-
-      const launcherToggle = $<SettingsToggleButtonElement>('launcherToggle')!;
-
-      await clickType();
-      assertTrue(page.getPref(PrefName.LAUNCHER_ENABLED).value);
-      assertTrue(launcherToggle.checked);
-      assertEquals(
-          1, glicBrowserProxy.getCallCount('setGlicOsLauncherEnabled'));
-      glicBrowserProxy.reset();
-
-      await clickType();
-      assertFalse(page.getPref(PrefName.LAUNCHER_ENABLED).value);
-      assertFalse(launcherToggle.checked);
-      assertEquals(
-          1, glicBrowserProxy.getCallCount('setGlicOsLauncherEnabled'));
-      glicBrowserProxy.reset();
-    });
-
-    // Test that the keyboard shortcut is collapsed/invisible when the
-    // launcher is disabled and shown when the launcher is enabled.
-    test('KeyboardShortcutVisibility' + clickTypeName, async () => {
-      const keyboardShortcutSetting = $('keyboardShortcutSetting');
-
-      // The pref starts off disabled, the keyboard shortcut row should be
-      // hidden.
-      page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
-      assertFalse(isVisible(keyboardShortcutSetting));
-
-      // Enable using the launcher toggle, the row should show.
-      await clickType();
-      assertTrue(page.getPref(PrefName.LAUNCHER_ENABLED).value);
-      assertTrue(isVisible(keyboardShortcutSetting));
-
-      // Disable using the launcher toggle, the row should hide.
-      await clickType();
-      assertFalse(page.getPref(PrefName.LAUNCHER_ENABLED).value);
-      assertFalse(isVisible(keyboardShortcutSetting));
-
-      // Enable via pref, the row should show.
+  suite('Default', () => {
+    test('LauncherToggleEnabled', () => {
       page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
-      await flushTasks();
-      assertTrue(isVisible(keyboardShortcutSetting));
+
+      assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
     });
-  }
 
-  test('GeolocationToggleEnabled', () => {
-    page.setPrefValue(PrefName.GEOLOCATION_ENABLED, true);
+    test('LauncherToggleDisabled', () => {
+      page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
 
-    assertTrue($<SettingsToggleButtonElement>('geolocationToggle')!.checked);
-  });
+      assertFalse($<SettingsToggleButtonElement>('launcherToggle')!.checked);
+    });
 
-  test('GeolocationToggleDisabled', () => {
-    page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
+    for (const clickType of [clickToggle, clickToggleRow]) {
+      const clickTypeName = clickType.name.replace('click', '');
+      test('Launcher' + clickTypeName + 'Change', async () => {
+        page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
 
-    assertFalse($<SettingsToggleButtonElement>('geolocationToggle')!.checked);
-  });
+        const launcherToggle =
+            $<SettingsToggleButtonElement>('launcherToggle')!;
 
-  test('GeolocationToggleChange', () => {
-    page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
+        await clickType();
+        assertTrue(page.getPref(PrefName.LAUNCHER_ENABLED).value);
+        assertTrue(launcherToggle.checked);
+        assertEquals(
+            1, glicBrowserProxy.getCallCount('setGlicOsLauncherEnabled'));
+        glicBrowserProxy.reset();
 
-    const geolocationToggle =
-        $<SettingsToggleButtonElement>('geolocationToggle')!;
-    assertTrue(!!geolocationToggle);
+        await clickType();
+        assertFalse(page.getPref(PrefName.LAUNCHER_ENABLED).value);
+        assertFalse(launcherToggle.checked);
+        assertEquals(
+            1, glicBrowserProxy.getCallCount('setGlicOsLauncherEnabled'));
+        glicBrowserProxy.reset();
+      });
 
-    geolocationToggle.click();
-    assertTrue(page.getPref(PrefName.GEOLOCATION_ENABLED).value);
-    assertTrue(geolocationToggle.checked);
+      // Test that the keyboard shortcut is collapsed/invisible when the
+      // launcher is disabled and shown when the launcher is enabled.
+      test('KeyboardShortcutVisibility' + clickTypeName, async () => {
+        const keyboardShortcutSetting = $('keyboardShortcutSetting');
 
-    geolocationToggle.click();
-    assertFalse(page.getPref(PrefName.GEOLOCATION_ENABLED).value);
-    assertFalse(geolocationToggle.checked);
-  });
+        // The pref starts off disabled, the keyboard shortcut row should be
+        // hidden.
+        page.setPrefValue(PrefName.LAUNCHER_ENABLED, false);
+        assertFalse(isVisible(keyboardShortcutSetting));
 
-  test('MicrophoneToggleEnabled', () => {
-    page.setPrefValue(PrefName.MICROPHONE_ENABLED, true);
+        // Enable using the launcher toggle, the row should show.
+        await clickType();
+        assertTrue(page.getPref(PrefName.LAUNCHER_ENABLED).value);
+        assertTrue(isVisible(keyboardShortcutSetting));
 
-    assertTrue($<SettingsToggleButtonElement>('microphoneToggle')!.checked);
-  });
+        // Disable using the launcher toggle, the row should hide.
+        await clickType();
+        assertFalse(page.getPref(PrefName.LAUNCHER_ENABLED).value);
+        assertFalse(isVisible(keyboardShortcutSetting));
 
-  test('MicrophoneToggleDisabled', () => {
-    page.setPrefValue(PrefName.MICROPHONE_ENABLED, false);
-
-    assertFalse($<SettingsToggleButtonElement>('microphoneToggle')!.checked);
-  });
-
-  test('MicrophoneToggleChange', () => {
-    page.setPrefValue(PrefName.MICROPHONE_ENABLED, false);
-
-    const microphoneToggle =
-        $<SettingsToggleButtonElement>('microphoneToggle')!;
-    assertTrue(!!microphoneToggle);
-
-    microphoneToggle.click();
-    assertTrue(page.getPref(PrefName.MICROPHONE_ENABLED).value);
-    assertTrue(microphoneToggle.checked);
-
-    microphoneToggle.click();
-    assertFalse(page.getPref(PrefName.MICROPHONE_ENABLED).value);
-    assertFalse(microphoneToggle.checked);
-  });
-
-  test('TabContextToggleEnabled', () => {
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
-
-    assertTrue($<SettingsToggleButtonElement>('tabAccessToggle')!.checked);
-  });
-
-  test('TabContextToggleDisabled', () => {
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
-
-    assertFalse($<SettingsToggleButtonElement>('tabAccessToggle')!.checked);
-  });
-
-  test('TabContextToggleChange', () => {
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
-
-    const tabAccessToggle = $<SettingsToggleButtonElement>('tabAccessToggle');
-    assertTrue(!!tabAccessToggle);
-
-    tabAccessToggle.click();
-    assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertTrue(tabAccessToggle.checked);
-
-    tabAccessToggle.click();
-    assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertFalse(tabAccessToggle.checked);
-  });
-
-  test('TabContextExpand', async () => {
-    const tabAccessToggle = $<SettingsToggleButtonElement>('tabAccessToggle')!;
-    const expandButton =
-        $<SettingsToggleButtonElement>('tabAccessExpandButton')!;
-    const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse')!;
-
-    assertFalse(infoCard.opened);
-
-    // Clicking the expand button opens the info card.
-    expandButton.click();
-    await flushTasks();
-    assertTrue(infoCard.opened);
-    assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-
-    // Clicking the expand button again collapses the info card.
-    expandButton.click();
-    await flushTasks();
-    assertFalse(infoCard.opened);
-    assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-
-    // Toggling the setting to on opens the info card.
-    tabAccessToggle.click();
-    await flushTasks();
-    assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertTrue(infoCard.opened);
-
-    // Toggling the setting off closes the info card.
-    tabAccessToggle.click();
-    await flushTasks();
-    assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertFalse(infoCard.opened);
-
-    // Toggling the setting to on while the info card is open leaves it open.
-    expandButton.click();
-    await flushTasks();
-    assertTrue(infoCard.opened);
-    tabAccessToggle.click();
-    await flushTasks();
-    assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertTrue(infoCard.opened);
-
-    // Toggling the setting to off while the info card is closed leaves it
-    // closed.
-    expandButton.click();
-    await flushTasks();
-    assertFalse(infoCard.opened);
-    tabAccessToggle.click();
-    await flushTasks();
-    assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
-    assertFalse(infoCard.opened);
-  });
-
-  // Ensure the page reacts appropriately to the enterprise policy pref being
-  // flipped off and back on.
-  test('DisabledByPolicy', async () => {
-    page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
-    page.setPrefValue(PrefName.GEOLOCATION_ENABLED, true);
-    page.setPrefValue(PrefName.MICROPHONE_ENABLED, true);
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
-
-    // Page starts off with policy enabled. The shortcut editor, info card
-    // expand, and activity button are all present.
-    assertTrue(!!$('shortcutInput'));
-    assertTrue(isVisible($('shortcutInput')));
-    assertTrue(!!$('activityButton'));
-    assertTrue(!!$('tabAccessExpandButton'));
-    assertTrue(!!$('tabAccessInfoCollapse'));
-
-    // Toggles should all have values from the real pref and be enabled.
-    let toggles = page.shadowRoot!.querySelectorAll(
-        'settings-toggle-button[checked]:not([disabled])');
-    assertEquals(4, toggles.length);
-
-    page.setPrefValue(PrefName.SETTINGS_POLICY, POLICY_DISABLED_VALUE);
-    await flushTasks();
-
-    // Now that the policy is disabled, the shortcut edit, info card expand,
-    // and activity button should be removed. Toggles should all show "off"
-    // and be disabled.
-    assertFalse(!!$('shortcutInput'));
-    assertFalse(!!$('activityButton'));
-    assertFalse(!!$('tabAccessExpandButton'));
-    assertFalse(!!$('tabAccessInfoCollapse'));
-
-    toggles = page.shadowRoot!.querySelectorAll(
-        'settings-toggle-button:not([checked])[disabled]');
-    assertEquals(4, toggles.length);
-
-    // Re-enable the policy, the page should go back to the initial state.
-    page.setPrefValue(PrefName.SETTINGS_POLICY, POLICY_ENABLED_VALUE);
-    await flushTasks();
-
-    assertTrue(!!$('shortcutInput'));
-    assertTrue(isVisible($('shortcutInput')));
-    assertTrue(!!$('activityButton'));
-    assertTrue(!!$('tabAccessExpandButton'));
-    assertTrue(!!$('tabAccessInfoCollapse'));
-
-    toggles = page.shadowRoot!.querySelectorAll(
-        'settings-toggle-button[checked]:not([disabled])');
-    assertEquals(4, toggles.length);
-  });
-
-  test('ClickGlicRowInGlicSection', async () => {
-    Router.getInstance().navigateTo(routes.AI);
-    await flushTasks();
-
-    const glicRow = $<HTMLElement>('glicLinkRow');
-    assertTrue(!!glicRow);
-    assertTrue(isVisible(glicRow));
-
-    glicRow.click();
-    assertEquals(
-        routes.GEMINI.path, Router.getInstance().getCurrentRoute().path);
-  });
-
-  test('ManageActivityRow', async () => {
-    page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
-
-    const activityButton = $<HTMLElement>('activityButton');
-    assertTrue(!!activityButton);
-
-    activityButton.click();
-    const url = await openWindowProxy.whenCalled('openUrl');
-    assertEquals(page.i18n('glicActivityButtonUrl'), url);
-  });
-
-  // Ensure that the info collapse is initialized correctly when the tab
-  // context pref is enabled when the page is created.
-  test('InfoCollapseInitializiedOpen', async () => {
-    // Clear and re-create a new page rather than using the one initialized in
-    // setup().
-    document.body.innerHTML = window.trustedTypes!.emptyHTML;
-    page = document.createElement('settings-glic-page');
-    page.prefs = settingsPrefs.prefs;
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
-    Router.getInstance().navigateTo(routes.GEMINI);
-    document.body.appendChild(page);
-
-    await flushTasks();
-
-    const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse');
-    assertTrue(!!infoCard);
-    assertTrue(infoCard.opened);
-  });
-
-  test('InfoCollapseInitializiedClosed', async () => {
-    document.body.innerHTML = window.trustedTypes!.emptyHTML;
-    page = document.createElement('settings-glic-page');
-    page.prefs = settingsPrefs.prefs;
-    page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
-    Router.getInstance().navigateTo(routes.GEMINI);
-    document.body.appendChild(page);
-
-    await flushTasks();
-
-    const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse');
-    assertTrue(!!infoCard);
-    assertFalse(infoCard.opened);
-  });
-
-  suite('Metrics', () => {
-    async function verifyUserAction(userAction: string) {
-      const userActions = await metricsBrowserProxy.getArgs('recordAction');
-      assertEquals(1, userActions.length);
-      assertTrue(userActions.includes(userAction));
-      metricsBrowserProxy.reset();
+        // Enable via pref, the row should show.
+        page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
+        await flushTasks();
+        assertTrue(isVisible(keyboardShortcutSetting));
+      });
     }
 
-    test('GeolocationToggle', async () => {
+    test('GeolocationToggleEnabled', () => {
+      page.setPrefValue(PrefName.GEOLOCATION_ENABLED, true);
+
+      assertTrue($<SettingsToggleButtonElement>('geolocationToggle')!.checked);
+    });
+
+    test('GeolocationToggleDisabled', () => {
+      page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
+
+      assertFalse($<SettingsToggleButtonElement>('geolocationToggle')!.checked);
+    });
+
+    test('GeolocationToggleChange', () => {
       page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
 
       const geolocationToggle =
@@ -407,13 +169,27 @@
       assertTrue(!!geolocationToggle);
 
       geolocationToggle.click();
-      await verifyUserAction('Glic.Settings.Geolocation.Enabled');
+      assertTrue(page.getPref(PrefName.GEOLOCATION_ENABLED).value);
+      assertTrue(geolocationToggle.checked);
 
       geolocationToggle.click();
-      await verifyUserAction('Glic.Settings.Geolocation.Disabled');
+      assertFalse(page.getPref(PrefName.GEOLOCATION_ENABLED).value);
+      assertFalse(geolocationToggle.checked);
     });
 
-    test('MicrophoneToggle', async () => {
+    test('MicrophoneToggleEnabled', () => {
+      page.setPrefValue(PrefName.MICROPHONE_ENABLED, true);
+
+      assertTrue($<SettingsToggleButtonElement>('microphoneToggle')!.checked);
+    });
+
+    test('MicrophoneToggleDisabled', () => {
+      page.setPrefValue(PrefName.MICROPHONE_ENABLED, false);
+
+      assertFalse($<SettingsToggleButtonElement>('microphoneToggle')!.checked);
+    });
+
+    test('MicrophoneToggleChange', () => {
       page.setPrefValue(PrefName.MICROPHONE_ENABLED, false);
 
       const microphoneToggle =
@@ -421,44 +197,278 @@
       assertTrue(!!microphoneToggle);
 
       microphoneToggle.click();
-      await verifyUserAction('Glic.Settings.Microphone.Enabled');
+      assertTrue(page.getPref(PrefName.MICROPHONE_ENABLED).value);
+      assertTrue(microphoneToggle.checked);
 
       microphoneToggle.click();
-      await verifyUserAction('Glic.Settings.Microphone.Disabled');
+      assertFalse(page.getPref(PrefName.MICROPHONE_ENABLED).value);
+      assertFalse(microphoneToggle.checked);
     });
 
-    test('TabContextToggle', async () => {
+    test('TabContextToggleEnabled', () => {
+      page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
+
+      assertTrue($<SettingsToggleButtonElement>('tabAccessToggle')!.checked);
+    });
+
+    test('TabContextToggleDisabled', () => {
       page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
 
-      const tabAccessToggle =
-          $<SettingsToggleButtonElement>('tabAccessToggle')!;
+      assertFalse($<SettingsToggleButtonElement>('tabAccessToggle')!.checked);
+    });
+
+    test('TabContextToggleChange', () => {
+      page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
+
+      const tabAccessToggle = $<SettingsToggleButtonElement>('tabAccessToggle');
       assertTrue(!!tabAccessToggle);
 
       tabAccessToggle.click();
-      await verifyUserAction('Glic.Settings.TabContext.Enabled');
+      assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertTrue(tabAccessToggle.checked);
 
       tabAccessToggle.click();
-      await verifyUserAction('Glic.Settings.TabContext.Disabled');
+      assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertFalse(tabAccessToggle.checked);
     });
 
-    test('keyboardShortcutLearnMore', async () => {
-      assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
-      const learnMoreLink = page.shadowRoot!.querySelector('a');
-      assertTrue(!!learnMoreLink);
-      assertEquals(learnMoreLink.href, 'https://google.com/');
+    test('TabContextExpand', async () => {
+      const tabAccessToggle =
+          $<SettingsToggleButtonElement>('tabAccessToggle')!;
+      const expandButton =
+          $<SettingsToggleButtonElement>('tabAccessExpandButton')!;
+      const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse')!;
 
-      learnMoreLink.click();
+      assertFalse(infoCard.opened);
+
+      // Clicking the expand button opens the info card.
+      expandButton.click();
+      await flushTasks();
+      assertTrue(infoCard.opened);
+      assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+
+      // Clicking the expand button again collapses the info card.
+      expandButton.click();
+      await flushTasks();
+      assertFalse(infoCard.opened);
+      assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+
+      // Toggling the setting to on opens the info card.
+      tabAccessToggle.click();
+      await flushTasks();
+      assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertTrue(infoCard.opened);
+
+      // Toggling the setting off closes the info card.
+      tabAccessToggle.click();
+      await flushTasks();
+      assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertFalse(infoCard.opened);
+
+      // Toggling the setting to on while the info card is open leaves it open.
+      expandButton.click();
+      await flushTasks();
+      assertTrue(infoCard.opened);
+      tabAccessToggle.click();
+      await flushTasks();
+      assertTrue(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertTrue(infoCard.opened);
+
+      // Toggling the setting to off while the info card is closed leaves it
+      // closed.
+      expandButton.click();
+      await flushTasks();
+      assertFalse(infoCard.opened);
+      tabAccessToggle.click();
+      await flushTasks();
+      assertFalse(page.getPref(PrefName.TAB_CONTEXT_ENABLED).value);
+      assertFalse(infoCard.opened);
+    });
+
+    // Ensure the page reacts appropriately to the enterprise policy pref being
+    // flipped off and back on.
+    test('DisabledByPolicy', async () => {
+      page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
+      page.setPrefValue(PrefName.GEOLOCATION_ENABLED, true);
+      page.setPrefValue(PrefName.MICROPHONE_ENABLED, true);
+      page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
+
+      // Page starts off with policy enabled. The shortcut editor, info card
+      // expand, and activity button are all present.
+      assertTrue(!!$('shortcutInput'));
+      assertTrue(isVisible($('shortcutInput')));
+      assertTrue(!!$('activityButton'));
+      assertTrue(!!$('tabAccessExpandButton'));
+      assertTrue(!!$('tabAccessInfoCollapse'));
+
+      // Toggles should all have values from the real pref and be enabled.
+      let toggles = page.shadowRoot!.querySelectorAll(
+          'settings-toggle-button[checked]:not([disabled])');
+      assertEquals(4, toggles.length);
+
+      page.setPrefValue(PrefName.SETTINGS_POLICY, POLICY_DISABLED_VALUE);
+      await flushTasks();
+
+      // Now that the policy is disabled, the shortcut edit, info card expand,
+      // and activity button should be removed. Toggles should all show "off"
+      // and be disabled.
+      assertFalse(!!$('shortcutInput'));
+      assertFalse(!!$('activityButton'));
+      assertFalse(!!$('tabAccessExpandButton'));
+      assertFalse(!!$('tabAccessInfoCollapse'));
+
+      toggles = page.shadowRoot!.querySelectorAll(
+          'settings-toggle-button:not([checked])[disabled]');
+      assertEquals(4, toggles.length);
+
+      // Re-enable the policy, the page should go back to the initial state.
+      page.setPrefValue(PrefName.SETTINGS_POLICY, POLICY_ENABLED_VALUE);
+      await flushTasks();
+
+      assertTrue(!!$('shortcutInput'));
+      assertTrue(isVisible($('shortcutInput')));
+      assertTrue(!!$('activityButton'));
+      assertTrue(!!$('tabAccessExpandButton'));
+      assertTrue(!!$('tabAccessInfoCollapse'));
+
+      toggles = page.shadowRoot!.querySelectorAll(
+          'settings-toggle-button[checked]:not([disabled])');
+      assertEquals(4, toggles.length);
+    });
+
+    test('ClickGlicRowInGlicSection', async () => {
+      Router.getInstance().navigateTo(routes.AI);
+      await flushTasks();
+
+      const glicRow = $<HTMLElement>('glicLinkRow');
+      assertTrue(!!glicRow);
+      assertTrue(isVisible(glicRow));
+
+      glicRow.click();
+      assertEquals(
+          routes.GEMINI.path, Router.getInstance().getCurrentRoute().path);
+    });
+
+    test('ManageActivityRow', async () => {
+      page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
+
+      const activityButton = $<HTMLElement>('activityButton');
+      assertTrue(!!activityButton);
+
+      activityButton.click();
+      const url = await openWindowProxy.whenCalled('openUrl');
+      assertEquals(page.i18n('glicActivityButtonUrl'), url);
+    });
+
+    // Ensure that the info collapse is initialized correctly when the tab
+    // context pref is enabled when the page is created.
+    test('InfoCollapseInitializiedOpen', async () => {
+      // Clear and re-create a new page rather than using the one initialized in
+      // setup().
+      document.body.innerHTML = window.trustedTypes!.emptyHTML;
+      page = document.createElement('settings-glic-page');
+      page.prefs = settingsPrefs.prefs;
+      page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, true);
+      Router.getInstance().navigateTo(routes.GEMINI);
+      document.body.appendChild(page);
+
+      await flushTasks();
+
+      const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse');
+      assertTrue(!!infoCard);
+      assertTrue(infoCard.opened);
+    });
+
+    test('InfoCollapseInitializiedClosed', async () => {
+      document.body.innerHTML = window.trustedTypes!.emptyHTML;
+      page = document.createElement('settings-glic-page');
+      page.prefs = settingsPrefs.prefs;
+      page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
+      Router.getInstance().navigateTo(routes.GEMINI);
+      document.body.appendChild(page);
+
+      await flushTasks();
+
+      const infoCard = $<CrCollapseElement>('tabAccessInfoCollapse');
+      assertTrue(!!infoCard);
+      assertFalse(infoCard.opened);
+    });
+
+    suite('Metrics', () => {
+      async function verifyUserAction(userAction: string) {
+        const userActions = await metricsBrowserProxy.getArgs('recordAction');
+        assertEquals(1, userActions.length);
+        assertTrue(userActions.includes(userAction));
+        metricsBrowserProxy.reset();
+      }
+
+      test('GeolocationToggle', async () => {
+        page.setPrefValue(PrefName.GEOLOCATION_ENABLED, false);
+
+        const geolocationToggle =
+            $<SettingsToggleButtonElement>('geolocationToggle')!;
+        assertTrue(!!geolocationToggle);
+
+        geolocationToggle.click();
+        await verifyUserAction('Glic.Settings.Geolocation.Enabled');
+
+        geolocationToggle.click();
+        await verifyUserAction('Glic.Settings.Geolocation.Disabled');
+      });
+
+      test('MicrophoneToggle', async () => {
+        page.setPrefValue(PrefName.MICROPHONE_ENABLED, false);
+
+        const microphoneToggle =
+            $<SettingsToggleButtonElement>('microphoneToggle')!;
+        assertTrue(!!microphoneToggle);
+
+        microphoneToggle.click();
+        await verifyUserAction('Glic.Settings.Microphone.Enabled');
+
+        microphoneToggle.click();
+        await verifyUserAction('Glic.Settings.Microphone.Disabled');
+      });
+
+      test('TabContextToggle', async () => {
+        page.setPrefValue(PrefName.TAB_CONTEXT_ENABLED, false);
+
+        const tabAccessToggle =
+            $<SettingsToggleButtonElement>('tabAccessToggle')!;
+        assertTrue(!!tabAccessToggle);
+
+        tabAccessToggle.click();
+        await verifyUserAction('Glic.Settings.TabContext.Enabled');
+
+        tabAccessToggle.click();
+        await verifyUserAction('Glic.Settings.TabContext.Disabled');
+      });
+    });
+
+    test('keyboardShortcutLearnMoreHidden', () => {
+      // No url, so the element should be hidden.
+      page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
+      assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
+      const learnMoreElement = page.shadowRoot!.querySelector<HTMLElement>(
+          '#shortcutsLearnMoreLabel')!;
+      assertFalse(isVisible(learnMoreElement));
+    });
+  });
+
+  suite('LearnMoreEnabled', () => {
+    test('keyboardShortcutLearnMoreShown', async () => {
+      page.setPrefValue(PrefName.LAUNCHER_ENABLED, true);
+      assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
+
+      const learnMoreElement =
+          page.shadowRoot!.querySelector<HTMLAnchorElement>(
+              '#shortcutsLearnMoreLabel')!;
+      assertTrue(!!learnMoreElement);
+      assertEquals(learnMoreElement.href, 'https://google.com/');
+
+      learnMoreElement.click();
       await assertFeatureInteractionMetrics(
           AiPageActions.GLIC_SHORTCUTS_LEARN_MORE_CLICKED);
     });
-
-    test('keyboardShortcutLearnMoreManaged', () => {
-      page.setPrefValue(PrefName.SETTINGS_POLICY, POLICY_ENABLED_VALUE);
-
-      assertTrue($<SettingsToggleButtonElement>('launcherToggle')!.checked);
-      const learnMoreLink = page.shadowRoot!.querySelector('a');
-      assertTrue(!!learnMoreLink);
-      assertEquals(learnMoreLink.href, 'https://google.com/');
-    });
   });
 });
diff --git a/chrome/test/data/webui/settings/privacy_guide_safe_browsing_fragment_test.ts b/chrome/test/data/webui/settings/privacy_guide_safe_browsing_fragment_test.ts
index 0e703fd..95cba1a8 100644
--- a/chrome/test/data/webui/settings/privacy_guide_safe_browsing_fragment_test.ts
+++ b/chrome/test/data/webui/settings/privacy_guide_safe_browsing_fragment_test.ts
@@ -91,7 +91,8 @@
         fragment.shadowRoot!.querySelector<SettingsCollapseRadioButtonElement>(
             '#safeBrowsingRadioEnhanced');
     assertTrue(!!enhancedProtection);
-    const epSubLabel = loadTimeData.getString('safeBrowsingEnhancedDesc');
+    const epSubLabel =
+        loadTimeData.getString('safeBrowsingEnhancedDescUpdated');
     assertEquals(epSubLabel, enhancedProtection.subLabel);
 
     const group = fragment.shadowRoot!.querySelector<HTMLElement>(
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index fc0af11..bb60d80 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -360,7 +360,28 @@
 
 #if BUILDFLAG(ENABLE_GLIC)
 IN_PROC_BROWSER_TEST_F(SettingsTest, GlicSettingsPage) {
-  RunTest("settings/glic_page_test.js", "mocha.run()");
+  RunTest("settings/glic_page_test.js", "runMochaSuite('GlicPage Default')");
+}
+
+class SettingsGlicPageLearnMoreTest : public SettingsBrowserTest {
+ public:
+  SettingsGlicPageLearnMoreTest() {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        {{features::kGlicLearnMoreURLConfig,
+          {
+              {"glic-shortcuts-learn-more-url", "https://google.com/"},
+          }}},
+        /*disabled_features=*/{});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(SettingsGlicPageLearnMoreTest,
+                       GlicSettingsLearnMoreEnabled) {
+  RunTest("settings/glic_page_test.js",
+          "runMochaSuite('GlicPage LearnMoreEnabled')");
 }
 #endif
 
diff --git a/chrome/test/interaction/ax_tree/element_tracker_ax_tree_browsertest.cc b/chrome/test/interaction/ax_tree/element_tracker_ax_tree_browsertest.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/chrome/test/interaction/ax_tree/element_tracker_ax_tree_browsertest.cc
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index d9d2e46..be753c0e 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -9,7 +9,6 @@
 import("//chrome/enterprise_companion/branding.gni")
 import("//chrome/updater/apply_updater_branding.gni")
 import("//chrome/updater/branding.gni")
-import("//chrome/updater/zip.gni")
 import("//components/crx_file/crx3.gni")
 import("//testing/test.gni")
 
diff --git a/chromeos/ash/components/assistant/assistant.gni b/chromeos/ash/components/assistant/assistant.gni
index 9ed72cb..fa090d2 100644
--- a/chromeos/ash/components/assistant/assistant.gni
+++ b/chromeos/ash/components/assistant/assistant.gni
@@ -9,11 +9,3 @@
   # See chromeos/ash/components/assistant/tools/send-audio.sh
   enable_fake_assistant_microphone = false
 }
-
-declare_args() {
-  # Enable Assistant integration tests using LibAssistant and a fake S3 server.
-  # This requires libassistant.so to support grpc communication with the S3
-  # server, which increases the library size, which is why we introduced this
-  # flag to disable them in the release builds.
-  enable_assistant_integration_tests = enable_cros_libassistant
-}
diff --git a/chromeos/ash/components/boca/BUILD.gn b/chromeos/ash/components/boca/BUILD.gn
index e0c3a88a..c09f0ab 100644
--- a/chromeos/ash/components/boca/BUILD.gn
+++ b/chromeos/ash/components/boca/BUILD.gn
@@ -36,6 +36,7 @@
     "//chromeos/services/network_config/public/cpp",
     "//chromeos/strings:strings_grit",
     "//components/prefs",
+    "//components/session_manager/core",
     "//components/sessions:session_id",
     "//components/signin/public/identity_manager",
     "//components/user_manager",
@@ -147,6 +148,7 @@
     "//components/gcm_driver:test_support",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//components/session_manager/core",
     "//components/signin/public/identity_manager",
     "//components/signin/public/identity_manager:test_support",
     "//components/soda",
diff --git a/chromeos/ash/components/boca/DEPS b/chromeos/ash/components/boca/DEPS
index ea847f9c..c4c7ec3 100644
--- a/chromeos/ash/components/boca/DEPS
+++ b/chromeos/ash/components/boca/DEPS
@@ -5,6 +5,7 @@
   "+chromeos/services/network_config/public/cpp",
   "+components/content_settings",
   "+components/gcm_driver",
+  "+components/session_manager",
   "+components/sessions/core/session_id.h",
   "+components/signin/public/identity_manager",
   "+components/soda",
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_consumer.cc b/chromeos/ash/components/boca/babelorca/babel_orca_consumer.cc
index 249354d..aa64098 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_consumer.cc
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_consumer.cc
@@ -206,6 +206,9 @@
   StartReceiving();
 }
 
+bool BabelOrcaConsumer::IsProducer() {
+  return false;
+}
 
 void BabelOrcaConsumer::DispatchTranscription(
     const media::SpeechRecognitionResult& result) {
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_consumer.h b/chromeos/ash/components/boca/babelorca/babel_orca_consumer.h
index 9d6abc4..8edb195 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_consumer.h
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_consumer.h
@@ -88,6 +88,7 @@
   void OnSessionCaptionConfigUpdated(bool session_captions_enabled,
                                      bool translations_enabled) override;
   void OnLocalCaptionConfigUpdated(bool local_captions_enabled) override;
+  bool IsProducer() override;
 
  private:
   void OnTranslationCallback(
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_controller.h b/chromeos/ash/components/boca/babelorca/babel_orca_controller.h
index afe5df5..bf9f23b 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_controller.h
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_controller.h
@@ -22,6 +22,9 @@
                                              bool translations_enabled) = 0;
 
   virtual void OnLocalCaptionConfigUpdated(bool local_captions_enabled) = 0;
+
+  virtual bool IsProducer() = 0;
+
  protected:
   BabelOrcaController() = default;
 };
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_manager.cc b/chromeos/ash/components/boca/babelorca/babel_orca_manager.cc
index 39e8638..ea8a134b 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_manager.cc
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_manager.cc
@@ -162,6 +162,18 @@
       /*local_captions_enabled=*/false);
 }
 
+void BabelOrcaManager::OnSessionCaptionClosed(bool is_error) {
+  if (!babel_orca_controller_ || !babel_orca_controller_->IsProducer()) {
+    LOG_IF(ERROR,
+           babel_orca_controller_ && !babel_orca_controller_->IsProducer())
+        << "Session caption closed called on consumer.";
+    return;
+  }
+  // `translations_enabled` has no effect for producer.
+  babel_orca_controller_->OnSessionCaptionConfigUpdated(
+      /*session_captions_enabled=*/false, /*translations_enabled=*/false);
+}
+
 bool BabelOrcaManager::IsCaptioningAvailable() {
   // TODO(b/361086008): Implement IsCaptioningAvailable();
   return true;
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_manager.h b/chromeos/ash/components/boca/babelorca/babel_orca_manager.h
index d91cc90..262e2ab 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_manager.h
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_manager.h
@@ -105,6 +105,7 @@
   void OnLocalCaptionConfigUpdated(
       const ::boca::CaptionsConfig& config) override;
   void OnLocalCaptionClosed() override;
+  void OnSessionCaptionClosed(bool is_error) override;
 
   bool IsCaptioningAvailable();
 
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_manager_unittest.cc b/chromeos/ash/components/boca/babelorca/babel_orca_manager_unittest.cc
index 63da420..708fa76 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_manager_unittest.cc
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_manager_unittest.cc
@@ -49,6 +49,7 @@
   MOCK_METHOD(void, OnSessionEnded, (), (override));
   MOCK_METHOD(void, OnSessionCaptionConfigUpdated, (bool, bool), (override));
   MOCK_METHOD(void, OnLocalCaptionConfigUpdated, (bool), (override));
+  MOCK_METHOD(bool, IsProducer, (), (override));
 };
 
 class BabelOrcaManagerTest : public testing::Test {
@@ -400,6 +401,51 @@
   manager.OnLocalCaptionClosed();
 }
 
+TEST_F(BabelOrcaManagerTest, OnSessionCaptionClosedProducer) {
+  base::test::TestFuture<bool> test_future;
+  MockBabelOrcaController* controller_ptr;
+  auto controller_factory = base::BindLambdaForTesting(
+      [&controller_ptr](babelorca::TokenManager*,
+                        babelorca::TachyonRequestDataProvider* data_provider)
+          -> std::unique_ptr<babelorca::BabelOrcaController> {
+        auto controller =
+            std::make_unique<testing::NiceMock<MockBabelOrcaController>>();
+        controller_ptr = controller.get();
+        return controller;
+      });
+  BabelOrcaManager manager(
+      &pref_service_, identity_test_env_.identity_manager(),
+      url_loader_factory_.GetSafeWeakWrapper(), std::move(controller_factory));
+
+  EXPECT_CALL(*controller_ptr, IsProducer)
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*controller_ptr, OnSessionCaptionConfigUpdated(false, false))
+      .Times(1);
+  manager.OnSessionCaptionClosed(true);
+}
+
+TEST_F(BabelOrcaManagerTest, OnSessionCaptionClosedConsumer) {
+  base::test::TestFuture<bool> test_future;
+  MockBabelOrcaController* controller_ptr;
+  auto controller_factory = base::BindLambdaForTesting(
+      [&controller_ptr](babelorca::TokenManager*,
+                        babelorca::TachyonRequestDataProvider* data_provider)
+          -> std::unique_ptr<babelorca::BabelOrcaController> {
+        auto controller =
+            std::make_unique<testing::NiceMock<MockBabelOrcaController>>();
+        controller_ptr = controller.get();
+        return controller;
+      });
+  BabelOrcaManager manager(
+      &pref_service_, identity_test_env_.identity_manager(),
+      url_loader_factory_.GetSafeWeakWrapper(), std::move(controller_factory));
+
+  EXPECT_CALL(*controller_ptr, IsProducer)
+      .WillRepeatedly(testing::Return(false));
+  EXPECT_CALL(*controller_ptr, OnSessionCaptionConfigUpdated).Times(0);
+  manager.OnSessionCaptionClosed(true);
+}
+
 TEST_F(BabelOrcaManagerTest, RequestDataProviderIsTheManager) {
   base::test::TestFuture<bool> test_future;
   babelorca::TachyonRequestDataProvider* request_data_provider;
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_producer.cc b/chromeos/ash/components/boca/babelorca/babel_orca_producer.cc
index 178cc67..7442c3c 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_producer.cc
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_producer.cc
@@ -178,6 +178,10 @@
   speech_recognizer_->Start();
 }
 
+bool BabelOrcaProducer::IsProducer() {
+  return true;
+}
+
 void BabelOrcaProducer::InitSending(bool signed_in) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!signed_in) {
diff --git a/chromeos/ash/components/boca/babelorca/babel_orca_producer.h b/chromeos/ash/components/boca/babelorca/babel_orca_producer.h
index a495aec..a5fe897a 100644
--- a/chromeos/ash/components/boca/babelorca/babel_orca_producer.h
+++ b/chromeos/ash/components/boca/babelorca/babel_orca_producer.h
@@ -73,6 +73,7 @@
   void OnSessionCaptionConfigUpdated(bool session_captions_enabled,
                                      bool translations_enabled) override;
   void OnLocalCaptionConfigUpdated(bool local_captions_enabled) override;
+  bool IsProducer() override;
 
  private:
   void InitSending(bool signed_in);
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_streaming_client.cc b/chromeos/ash/components/boca/babelorca/tachyon_streaming_client.cc
index aa65e582..92aa8f74 100644
--- a/chromeos/ash/components/boca/babelorca/tachyon_streaming_client.cc
+++ b/chromeos/ash/components/boca/babelorca/tachyon_streaming_client.cc
@@ -113,6 +113,7 @@
                                   StreamEndReason::kConnectionClosedSuccess);
     std::move(request_data_->response_cb)
         .Run(TachyonResponse(TachyonResponse::Status::kOk));
+    url_loader_.reset();
     return;
   }
   base::UmaHistogramEnumeration(kStreamEndReasonUma,
diff --git a/chromeos/ash/components/boca/boca_session_manager.cc b/chromeos/ash/components/boca/boca_session_manager.cc
index 9c5ee44..927a54e2 100644
--- a/chromeos/ash/components/boca/boca_session_manager.cc
+++ b/chromeos/ash/components/boca/boca_session_manager.cc
@@ -32,6 +32,7 @@
 #include "chromeos/ash/components/boca/session_api/update_student_activities_request.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
+#include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "google_apis/common/api_error_codes.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -87,6 +88,10 @@
   if (user_manager::UserManager::IsInitialized()) {
     user_manager::UserManager::Get()->AddSessionStateObserver(this);
   }
+  if (session_manager::SessionManager::Get()) {
+    session_manager_observation_.Observe(
+        session_manager::SessionManager::Get());
+  }
   LoadInitialNetworkState();
   LoadCurrentSession(/*from_polling=*/false);
   StartSessionPolling(/*in_session=*/false);
@@ -122,6 +127,8 @@
 
 void BocaSessionManager::Observer::OnLocalCaptionClosed() {}
 
+void BocaSessionManager::Observer::OnSessionCaptionClosed(bool is_error) {}
+
 void BocaSessionManager::Observer::OnSessionRosterUpdated(
     const ::boca::Roster& roster) {}
 
@@ -305,6 +312,12 @@
   }
 }
 
+void BocaSessionManager::OnSessionStateChanged() {
+  if (session_manager::SessionManager::Get()->IsScreenLocked()) {
+    CloseAllCaptions();
+  }
+}
+
 void BocaSessionManager::NotifyLocalCaptionEvents(
     ::boca::CaptionsConfig caption_config) {
   for (auto& observer : observers_) {
@@ -411,6 +424,7 @@
 
 void BocaSessionManager::ActiveUserChanged(user_manager::User* active_user) {
   if (!active_user || active_user->GetAccountId() != account_id_) {
+    CloseAllCaptions();
     return;
   }
   LoadCurrentSession(/*from_polling=*/false);
@@ -769,4 +783,14 @@
   }
 }
 
+void BocaSessionManager::CloseAllCaptions() {
+  is_local_caption_enabled_ = false;
+  for (auto& observer : observers_) {
+    if (is_producer_) {
+      observer.OnSessionCaptionClosed(/*is_error=*/false);
+    }
+    observer.OnLocalCaptionClosed();
+  }
+}
+
 }  // namespace ash::boca
diff --git a/chromeos/ash/components/boca/boca_session_manager.h b/chromeos/ash/components/boca/boca_session_manager.h
index 712a20e3..e5ebb4bc 100644
--- a/chromeos/ash/components/boca/boca_session_manager.h
+++ b/chromeos/ash/components/boca/boca_session_manager.h
@@ -12,6 +12,7 @@
 #include "base/functional/callback.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/types/expected.h"
@@ -22,6 +23,7 @@
 #include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager_observer.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "google_apis/common/api_error_codes.h"
@@ -39,12 +41,17 @@
 enum ApiErrorCode;
 }
 
+namespace session_manager {
+class SessionManager;
+}  // namespace session_manager
+
 namespace ash::boca {
 
 class BocaSessionManager
     : public chromeos::network_config::CrosNetworkConfigObserver,
       public signin::IdentityManager::Observer,
-      public user_manager::UserManager::UserSessionStateObserver {
+      public user_manager::UserManager::UserSessionStateObserver,
+      public session_manager::SessionManagerObserver {
  public:
   using SessionCaptionInitializer =
       base::RepeatingCallback<void(base::OnceCallback<void(bool)>)>;
@@ -139,6 +146,10 @@
     // Notifies when the status of SODA changes.
     virtual void OnSodaStatusUpdate(SodaStatus status);
 
+    // Notifies when session caption is disabled from a source other than the
+    // boca app.
+    virtual void OnSessionCaptionClosed(bool is_error);
+
     // Notifies when session roster updated. Will emit when only elements order
     // changed in the vector too. Deferred to events consumer to decide on
     // the actual action.
@@ -187,6 +198,9 @@
 
   virtual void OnAppWindowOpened();
 
+  // session_manager::SessionManagerObserver::Observer
+  void OnSessionStateChanged() override;
+
   // Local events.
   virtual void NotifyLocalCaptionEvents(::boca::CaptionsConfig caption_config);
 
@@ -252,6 +266,8 @@
       chromeos::network_config::mojom::NetworkStatePropertiesPtr network_state);
   void NotifySodaStatusListeners(SodaStatus status);
 
+  void CloseAllCaptions();
+
   const bool is_producer_;
   base::TimeDelta in_session_polling_interval_;
   base::TimeDelta indefinite_polling_interval_;
@@ -297,6 +313,9 @@
   bool is_local_caption_enabled_ = false;
   SessionCaptionInitializer session_caption_initializer_;
   net::BackoffEntry student_heartbeat_retry_backoff_;
+  base::ScopedObservation<session_manager::SessionManager,
+                          session_manager::SessionManagerObserver>
+      session_manager_observation_{this};
   base::WeakPtrFactory<BocaSessionManager> weak_factory_{this};
 };
 }  // namespace ash::boca
diff --git a/chromeos/ash/components/boca/boca_session_manager_unittest.cc b/chromeos/ash/components/boca/boca_session_manager_unittest.cc
index 9f0d053f..abbc146 100644
--- a/chromeos/ash/components/boca/boca_session_manager_unittest.cc
+++ b/chromeos/ash/components/boca/boca_session_manager_unittest.cc
@@ -32,6 +32,8 @@
 #include "chromeos/ash/components/settings/fake_cros_settings_provider.h"
 #include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/session_manager/session_manager_types.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/soda/constants.h"
@@ -39,6 +41,7 @@
 #include "components/user_manager/fake_user_manager_delegate.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/test_helper.h"
+#include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_manager_impl.h"
 #include "content/public/test/browser_task_environment.h"
 #include "google_apis/common/api_error_codes.h"
@@ -122,6 +125,7 @@
       (override));
   MOCK_METHOD(void, OnAppReloaded, (), (override));
   MOCK_METHOD(void, OnLocalCaptionClosed, (), (override));
+  MOCK_METHOD(void, OnSessionCaptionClosed, (bool), (override));
 };
 
 class MockBocaAppClient : public BocaAppClient {
@@ -334,6 +338,7 @@
   }
 
  protected:
+  session_manager::SessionManager device_session_manger_;
   base::Time session_start_time_ = base::Time::Now();
   bool is_producer_ = true;
 
@@ -1218,6 +1223,8 @@
   EXPECT_CALL(*session_client_impl(),
               GetSession(_, /*can_skip_duplicate_request=*/true))
       .Times(0);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(1);
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed(/*is_error=*/false)).Times(1);
   user_manager->SwitchActiveUser(account_id);
   testing::Mock::VerifyAndClearExpectations(session_client_impl());
 
@@ -1225,6 +1232,8 @@
   EXPECT_CALL(*session_client_impl(),
               GetSession(_, /*can_skip_duplicate_request=*/true))
       .Times(1);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(0);
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed).Times(0);
   user_manager->SwitchActiveUser(
       AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestGaiaId));
   testing::Mock::VerifyAndClearExpectations(session_client_impl());
@@ -1551,6 +1560,19 @@
   EXPECT_TRUE(test_future.Get());
 }
 
+TEST_F(BocaSessionManagerTest, NotifyCloseCaptionsOnDeviceSessionLocked) {
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed(/*is_error=*/false)).Times(1);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(1);
+  device_session_manger_.SetSessionState(session_manager::SessionState::LOCKED);
+}
+
+TEST_F(BocaSessionManagerTest,
+       DoesNotNotifyCloseCaptionsOnDeviceSessionNotLocked) {
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed).Times(0);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(0);
+  device_session_manger_.SetSessionState(session_manager::SessionState::ACTIVE);
+}
+
 class BocaSessionManagerSodaTest : public BocaSessionManagerTestBase {
  protected:
   void SetUp() override {
@@ -2293,5 +2315,27 @@
                                     base::Seconds(1));
 }
 
+TEST_F(BocaSessionManagerConsumerTest,
+       NotifyCloseLocalCaptionsOnlyOnDeviceSessionLocked) {
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed).Times(0);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(1);
+  device_session_manger_.SetSessionState(session_manager::SessionState::LOCKED);
+}
+
+TEST_F(BocaSessionManagerConsumerTest,
+       NotifyCloseLocalCaptionsOnlyOnActiveUserChanged) {
+  const auto account_id =
+      AccountId::FromUserEmailGaiaId(kTestUserEmail2, kTestGaiaId2);
+  const std::string username_hash =
+      user_manager::TestHelper::GetFakeUsernameHash(account_id);
+  auto* user_manager = user_manager::UserManager::Get();
+  user_manager->UserLoggedIn(account_id, username_hash);
+  testing::Mock::VerifyAndClearExpectations(session_client_impl());
+  EXPECT_CALL(*observer(), OnSessionCaptionClosed).Times(0);
+  EXPECT_CALL(*observer(), OnLocalCaptionClosed).Times(1);
+  user_manager::UserManager::Get()->SwitchActiveUser(
+      AccountId::FromUserEmailGaiaId(kTestUserEmail2, kTestGaiaId2));
+}
+
 }  // namespace
 }  // namespace ash::boca
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index 09021bf..442c309 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -108,6 +108,13 @@
   # b/409349162
   "inputs.PhysicalKeyboardKoreanTyping@jacuzzi",
 
+  # b/413662732
+  "arc.Boot.vm@volteer",
+  "arc.Boot.vm_with_per_vcpu_core_scheduling@volteer",
+  "platform.ResourcedCgroups@volteer",
+  "sched.ChromeQoS@volteer",
+  "sched.SetQoSState@volteer",
+
   # READ COMMENT AT TOP BEFORE ADDING NEW TESTS HERE.
 ]
 
diff --git a/clank b/clank
index 86860c4..72d9d8f 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 86860c4de44765ed2d195926b9d3dd6ed1d20efd
+Subproject commit 72d9d8f0bcf477b826e8abd3986b2b24eff275ff
diff --git a/components/autofill/content/browser/content_identity_credential_delegate.cc b/components/autofill/content/browser/content_identity_credential_delegate.cc
index cbca39a..b2e4cb87 100644
--- a/components/autofill/content/browser/content_identity_credential_delegate.cc
+++ b/components/autofill/content/browser/content_identity_credential_delegate.cc
@@ -22,6 +22,10 @@
 std::vector<Suggestion>
 ContentIdentityCredentialDelegate::GetVerifiedAutofillSuggestions(
     const FieldType& field_type) const {
+  if (!(field_type == EMAIL_ADDRESS || field_type == NAME_FIRST ||
+        field_type == NAME_FULL)) {
+    return {};
+  }
   // TODO(crbug.com/380367784): reproduce and add a test to make sure this
   // works properly when FedCM is called from inner frames.
   content::FederatedAuthAutofillSource* source =
@@ -41,21 +45,26 @@
 
   std::vector<Suggestion> suggestions;
   for (IdentityRequestAccountPtr account : *accounts) {
-    Suggestion suggestion(base::UTF8ToUTF16(account->email),
-                          SuggestionType::kIdentityCredential);
-
+    Suggestion suggestion(SuggestionType::kIdentityCredential);
     auto payload = Suggestion::IdentityCredentialPayload(
         account->identity_provider->idp_metadata.config_url, account->id);
+    suggestion.payload = payload;
 
-    if (field_type == EMAIL_ADDRESS) {
+    if (field_type == EMAIL_ADDRESS || field_type == NAME_FIRST ||
+        field_type == NAME_FULL) {
+      payload.fields[NAME_FULL] = base::UTF8ToUTF16(account->name);
+      payload.fields[NAME_FIRST] = base::UTF8ToUTF16(account->given_name);
+      payload.fields[EMAIL_ADDRESS] = base::UTF8ToUTF16(account->email);
+
+      suggestion.main_text = Suggestion::Text(payload.fields[field_type]);
+      // TODO(crbug.com/380367784): revisit the iconography of the suggestion
+      // if the field goes beyond email.
       suggestion.icon = Suggestion::Icon::kEmail;
       suggestion.minor_texts.emplace_back(l10n_util::GetStringFUTF16(
           IDS_AUTOFILL_IDENTITY_CREDENTIAL_MINOR_TEXT,
           base::UTF8ToUTF16(account->identity_provider->idp_for_display)));
       suggestion.labels.push_back({Suggestion::Text(l10n_util::GetStringUTF16(
           IDS_AUTOFILL_IDENTITY_CREDENTIAL_EMAIL_LABEL))});
-      // TODO(crbug.com/380367784): add more field types.
-      payload.fields[HtmlFieldType::kEmail] = base::UTF8ToUTF16(account->email);
     } else if (field_type == PASSWORD) {
       suggestion.custom_icon = account->decoded_picture;
       // TODO(crbug.com/410421491): support more context.
@@ -64,7 +73,6 @@
           base::UTF8ToUTF16(account->identity_provider->idp_for_display)))});
     }
 
-    suggestion.payload = payload;
     suggestions.push_back(std::move(suggestion));
   }
 
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 2ac0660..c22fc799 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/buildflag_header.gni")
 import("//build/config/chrome_build.gni")
 import("//build/config/features.gni")
-import("//chrome/version.gni")
 import("//components/optimization_guide/features.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/protobuf/proto_library.gni")
@@ -507,6 +506,8 @@
     "payments/payments_requests/get_card_upload_details_request.h",
     "payments/payments_requests/get_details_for_create_bnpl_payment_instrument_request.cc",
     "payments/payments_requests/get_details_for_create_bnpl_payment_instrument_request.h",
+    "payments/payments_requests/get_details_for_create_card_request.cc",
+    "payments/payments_requests/get_details_for_create_card_request.h",
     "payments/payments_requests/get_details_for_enrollment_request.cc",
     "payments/payments_requests/get_details_for_enrollment_request.h",
     "payments/payments_requests/get_iban_upload_details_request.cc",
@@ -796,8 +797,6 @@
     ]
   }
 
-  defines = [ "CHROME_VERSION_MAJOR=" + chrome_version_major ]
-
   configs += [
     "//build/config:precompiled_headers",
     "//build/config/compiler:wexit_time_destructors",
@@ -842,6 +841,7 @@
     ":regex_patterns_inl_h",
     "//base",
     "//base:i18n",
+    "//base/version_info",
     "//build:branding_buildflags",
     "//components/affiliations/core/browser:affiliations",
     "//components/autofill/core/common:autofill_regex",
@@ -1054,6 +1054,7 @@
     "payments/payments_network_interface_test_base.h",
     "payments/payments_requests/create_bnpl_payment_instrument_request_test_api.h",
     "payments/payments_requests/get_details_for_create_bnpl_payment_instrument_request_test_api.h",
+    "payments/payments_requests/get_details_for_create_card_request_test_api.h",
     "payments/test/autofill_payments_test_utils.cc",
     "payments/test/autofill_payments_test_utils.h",
     "payments/test/mock_bnpl_manager.cc",
@@ -1388,6 +1389,7 @@
     "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_vcn_request_unittest.cc",
     "payments/payments_requests/get_card_upload_details_request_unittest.cc",
     "payments/payments_requests/get_details_for_create_bnpl_payment_instrument_request_unittest.cc",
+    "payments/payments_requests/get_details_for_create_card_request_unittest.cc",
     "payments/payments_requests/get_details_for_enrollment_request_unittest.cc",
     "payments/payments_requests/get_iban_upload_details_request_unittest.cc",
     "payments/payments_requests/unmask_card_request_unittest.cc",
@@ -1520,8 +1522,6 @@
         [ "ml_model/autofill_ai/autofill_ai_model_executor_impl_unittest.cc" ]
   }
 
-  defines = [ "CHROME_VERSION_MAJOR=" + chrome_version_major ]
-
   deps = [
     ":autofill_address_rewriter_resources",
     ":browser",
@@ -1532,6 +1532,7 @@
     ":unit_tests_bundle_data",
     "//base",
     "//base/test:test_support",
+    "//base/version_info",
     "//components/autofill/core/common:autofill_regex",
     "//components/autofill/core/common:credit_card_number_validation",
     "//components/device_reauth:device_reauth",
diff --git a/components/autofill/core/browser/data_manager/addresses/address_data_cleaner.cc b/components/autofill/core/browser/data_manager/addresses/address_data_cleaner.cc
index e5383f06..f7ca901 100644
--- a/components/autofill/core/browser/data_manager/addresses/address_data_cleaner.cc
+++ b/components/autofill/core/browser/data_manager/addresses/address_data_cleaner.cc
@@ -8,6 +8,7 @@
 
 #include "base/containers/to_vector.h"
 #include "base/notreached.h"
+#include "base/version_info/version_info.h"
 #include "components/autofill/core/browser/data_manager/addresses/address_data_manager.h"
 #include "components/autofill/core/browser/data_manager/personal_data_manager.h"
 #include "components/autofill/core/browser/data_model/addresses/autofill_profile.h"
@@ -271,11 +272,12 @@
   }
   are_cleanups_pending_ = false;
 
+  int chrome_version_major = version_info::GetMajorVersionNumberAsInt();
   // Ensure that deduplication is only run one per milestone.
   if (pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) <
-      CHROME_VERSION_MAJOR) {
+      chrome_version_major) {
     pref_service_->SetInteger(prefs::kAutofillLastVersionDeduped,
-                              CHROME_VERSION_MAJOR);
+                              chrome_version_major);
     // Since the milesone changed the extra deduplication can be run again.
     pref_service_->ClearPref(
         prefs::kAutofillRanExtraDeduplication);
diff --git a/components/autofill/core/browser/data_manager/addresses/address_data_cleaner_unittest.cc b/components/autofill/core/browser/data_manager/addresses/address_data_cleaner_unittest.cc
index 5d58f35d..2050a63 100644
--- a/components/autofill/core/browser/data_manager/addresses/address_data_cleaner_unittest.cc
+++ b/components/autofill/core/browser/data_manager/addresses/address_data_cleaner_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "base/version_info/version_info.h"
 #include "components/autofill/core/browser/data_manager/addresses/address_data_cleaner_test_api.h"
 #include "components/autofill/core/browser/data_manager/addresses/test_address_data_manager.h"
 #include "components/autofill/core/browser/data_model/addresses/autofill_profile_comparator.h"
@@ -196,7 +197,8 @@
   test_adm_.AddProfile(test::StandardProfile());
   test_adm_.AddProfile(test::UpdateableStandardProfile());
   // Pretend that deduplication was already run this milestone.
-  prefs_->SetInteger(prefs::kAutofillLastVersionDeduped, CHROME_VERSION_MAJOR);
+  prefs_->SetInteger(prefs::kAutofillLastVersionDeduped,
+                     version_info::GetMajorVersionNumberAsInt());
   data_cleaner_.MaybeCleanupAddressData();
   EXPECT_EQ(2U, test_adm_.GetProfiles().size());
 }
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
index 84a28bc5..149f828 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
@@ -17,6 +17,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/types/zip.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/addresses/autofill_i18n_api.h"
 #include "components/autofill/core/browser/data_model/addresses/autofill_structured_address_format_provider.h"
@@ -133,8 +134,10 @@
 
   CHECK_EQ(other.subcomponents_.size(), subcomponents_.size())
       << GetStorageTypeName();
-  for (size_t i = 0; i < other.subcomponents_.size(); i++)
-    subcomponents_[i]->CopyFrom(*other.subcomponents_[i]);
+  for (auto [subcomponent, other_subcomponent] :
+       base::zip(subcomponents_, other.subcomponents_)) {
+    subcomponent->CopyFrom(*other_subcomponent);
+  }
 
   PostAssignSanitization();
 }
@@ -154,8 +157,9 @@
   if (subcomponents_.size() != other.subcomponents_.size()) {
     return false;
   }
-  for (size_t i = 0; i < other.subcomponents_.size(); i++) {
-    if (!(subcomponents_[i]->SameAs(*other.subcomponents_[i]))) {
+  for (auto [subcomponent, other_subcomponent] :
+       base::zip(subcomponents_, other.subcomponents_)) {
+    if (!subcomponent->SameAs(*other_subcomponent)) {
       return false;
     }
   }
@@ -930,9 +934,9 @@
   }
   CHECK_EQ(newer_component.subcomponents_.size(), subcomponents_.size())
       << GetStorageTypeName();
-  for (size_t i = 0; i < newer_component.subcomponents_.size(); i++) {
-    subcomponents_[i]->MergeVerificationStatuses(
-        *newer_component.subcomponents_.at(i));
+  for (auto [subcomponent, newer_subcomponent] :
+       base::zip(subcomponents_, newer_component.subcomponents_)) {
+    subcomponent->MergeVerificationStatuses(*newer_subcomponent);
   }
 }
 
@@ -1045,20 +1049,16 @@
 
   // Checks if all child nodes are mergeable.
   if (merge_mode_ & kMergeChildrenAndReformatIfNeeded) {
-    bool is_mergeable = true;
-
     if (subcomponents_.size() != newer_component.subcomponents_.size()) {
       return false;
     }
-    for (size_t i = 0; i < newer_component.subcomponents_.size(); i++) {
-      if (!subcomponents_[i]->IsMergeableWithComponent(
-              *newer_component.subcomponents_[i])) {
-        is_mergeable = false;
-        break;
+    for (auto [subcomponent, newer_subcomponent] :
+         base::zip(subcomponents_, newer_component.subcomponents_)) {
+      if (!subcomponent->IsMergeableWithComponent(*newer_subcomponent)) {
+        return false;
       }
     }
-    if (is_mergeable)
-      return true;
+    return true;
   }
   return false;
 }
@@ -1252,13 +1252,14 @@
   // the child tokens. Reformat this nodes from its children after the merge.
   if (merge_mode_ & kMergeChildrenAndReformatIfNeeded) {
     CHECK_EQ(newer_component.subcomponents_.size(), subcomponents_.size());
-    for (size_t i = 0; i < newer_component.subcomponents_.size(); i++) {
-      if (!subcomponents_[i]->MergeWithComponent(
-              *newer_component.subcomponents_[i],
-              newer_was_more_recently_used)) {
+    for (auto [subcomponent, newer_subcomponent] :
+         base::zip(subcomponents_, newer_component.subcomponents_)) {
+      if (!subcomponent->MergeWithComponent(*newer_subcomponent,
+                                            newer_was_more_recently_used)) {
         return false;
       }
     }
+
     // If the two values are already token equivalent, use the value of the
     // component with the better verification status, or if both are the same,
     // use the newer one.
@@ -1343,8 +1344,9 @@
   } else if (AllDescendantsAreEmpty()) {
     // Otherwise, replace this subtree with the other one if this subtree is
     // empty.
-    for (size_t i = 0; i < subcomponents_.size(); ++i) {
-      subcomponents_[i]->CopyFrom(*other_subcomponents[i]);
+    for (auto [subcomponent, other_subcomponent] :
+         base::zip(subcomponents_, other_subcomponents)) {
+      subcomponent->CopyFrom(*other_subcomponent);
     }
     return true;
   }
diff --git a/components/autofill/core/browser/filling/filling_product.cc b/components/autofill/core/browser/filling/filling_product.cc
index 4b70d17..73bebc1e 100644
--- a/components/autofill/core/browser/filling/filling_product.cc
+++ b/components/autofill/core/browser/filling/filling_product.cc
@@ -36,6 +36,8 @@
       return "AutofillAi";
     case FillingProduct::kLoyaltyCard:
       return "LoyaltyCard";
+    case FillingProduct::kIdentityCredential:
+      return "IdentityCredential";
   };
   NOTREACHED();
 }
@@ -50,7 +52,6 @@
     case SuggestionType::kDevtoolsTestAddressByCountry:
     case SuggestionType::kDevtoolsTestAddressEntry:
     case SuggestionType::kManageAddress:
-    case SuggestionType::kIdentityCredential:
       return FillingProduct::kAddress;
     case SuggestionType::kBnplEntry:
     case SuggestionType::kCreditCardEntry:
@@ -104,6 +105,8 @@
     case SuggestionType::kLoyaltyCardEntry:
     case SuggestionType::kManageLoyaltyCard:
       return FillingProduct::kLoyaltyCard;
+    case SuggestionType::kIdentityCredential:
+      return FillingProduct::kIdentityCredential;
   }
   NOTREACHED();
 }
diff --git a/components/autofill/core/browser/filling/filling_product.h b/components/autofill/core/browser/filling/filling_product.h
index 37e2eef7..3a9db55 100644
--- a/components/autofill/core/browser/filling/filling_product.h
+++ b/components/autofill/core/browser/filling/filling_product.h
@@ -25,7 +25,8 @@
   kPlusAddresses,
   kAutofillAi,
   kLoyaltyCard,
-  kMaxValue = kLoyaltyCard
+  kIdentityCredential,
+  kMaxValue = kIdentityCredential
 };
 
 FillingProduct GetFillingProductFromSuggestionType(SuggestionType type);
diff --git a/components/autofill/core/browser/filling/form_filler.cc b/components/autofill/core/browser/filling/form_filler.cc
index 01a9853..b272aaab 100644
--- a/components/autofill/core/browser/filling/form_filler.cc
+++ b/components/autofill/core/browser/filling/form_filler.cc
@@ -71,6 +71,7 @@
     case FillingProduct::kLoyaltyCard:
     case FillingProduct::kMerchantPromoCode:
     case FillingProduct::kPlusAddresses:
+    case FillingProduct::kIdentityCredential:
       return false;
     case FillingProduct::kPassword:
     case FillingProduct::kNone:
@@ -84,7 +85,10 @@
       base::Overloaded{
           [](const AutofillProfile*) { return FillingProduct::kAddress; },
           [](const CreditCard*) { return FillingProduct::kCreditCard; },
-          [](const EntityInstance*) { return FillingProduct::kAutofillAi; }},
+          [](const EntityInstance*) { return FillingProduct::kAutofillAi; },
+          [](const VerifiedProfile*) {
+            return FillingProduct::kIdentityCredential;
+          }},
       filling_payload);
 }
 
@@ -137,6 +141,8 @@
       return FieldTypeSet{LOYALTY_MEMBERSHIP_ID};
     case FillingProduct::kPlusAddresses:
       return FieldTypeSet{EMAIL_ADDRESS};
+    case FillingProduct::kIdentityCredential:
+      return FieldTypeSet{EMAIL_ADDRESS, NAME_FIRST, NAME_FULL};
     case FillingProduct::kAutocomplete:
     case FillingProduct::kCompose:
       return std::nullopt;
@@ -228,6 +234,7 @@
     case FillingProduct::kPassword:
     case FillingProduct::kCompose:
     case FillingProduct::kLoyaltyCard:
+    case FillingProduct::kIdentityCredential:
       return false;
   }
   NOTREACHED();
@@ -397,6 +404,9 @@
           // Autofill with AI doesn't support refills.
           [](const EntityInstance*)
               -> std::variant<CreditCard, AutofillProfile> { NOTREACHED(); },
+          // Verified Profiles doesn't support refills.
+          [](const VerifiedProfile*)
+              -> std::variant<CreditCard, AutofillProfile> { NOTREACHED(); },
           [](const auto* x) {
             return std::variant<CreditCard, AutofillProfile>(*x);
           }},
@@ -988,6 +998,12 @@
                         manager_->client().GetAppLocale(),
                         manager_->client().GetAddressNormalizer()),
                     std::nullopt};
+          },
+          [&](const VerifiedProfile* profile)
+              -> std::pair<std::u16string, std::optional<FieldType>> {
+            auto it = profile->find(autofill_field.Type().GetStorableType());
+            std::u16string value = it == profile->end() ? u"" : it->second;
+            return {value, autofill_field.Type().GetStorableType()};
           }},
       filling_payload);
   return {value_to_fill, filling_type, /*value_is_an_override=*/false};
diff --git a/components/autofill/core/browser/filling/form_filler.h b/components/autofill/core/browser/filling/form_filler.h
index 30ef1ed..ebb6b56 100644
--- a/components/autofill/core/browser/filling/form_filler.h
+++ b/components/autofill/core/browser/filling/form_filler.h
@@ -39,8 +39,12 @@
   kMaxValue = kExpirationDateFormatted
 };
 
-using FillingPayload = std::
-    variant<const AutofillProfile*, const CreditCard*, const EntityInstance*>;
+using VerifiedProfile = std::map<FieldType, std::u16string>;
+
+using FillingPayload = std::variant<const AutofillProfile*,
+                                    const CreditCard*,
+                                    const EntityInstance*,
+                                    const VerifiedProfile*>;
 
 // Helper class responsible for [re]filling forms and fields.
 //
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 898712f..9989be2 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,6 +9,7 @@
 
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
+#include "base/types/zip.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
 #include "components/autofill/core/browser/data_model/payments/credit_card.h"
@@ -54,12 +55,12 @@
   std::vector<std::u16string> trimmed_values(field_options.size());
   static constexpr char16_t kNumberPrefix[] = u"number:";
   static constexpr char16_t kStringPrefix[] = u"string:";
-  for (size_t i = 0; i < field_options.size(); ++i) {
-    base::TrimWhitespace(field_options[i].value, base::TRIM_ALL,
-                         &trimmed_values[i]);
-    base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kNumberPrefix,
+  for (auto [field_option, trimmed_value] :
+       base::zip(field_options, trimmed_values)) {
+    base::TrimWhitespace(field_option.value, base::TRIM_ALL, &trimmed_value);
+    base::ReplaceFirstSubstringAfterOffset(&trimmed_value, 0, kNumberPrefix,
                                            u"");
-    base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kStringPrefix,
+    base::ReplaceFirstSubstringAfterOffset(&trimmed_value, 0, kStringPrefix,
                                            u"");
   }
 
@@ -92,14 +93,15 @@
   }
 
   // Attempt to match the user's `month` with the field's value attributes.
-  for (size_t i = 0; i < trimmed_values.size(); ++i) {
+  for (auto [field_option, trimmed_value] :
+       base::zip(field_options, trimmed_values)) {
     int converted_value = 0;
     // We use the trimmed value to match with `month`, but the original select
     // value to fill the field (otherwise filling wouldn't work).
-    if (data_util::ParseExpirationMonth(trimmed_values[i], app_locale,
+    if (data_util::ParseExpirationMonth(trimmed_value, app_locale,
                                         &converted_value) &&
         month == converted_value) {
-      return field_options[i].value;
+      return field_option.value;
     }
   }
 
diff --git a/components/autofill/core/browser/form_structure_test_api.cc b/components/autofill/core/browser/form_structure_test_api.cc
index 94d4e2e..f838b27 100644
--- a/components/autofill/core/browser/form_structure_test_api.cc
+++ b/components/autofill/core/browser/form_structure_test_api.cc
@@ -4,6 +4,7 @@
 
 #include "components/autofill/core/browser/form_structure_test_api.h"
 
+#include "base/types/zip.h"
 #include "components/autofill/core/browser/form_parsing/field_candidates.h"
 #include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -28,13 +29,12 @@
               Each(Contains(Pair(GetActiveHeuristicSource(), _))))
       << "There must be a default heuristic prediction for every field.";
 
-  for (size_t i = 0; i < form_structure_->field_count(); ++i) {
-    AutofillField* form_field = form_structure_->field(i);
-    ASSERT_TRUE(form_field);
-
-    for (const auto& [source, type] : heuristic_types[i])
-      form_field->set_heuristic_type(source, type);
-    form_field->set_server_predictions({server_types[i]});
+  for (auto [field, heuristic_type, server_type] :
+       base::zip(form_structure_->fields(), heuristic_types, server_types)) {
+    for (const auto& [source, type] : heuristic_type) {
+      field->set_heuristic_type(source, type);
+    }
+    field->set_server_predictions({server_type});
   }
 }
 
@@ -62,8 +62,7 @@
 
 AutofillUploadContents::Field::VoteType
 FormStructureTestApi::get_username_vote_type() {
-  for (size_t i = 0; i < form_structure_->field_count(); ++i) {
-    AutofillField* field = form_structure_->field(i);
+  for (const auto& field : form_structure_->fields()) {
     AutofillUploadContents::Field::VoteType vote_type = field->vote_type();
     if (vote_type == AutofillUploadContents::Field::USERNAME_OVERWRITTEN ||
         vote_type == AutofillUploadContents::Field::USERNAME_EDITED ||
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager.cc b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
index 0ee2e96..3b13cd1 100644
--- a/components/autofill/core/browser/foundations/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
@@ -58,6 +58,7 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
+#include "base/types/zip.h"
 #include "base/uuid.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_browser_util.h"
@@ -182,7 +183,9 @@
       base::Overloaded{
           [](const AutofillProfile*) { return FillDataType::kAutofillProfile; },
           [](const CreditCard*) { return FillDataType::kCreditCard; },
-          [](const EntityInstance*) { return FillDataType::kAutofillAi; }},
+          [](const EntityInstance*) { return FillDataType::kAutofillAi; },
+          [](const VerifiedProfile*) { return FillDataType::kAutofillProfile; },
+      },
       filling_payload);
 }
 
@@ -239,6 +242,7 @@
     case FillingProduct::kCreditCard:
     case FillingProduct::kAddress:
     case FillingProduct::kNone:
+    case FillingProduct::kIdentityCredential:
       return false;
   }
 }
@@ -1548,6 +1552,12 @@
                        action_persistence, form, filling_payload,
                        CHECK_DEREF(form_structure), CHECK_DEREF(autofill_field),
                        trigger_source);
+                 },
+                 [&](const VerifiedProfile*) {
+                   form_filler_->FillOrPreviewForm(
+                       action_persistence, form, filling_payload,
+                       CHECK_DEREF(form_structure), CHECK_DEREF(autofill_field),
+                       trigger_source);
                  }},
              filling_payload);
 }
@@ -2394,6 +2404,10 @@
                                trigger_autofill_field,
                                driver().GetPageUkmSourceId());
                          }
+                       },
+                       [&](const VerifiedProfile*) {
+                         // TODO(crbug.com/380367784): consider moving the
+                         // notification to the delegate here.
                        }},
       filling_payload);
 }
@@ -2422,16 +2436,16 @@
       trigger_fill_field_log_event);
   FillEventId fill_event_id = trigger_fill_field_log_event.fill_event_id;
 
-  for (size_t i = 0; i < form_structure.field_count(); ++i) {
-    AutofillField& field = CHECK_DEREF(form_structure.field(i));
-    const FieldGlobalId field_id = field.global_id();
-    const bool has_value_before = !form.fields()[i].value().empty();
+  for (auto [form_field, field] :
+       base::zip(form.fields(), form_structure.fields())) {
+    const FieldGlobalId field_id = field->global_id();
+    const bool has_value_before = !form_field.value().empty();
     const FieldFillingSkipReason skip_reason =
         skip_reasons.at(field_id).empty() ? FieldFillingSkipReason::kNotSkipped
                                           : *skip_reasons.at(field_id).begin();
-    if (!IsCheckable(field.check_status())) {
+    if (!IsCheckable(field->check_status())) {
       if (skip_reason == FieldFillingSkipReason::kNotSkipped) {
-        field.AppendLogEventIfNotRepeated(FillFieldLogEvent{
+        field->AppendLogEventIfNotRepeated(FillFieldLogEvent{
             .fill_event_id = fill_event_id,
             .had_value_before_filling = ToOptionalBoolean(has_value_before),
             .autofill_skipped_status = skip_reason,
@@ -2444,7 +2458,7 @@
             .was_refill = ToOptionalBoolean(is_refill),
         });
       } else {
-        field.AppendLogEventIfNotRepeated(FillFieldLogEvent{
+        field->AppendLogEventIfNotRepeated(FillFieldLogEvent{
             .fill_event_id = fill_event_id,
             .had_value_before_filling = ToOptionalBoolean(has_value_before),
             .autofill_skipped_status = skip_reason,
@@ -3019,11 +3033,10 @@
     if (std::optional<AutocompleteParsingResult> autocomplete =
             ParseAutocompleteAttribute(
                 autofill_field->autocomplete_attribute());
-        autocomplete && autocomplete->field_type == HtmlFieldType::kEmail &&
-        autocomplete->webidentity) {
+        autocomplete && autocomplete->webidentity) {
       std::vector<Suggestion> verified_suggestions =
           identity_credential_delegate->GetVerifiedAutofillSuggestions(
-              FieldType::EMAIL_ADDRESS);
+              autofill_field->Type().GetStorableType());
       // Insert verified suggestions above unverified ones.
       // TODO(crbug.com/380367784): figure out what to do when both verified
       // and unverified suggestions point to the same email address.
diff --git a/components/autofill/core/browser/metrics/suggestions_list_metrics.cc b/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
index 6fcadaf..c7cc0d60 100644
--- a/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
+++ b/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
@@ -64,6 +64,7 @@
     case FillingProduct::kPlusAddresses:
     case FillingProduct::kAutofillAi:
     case FillingProduct::kLoyaltyCard:
+    case FillingProduct::kIdentityCredential:
       NOTREACHED();
   }
 }
@@ -98,6 +99,7 @@
     case FillingProduct::kPlusAddresses:
     case FillingProduct::kAutofillAi:
     case FillingProduct::kMerchantPromoCode:
+    case FillingProduct::kIdentityCredential:
       // It is NOTREACHED because all other types should be handled separately.
       NOTREACHED();
   }
diff --git a/components/autofill/core/browser/payments/payments_request_details.h b/components/autofill/core/browser/payments/payments_request_details.h
index b73f1b7f..0efd0d2 100644
--- a/components/autofill/core/browser/payments/payments_request_details.h
+++ b/components/autofill/core/browser/payments/payments_request_details.h
@@ -345,6 +345,9 @@
   UPSTREAM_SETTINGS_PAGE,
   // Single card is being uploaded after being scanned by OCR.
   UPSTREAM_CARD_OCR,
+  // Single card is being uploaded from the Save and Fill dialog during a
+  // non-post-checkout flow.
+  UPSTREAM_SAVE_AND_FILL,
 };
 
 // A collection of information received in the response for an
diff --git a/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.cc b/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.cc
index 4287774..88745bd6 100644
--- a/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.cc
+++ b/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/json/json_writer.h"
-#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -137,30 +136,4 @@
                            supported_card_bin_ranges_);
 }
 
-std::vector<std::pair<int, int>>
-GetCardUploadDetailsRequest::ParseSupportedCardBinRangesString(
-    const std::string& supported_card_bin_ranges_string) {
-  std::vector<std::pair<int, int>> supported_card_bin_ranges;
-  std::vector<std::string> range_strings =
-      base::SplitString(supported_card_bin_ranges_string, ",",
-                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
-  for (std::string& range_string : range_strings) {
-    std::vector<std::string> range = base::SplitString(
-        range_string, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-    DCHECK(range.size() <= 2);
-    int start;
-    base::StringToInt(range[0], &start);
-    if (range.size() == 1) {
-      supported_card_bin_ranges.emplace_back(start, start);
-    } else {
-      int end;
-      base::StringToInt(range[1], &end);
-      DCHECK_LE(start, end);
-      supported_card_bin_ranges.emplace_back(start, end);
-    }
-  }
-  return supported_card_bin_ranges;
-}
-
 }  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.h b/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.h
index 6a70cdb..d1a5a2c7 100644
--- a/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.h
+++ b/components/autofill/core/browser/payments/payments_requests/get_card_upload_details_request.h
@@ -46,13 +46,6 @@
       PaymentsAutofillClient::PaymentsRpcResult result) override;
 
  private:
-  // Helper for ParseResponse(). Input format should be :"1234,30000-55555,765",
-  // where ranges are separated by commas and items separated with a dash means
-  // the start and ends of the range. Items without a dash have the same start
-  // and end (ex. 1234-1234)
-  std::vector<std::pair<int, int>> ParseSupportedCardBinRangesString(
-      const std::string& supported_card_bin_ranges_string);
-
   const std::vector<AutofillProfile> addresses_;
   const int detected_values_;
   const std::vector<ClientBehaviorConstants> client_behavior_signals_;
diff --git a/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.cc b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.cc
new file mode 100644
index 0000000..18b9bd039
--- /dev/null
+++ b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.cc
@@ -0,0 +1,112 @@
+// Copyright 2025 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/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h"
+
+#include "base/json/json_writer.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace autofill::payments {
+
+namespace {
+const char kGetDetailsForCreateCardRequestPath[] =
+    "payments/apis/chromepaymentsservice/getdetailsforcreatepaymentinstrument";
+}  // namespace
+
+GetDetailsForCreateCardRequest::GetDetailsForCreateCardRequest(
+    const std::string& unique_country_code,
+    const std::vector<ClientBehaviorConstants>& client_behavior_signals,
+    const std::string& app_locale,
+    base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult,
+                            const std::u16string&,
+                            std::unique_ptr<base::Value::Dict>,
+                            std::vector<std::pair<int, int>>)> callback,
+    const int billable_service_number,
+    const int64_t billing_customer_number,
+    UploadCardSource upload_card_source)
+    : unique_country_code_(unique_country_code),
+      client_behavior_signals_(client_behavior_signals),
+      app_locale_(app_locale),
+      callback_(std::move(callback)),
+      billable_service_number_(billable_service_number),
+      upload_card_source_(upload_card_source),
+      billing_customer_number_(billing_customer_number) {}
+
+GetDetailsForCreateCardRequest::~GetDetailsForCreateCardRequest() = default;
+
+std::string GetDetailsForCreateCardRequest::GetRequestUrlPath() {
+  return kGetDetailsForCreateCardRequestPath;
+}
+
+std::string GetDetailsForCreateCardRequest::GetRequestContentType() {
+  return "application/json";
+}
+
+std::string GetDetailsForCreateCardRequest::GetRequestContent() {
+  base::Value::Dict request_dict;
+  base::Value::Dict context;
+  context.Set("language_code", app_locale_);
+  context.Set("billable_service", billable_service_number_);
+  if (billing_customer_number_ != 0) {
+    context.Set("customer_context",
+                BuildCustomerContextDictionary(billing_customer_number_));
+  }
+  request_dict.Set("context", std::move(context));
+  request_dict.Set("chrome_user_context",
+                   BuildChromeUserContext(client_behavior_signals_));
+
+  base::Value::Dict card_info;
+  card_info.Set("unique_country_code", unique_country_code_);
+  switch (upload_card_source_) {
+    case UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE:
+      card_info.Set("upload_card_source", "UNKNOWN_UPLOAD_CARD_SOURCE");
+      break;
+    case UploadCardSource::UPSTREAM_SAVE_AND_FILL:
+      card_info.Set("upload_card_source", "UPSTREAM_SAVE_AND_FILL");
+      break;
+    default:
+      // This class has not been integrated with other Upstream flows yet.
+      NOTREACHED();
+  }
+  request_dict.Set("card_info", std::move(card_info));
+
+  std::string request_content;
+  base::JSONWriter::Write(request_dict, &request_content);
+  DVLOG(3) << "getdetailsforcreatecard request body: " << request_content;
+  return request_content;
+}
+
+void GetDetailsForCreateCardRequest::ParseResponse(
+    const base::Value::Dict& response) {
+  if (const auto* context_token = response.FindString("context_token")) {
+    context_token_ = base::UTF8ToUTF16(*context_token);
+  }
+
+  if (const base::Value::Dict* dictionary_value =
+          response.FindDict("legal_message")) {
+    legal_message_ =
+        std::make_unique<base::Value::Dict>(dictionary_value->Clone());
+  }
+
+  if (const base::Value::Dict* card_details =
+          response.FindDict("card_details")) {
+    if (const auto* supported_card_bin_ranges_string =
+            card_details->FindString("supported_card_bin_ranges_string")) {
+      supported_card_bin_ranges_ =
+          ParseSupportedCardBinRangesString(*supported_card_bin_ranges_string);
+    }
+  }
+}
+
+bool GetDetailsForCreateCardRequest::IsResponseComplete() {
+  return !context_token_.empty() && legal_message_;
+}
+
+void GetDetailsForCreateCardRequest::RespondToDelegate(
+    PaymentsAutofillClient::PaymentsRpcResult result) {
+  std::move(callback_).Run(result, context_token_, std::move(legal_message_),
+                           supported_card_bin_ranges_);
+}
+
+}  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h
new file mode 100644
index 0000000..3b2dd4f
--- /dev/null
+++ b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h
@@ -0,0 +1,63 @@
+// Copyright 2025 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_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_H_
+
+#include "components/autofill/core/browser/payments/payments_request_details.h"
+#include "components/autofill/core/browser/payments/payments_requests/payments_request.h"
+
+namespace autofill::payments {
+
+class GetDetailsForCreateCardRequest : public PaymentsRequest {
+ public:
+  GetDetailsForCreateCardRequest(
+      const std::string& unique_country_code,
+      const std::vector<ClientBehaviorConstants>& client_behavior_signals,
+      const std::string& app_locale,
+      base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult,
+                              const std::u16string&,
+                              std::unique_ptr<base::Value::Dict>,
+                              std::vector<std::pair<int, int>>)> callback,
+      const int billable_service_number,
+      const int64_t billing_customer_number,
+      UploadCardSource upload_card_source);
+  GetDetailsForCreateCardRequest(const GetDetailsForCreateCardRequest&) =
+      delete;
+  GetDetailsForCreateCardRequest& operator=(
+      const GetDetailsForCreateCardRequest&) = delete;
+  ~GetDetailsForCreateCardRequest() override;
+
+  // PaymentsRequest:
+  std::string GetRequestUrlPath() override;
+  std::string GetRequestContentType() override;
+  std::string GetRequestContent() override;
+  void ParseResponse(const base::Value::Dict& response) override;
+  bool IsResponseComplete() override;
+  void RespondToDelegate(
+      PaymentsAutofillClient::PaymentsRpcResult result) override;
+
+ private:
+  friend class GetDetailsForCreateCardTestApi;
+
+  const std::string unique_country_code_;
+  const std::vector<ClientBehaviorConstants> client_behavior_signals_;
+  const std::string app_locale_;
+  base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult,
+                          const std::u16string&,
+                          std::unique_ptr<base::Value::Dict>,
+                          std::vector<std::pair<int, int>>)>
+      callback_;
+  const int billable_service_number_;
+  const UploadCardSource upload_card_source_;
+  const int64_t billing_customer_number_;
+
+  std::u16string context_token_;
+  std::unique_ptr<base::Value::Dict> legal_message_;
+  std::vector<std::pair<int, int>> supported_card_bin_ranges_;
+};
+
+}  // namespace autofill::payments
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_H_
diff --git a/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_test_api.h b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_test_api.h
new file mode 100644
index 0000000..232e6db6
--- /dev/null
+++ b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_test_api.h
@@ -0,0 +1,45 @@
+// Copyright 2025 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_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_TEST_API_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_TEST_API_H_
+
+#include "base/check_deref.h"
+#include "components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h"
+
+namespace autofill::payments {
+
+class GetDetailsForCreateCardTestApi {
+ public:
+  explicit GetDetailsForCreateCardTestApi(
+      GetDetailsForCreateCardRequest* request)
+      : request_(CHECK_DEREF(request)) {}
+  GetDetailsForCreateCardTestApi(const GetDetailsForCreateCardTestApi&) =
+      delete;
+  GetDetailsForCreateCardTestApi& operator=(
+      const GetDetailsForCreateCardTestApi&) = delete;
+  ~GetDetailsForCreateCardTestApi() = default;
+
+  std::u16string context_token() const { return request_->context_token_; }
+
+  base::Value::Dict* legal_message() const {
+    return request_->legal_message_.get();
+  }
+
+  std::vector<std::pair<int, int>> supported_card_bin_ranges() const {
+    return request_->supported_card_bin_ranges_;
+  }
+
+ private:
+  const raw_ref<GetDetailsForCreateCardRequest> request_;
+};
+
+inline GetDetailsForCreateCardTestApi test_api(
+    GetDetailsForCreateCardRequest& request) {
+  return GetDetailsForCreateCardTestApi(&request);
+}
+
+}  // namespace autofill::payments
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_GET_DETAILS_FOR_CREATE_CARD_REQUEST_TEST_API_H_
diff --git a/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_unittest.cc
new file mode 100644
index 0000000..633cf1c
--- /dev/null
+++ b/components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2025 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/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/test/values_test_util.h"
+#include "components/autofill/core/browser/payments/client_behavior_constants.h"
+#include "components/autofill/core/browser/payments/payments_request_details.h"
+#include "components/autofill/core/browser/payments/payments_requests/get_details_for_create_card_request_test_api.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill::payments {
+namespace {
+
+constexpr char kUniqueCountryCode[] = "US";
+constexpr char kAppLocale[] = "en";
+constexpr int64_t kBillingCustomerNumber = 111122223333;
+
+std::unique_ptr<GetDetailsForCreateCardRequest> CreateRequest() {
+  std::vector<ClientBehaviorConstants> client_behavior_signals{
+      ClientBehaviorConstants::kOfferingToSaveCvc};
+  return std::make_unique<GetDetailsForCreateCardRequest>(
+      kUniqueCountryCode, client_behavior_signals, kAppLocale,
+      /*callback=*/base::DoNothing(), kUploadPaymentMethodBillableServiceNumber,
+      kBillingCustomerNumber, UploadCardSource::UPSTREAM_SAVE_AND_FILL);
+}
+
+TEST(GetDetailsForCreateCardRequestTest,
+     GetRequestContent_ContainsExpectedData) {
+  std::unique_ptr<GetDetailsForCreateCardRequest> request = CreateRequest();
+  base::Value::Dict expected_request_content =
+      base::Value::Dict()
+          .Set("context",
+               base::Value::Dict()
+                   .Set("billable_service",
+                        payments::kUploadPaymentMethodBillableServiceNumber)
+                   .Set("customer_context",
+                        PaymentsRequest::BuildCustomerContextDictionary(
+                            kBillingCustomerNumber))
+                   .Set("language_code", "en"))
+          .Set("chrome_user_context",
+               base::Value::Dict().Set(
+                   "client_behavior_signals",
+                   base::Value::List().Append(static_cast<int>(
+                       ClientBehaviorConstants::kOfferingToSaveCvc))))
+          .Set("card_info",
+               base::Value::Dict()
+                   .Set("unique_country_code", "US")
+                   .Set("upload_card_source", "UPSTREAM_SAVE_AND_FILL"));
+
+  EXPECT_THAT(request->GetRequestContent(),
+              base::test::IsJson(expected_request_content));
+}
+
+TEST(GetDetailsForCreateCardRequestTest, ParseResponse_ResponseIsComplete) {
+  std::unique_ptr<GetDetailsForCreateCardRequest> request = CreateRequest();
+  base::Value::Dict response =
+      base::Value::Dict()
+          .Set("context_token", u"some token")
+          .Set("legal_message",
+               base::Value::Dict().Set("terms_of_service", "Terms of Service"))
+          .Set("card_details",
+               base::Value::Dict().Set("supported_card_bin_ranges_string",
+                                       "1234,30000-55555,765"));
+
+  request->ParseResponse(response);
+
+  EXPECT_EQ(test_api(*request).context_token(), u"some token");
+  EXPECT_TRUE(test_api(*request).legal_message());
+  EXPECT_EQ(test_api(*request).supported_card_bin_ranges().size(), 3UL);
+  EXPECT_TRUE(request->IsResponseComplete());
+}
+
+TEST(GetDetailsForCreateCardRequestTest, ParseResponse_MissingContextToken) {
+  std::unique_ptr<GetDetailsForCreateCardRequest> request = CreateRequest();
+  base::Value::Dict response =
+      base::Value::Dict()
+          .Set("legal_message",
+               base::Value::Dict().Set("terms_of_service", "Terms of Service"))
+          .Set("card_details",
+               base::Value::Dict().Set("supported_card_bin_ranges_string",
+                                       "1234,30000-55555,765"));
+
+  request->ParseResponse(response);
+
+  EXPECT_FALSE(request->IsResponseComplete());
+}
+
+TEST(GetDetailsForCreateCardRequestTest, ParseResponse_MissingLegalMessage) {
+  std::unique_ptr<GetDetailsForCreateCardRequest> request = CreateRequest();
+  base::Value::Dict response =
+      base::Value::Dict()
+          .Set("context_token", u"some token")
+          .Set("card_details",
+               base::Value::Dict().Set("supported_card_bin_ranges_string",
+                                       "1234,30000-55555,765"));
+
+  request->ParseResponse(response);
+
+  EXPECT_FALSE(request->IsResponseComplete());
+}
+
+TEST(GetDetailsForCreateCardRequestTest,
+     ParseResponse_MissingSupportedCardBinRanges) {
+  std::unique_ptr<GetDetailsForCreateCardRequest> request = CreateRequest();
+  base::Value::Dict response =
+      base::Value::Dict()
+          .Set("context_token", u"some token")
+          .Set("legal_message",
+               base::Value::Dict().Set("terms_of_service", "Terms of Service"));
+
+  request->ParseResponse(response);
+
+  EXPECT_TRUE(request->IsResponseComplete());
+}
+
+}  // namespace
+
+}  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_requests/payments_request.cc b/components/autofill/core/browser/payments/payments_requests/payments_request.cc
index da438be..0995d3f 100644
--- a/components/autofill/core/browser/payments/payments_requests/payments_request.cc
+++ b/components/autofill/core/browser/payments/payments_requests/payments_request.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
 #include "base/types/cxx23_to_underlying.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -77,8 +78,15 @@
 base::Value::Dict PaymentsRequest::BuildChromeUserContext(
     const std::vector<ClientBehaviorConstants>& client_behavior_signals,
     bool full_sync_enabled) {
-  base::Value::Dict chrome_user_context;
+  base::Value::Dict chrome_user_context =
+      BuildChromeUserContext(client_behavior_signals);
   chrome_user_context.Set("full_sync_enabled", full_sync_enabled);
+  return chrome_user_context;
+}
+
+base::Value::Dict PaymentsRequest::BuildChromeUserContext(
+    const std::vector<ClientBehaviorConstants>& client_behavior_signals) {
+  base::Value::Dict chrome_user_context;
   if (!client_behavior_signals.empty()) {
     base::Value::List active_client_signals;
     for (ClientBehaviorConstants signal : client_behavior_signals) {
@@ -182,4 +190,30 @@
     dictionary.Set(path, std::move(value));
 }
 
+std::vector<std::pair<int, int>>
+PaymentsRequest::ParseSupportedCardBinRangesString(
+    const std::string& supported_card_bin_ranges_string) {
+  std::vector<std::pair<int, int>> supported_card_bin_ranges;
+  std::vector<std::string> range_strings =
+      base::SplitString(supported_card_bin_ranges_string, ",",
+                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  for (std::string& range_string : range_strings) {
+    std::vector<std::string> range = base::SplitString(
+        range_string, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    DCHECK(range.size() <= 2);
+    int start;
+    base::StringToInt(range[0], &start);
+    if (range.size() == 1) {
+      supported_card_bin_ranges.emplace_back(start, start);
+    } else {
+      int end;
+      base::StringToInt(range[1], &end);
+      DCHECK_LE(start, end);
+      supported_card_bin_ranges.emplace_back(start, end);
+    }
+  }
+  return supported_card_bin_ranges;
+}
+
 }  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_requests/payments_request.h b/components/autofill/core/browser/payments/payments_requests/payments_request.h
index b19048ff..6ba0558 100644
--- a/components/autofill/core/browser/payments/payments_requests/payments_request.h
+++ b/components/autofill/core/browser/payments/payments_requests/payments_request.h
@@ -91,9 +91,13 @@
  protected:
   // Shared helper function that builds the Chrome user context which is then
   // set in the payment requests.
+  // Note: `full_sync_enabled` is being deprecated. Don't call this in new code.
+  // Use the below function instead.
   base::Value::Dict BuildChromeUserContext(
       const std::vector<ClientBehaviorConstants>& client_behavior_signals,
       bool full_sync_enabled);
+  base::Value::Dict BuildChromeUserContext(
+      const std::vector<ClientBehaviorConstants>& client_behavior_signals);
 
   // Shared helper functoin that returns a dictionary with the structure
   // expected by Payments RPCs, containing each of the fields in |profile|,
@@ -123,6 +127,13 @@
                                   const std::string& app_locale,
                                   const std::string& path,
                                   base::Value::Dict& dictionary);
+
+  // Helper for ParseResponse(). Input format should be "1234,30000-55555,765",
+  // where ranges are separated by commas and items separated with a dash means
+  // the start and ends of the range. Items without a dash have the same start
+  // and end (ex. 1234-1234).
+  std::vector<std::pair<int, int>> ParseSupportedCardBinRangesString(
+      const std::string& supported_card_bin_ranges_string);
 };
 
 }  // namespace autofill::payments
diff --git a/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager.cc b/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager.cc
index 20e8650..f4e118e 100644
--- a/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager.cc
+++ b/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager.cc
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/version_info/version_info.h"
 #include "components/autofill/core/browser/data_quality/validation.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/studies/autofill_experiments.h"
@@ -174,7 +175,7 @@
     // stored in this pref.
     int last_cleaned_version = pref_service_->GetInteger(
         prefs::kAutocompleteLastVersionRetentionPolicy);
-    if (CHROME_VERSION_MAJOR > last_cleaned_version) {
+    if (version_info::GetMajorVersionNumberAsInt() > last_cleaned_version) {
       // Trigger the cleanup.
       profile_database_->RemoveExpiredAutocompleteEntries(base::BindOnce(
           &AutocompleteHistoryManager::OnWebDataServiceRequestDone,
@@ -287,7 +288,7 @@
 
   // Cleanup was successful, update the latest run milestone.
   pref_service_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                            CHROME_VERSION_MAJOR);
+                            version_info::GetMajorVersionNumberAsInt());
 }
 
 // We put the following restriction on stored FormFields:
diff --git a/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager_unittest.cc
index f34f011..a3ff4dd7 100644
--- a/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager_unittest.cc
+++ b/components/autofill/core/browser/single_field_fillers/autocomplete/autocomplete_history_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "base/version_info/version_info.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/foundations/test_autofill_client.h"
 #include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
@@ -78,7 +79,7 @@
 
     // Mock such that we don't trigger the cleanup.
     prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                       CHROME_VERSION_MAJOR);
+                       version_info::GetMajorVersionNumberAsInt());
 
     // Set time to some arbitrary date.
     task_environment_.AdvanceClock(
@@ -387,7 +388,7 @@
 TEST_F(AutocompleteHistoryManagerTest, Init_TriggersCleanup) {
   // Set the retention policy cleanup to a past major version.
   prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                     CHROME_VERSION_MAJOR - 1);
+                     version_info::GetMajorVersionNumberAsInt() - 1);
 
   EXPECT_CALL(*web_data_service_, RemoveExpiredAutocompleteEntries).Times(1);
   autocomplete_manager_->Init(web_data_service_, prefs_.get(),
@@ -399,7 +400,7 @@
 TEST_F(AutocompleteHistoryManagerTest, Init_OTR_Not_TriggersCleanup) {
   // Set the retention policy cleanup to a past major version.
   prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                     CHROME_VERSION_MAJOR - 1);
+                     version_info::GetMajorVersionNumberAsInt() - 1);
 
   EXPECT_CALL(*web_data_service_, RemoveExpiredAutocompleteEntries).Times(0);
   autocomplete_manager_->Init(web_data_service_, prefs_.get(),
@@ -410,7 +411,7 @@
 TEST_F(AutocompleteHistoryManagerTest, Init_NullDB_NoCrash) {
   // Set the retention policy cleanup to a past major version.
   prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                     CHROME_VERSION_MAJOR - 1);
+                     version_info::GetMajorVersionNumberAsInt() - 1);
 
   EXPECT_CALL(*web_data_service_, RemoveExpiredAutocompleteEntries).Times(0);
   autocomplete_manager_->Init(nullptr, prefs_.get(),
@@ -423,7 +424,7 @@
        Init_SameMajorVersion_Not_TriggersCleanup) {
   // Set the retention policy cleanup to the current major version.
   prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                     CHROME_VERSION_MAJOR);
+                     version_info::GetMajorVersionNumberAsInt());
 
   EXPECT_CALL(*web_data_service_, RemoveExpiredAutocompleteEntries).Times(0);
   autocomplete_manager_->Init(web_data_service_, prefs_.get(),
@@ -881,7 +882,7 @@
       1, std::make_unique<WDResult<size_t>>(AUTOFILL_CLEANUP_RESULT,
                                             cleanup_result));
 
-  EXPECT_EQ(CHROME_VERSION_MAJOR,
+  EXPECT_EQ(version_info::GetMajorVersionNumberAsInt(),
             prefs_->GetInteger(prefs::kAutocompleteLastVersionRetentionPolicy));
 }
 
diff --git a/components/autofill/core/browser/single_field_fillers/single_field_fill_router_unittest.cc b/components/autofill/core/browser/single_field_fillers/single_field_fill_router_unittest.cc
index 15822b7..89a9c2a 100644
--- a/components/autofill/core/browser/single_field_fillers/single_field_fill_router_unittest.cc
+++ b/components/autofill/core/browser/single_field_fillers/single_field_fill_router_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "base/version_info/version_info.h"
 #include "components/autofill/core/browser/data_manager/personal_data_manager.h"
 #include "components/autofill/core/browser/data_manager/test_personal_data_manager.h"
 #include "components/autofill/core/browser/form_structure.h"
@@ -46,7 +47,7 @@
 
     // Mock such that we don't trigger the cleanup.
     prefs_->SetInteger(prefs::kAutocompleteLastVersionRetentionPolicy,
-                       CHROME_VERSION_MAJOR);
+                       version_info::GetMajorVersionNumberAsInt());
     web_data_service_ = base::MakeRefCounted<MockAutofillWebDataService>();
     history_manager().Init(web_data_service_, prefs_.get(), false);
 
diff --git a/components/autofill/core/browser/studies/autofill_ablation_study.cc b/components/autofill/core/browser/studies/autofill_ablation_study.cc
index ad694d85..0de075e 100644
--- a/components/autofill/core/browser/studies/autofill_ablation_study.cc
+++ b/components/autofill/core/browser/studies/autofill_ablation_study.cc
@@ -17,6 +17,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
+#include "base/types/zip.h"
 #include "components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_features.h"
@@ -183,37 +184,39 @@
       break;
   }
 
-  std::array<const base::FeatureParam<int>*, 6> ablation_list_params = {
-      &kAutofillAblationStudyAblationWeightPerMilleList1Param,
-      &kAutofillAblationStudyAblationWeightPerMilleList2Param,
-      &kAutofillAblationStudyAblationWeightPerMilleList3Param,
-      &kAutofillAblationStudyAblationWeightPerMilleList4Param,
-      &kAutofillAblationStudyAblationWeightPerMilleList5Param,
-      &kAutofillAblationStudyAblationWeightPerMilleList6Param,
-  };
+  const auto ablation_list_params =
+      std::to_array<const base::FeatureParam<int>*>(
+          {&kAutofillAblationStudyAblationWeightPerMilleList1Param,
+           &kAutofillAblationStudyAblationWeightPerMilleList2Param,
+           &kAutofillAblationStudyAblationWeightPerMilleList3Param,
+           &kAutofillAblationStudyAblationWeightPerMilleList4Param,
+           &kAutofillAblationStudyAblationWeightPerMilleList5Param,
+           &kAutofillAblationStudyAblationWeightPerMilleList6Param});
   using OptimizationType = optimization_guide::proto::OptimizationType;
-  constexpr std::array<OptimizationType, 6> ablation_optimization_types = {
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST1,
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST2,
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST3,
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST4,
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST5,
-      OptimizationType::AUTOFILL_ABLATION_SITES_LIST6};
+  static constexpr auto ablation_optimization_types =
+      std::to_array<OptimizationType>(
+          {OptimizationType::AUTOFILL_ABLATION_SITES_LIST1,
+           OptimizationType::AUTOFILL_ABLATION_SITES_LIST2,
+           OptimizationType::AUTOFILL_ABLATION_SITES_LIST3,
+           OptimizationType::AUTOFILL_ABLATION_SITES_LIST4,
+           OptimizationType::AUTOFILL_ABLATION_SITES_LIST5,
+           OptimizationType::AUTOFILL_ABLATION_SITES_LIST6});
 
   base::Time now = AutofillClock::Now();
-  for (size_t i = 0; i < ablation_list_params.size(); ++i) {
+  for (auto [param, optimization_type] :
+       base::zip(ablation_list_params, ablation_optimization_types)) {
     // Do some basic checks for plausibility. Note that for testing purposes
     // we allow that ablation_weight == 1000. In this case 100% of forms are
     // in the ablation case. In practice ablation_weight * 2 <= total_weight
     // should be true to get meaningful results (have an equally sized
     // ablation and control group).
-    int ablation_weight = ablation_list_params[i]->Get();
+    const int ablation_weight = param->Get();
     if (ablation_weight <= 0 || ablation_weight > 1000) {
       continue;
     }
     if (!autofill_optimization_guide ||
         !autofill_optimization_guide->IsEligibleForAblation(
-            url, ablation_optimization_types[i])) {
+            url, optimization_type)) {
       continue;
     }
     return GetAblationGroupImpl(url, now, ablation_weight);
diff --git a/components/autofill/core/browser/suggestions/suggestion.h b/components/autofill/core/browser/suggestions/suggestion.h
index a18c0c4..5e79ac3 100644
--- a/components/autofill/core/browser/suggestions/suggestion.h
+++ b/components/autofill/core/browser/suggestions/suggestion.h
@@ -163,7 +163,7 @@
     // https://w3c-fedid.github.io/FedCM/#dom-identityprovideraccount-id
     std::string account_id;
     // The field values of the account profile available to autofill.
-    std::map<HtmlFieldType, std::u16string> fields;
+    std::map<FieldType, std::u16string> fields;
   };
 
   using IsLoading = base::StrongAlias<class IsLoadingTag, bool>;
diff --git a/components/autofill/core/browser/ui/autofill_external_delegate.cc b/components/autofill/core/browser/ui/autofill_external_delegate.cc
index 205442c..222e677 100644
--- a/components/autofill/core/browser/ui/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/ui/autofill_external_delegate.cc
@@ -630,15 +630,16 @@
         PreviewAddressFieldByFieldFillingSuggestion(*profile, suggestion);
       }
       break;
-    case SuggestionType::kIdentityCredential:
-      // TODO(crbug.com/380367784): allow previewing more field types.
-      manager_->FillOrPreviewField(
-          mojom::ActionPersistence::kPreview,
-          mojom::FieldActionType::kReplaceAll, query_form_, query_field_,
-          suggestion.GetPayload<Suggestion::IdentityCredentialPayload>()
-              .fields[HtmlFieldType::kEmail],
-          SuggestionType::kIdentityCredential, EMAIL_ADDRESS);
+    case SuggestionType::kIdentityCredential: {
+      VerifiedProfile profile =
+          suggestion.GetPayload<Suggestion::IdentityCredentialPayload>().fields;
+
+      manager_->FillOrPreviewForm(
+          mojom::ActionPersistence::kPreview, query_form_,
+          query_field_.global_id(), &profile,
+          TriggerSourceFromSuggestionTriggerSource(trigger_source_));
       break;
+    }
     case SuggestionType::kLoyaltyCardEntry:
       // Always shows the masked loyalty card value as the preview of the
       // suggestion.
@@ -850,16 +851,13 @@
         identity_credential_delegate->NotifySuggestionAccepted(
             suggestion, base::NullCallback());
 
-        // TODO(crbug.com/380367784): generalize this to allow filling different
-        // field types (e.g. passwords) as well as more than one one field
-        // at a time (e.g. name and email, rather than email alone)?
-        Suggestion::IdentityCredentialPayload payload =
-            suggestion.GetPayload<Suggestion::IdentityCredentialPayload>();
-        manager_->FillOrPreviewField(
-            mojom::ActionPersistence::kFill,
-            mojom::FieldActionType::kReplaceAll, query_form_, query_field_,
-            payload.fields[HtmlFieldType::kEmail],
-            SuggestionType::kIdentityCredential, EMAIL_ADDRESS);
+        VerifiedProfile profile =
+            suggestion.GetPayload<Suggestion::IdentityCredentialPayload>()
+                .fields;
+        manager_->FillOrPreviewForm(
+            mojom::ActionPersistence::kFill, query_form_,
+            query_field_.global_id(), &profile,
+            TriggerSourceFromSuggestionTriggerSource(trigger_source_));
       }
       break;
     }
diff --git a/components/autofill/core/browser/ui/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/ui/autofill_external_delegate_unittest.cc
index 1f3b03f3..6f1c395 100644
--- a/components/autofill/core/browser/ui/autofill_external_delegate_unittest.cc
+++ b/components/autofill/core/browser/ui/autofill_external_delegate_unittest.cc
@@ -1261,11 +1261,8 @@
 
   // Test preview.
   EXPECT_CALL(manager(),
-              FillOrPreviewField(mojom::ActionPersistence::kPreview,
-                                 mojom::FieldActionType::kReplaceAll,
-                                 HasQueriedFormId(), HasQueriedFieldId(), _,
-                                 SuggestionType::kIdentityCredential,
-                                 std::optional(EMAIL_ADDRESS)));
+              FillOrPreviewForm(mojom::ActionPersistence::kPreview,
+                                HasQueriedFormId(), IsQueriedFieldId(), _, _));
   external_delegate().DidSelectSuggestion(suggestion);
 }
 
@@ -1283,12 +1280,8 @@
 
   // Expect that the form filler gets notified.
   EXPECT_CALL(manager(),
-              FillOrPreviewField(mojom::ActionPersistence::kFill,
-                                 mojom::FieldActionType::kReplaceAll,
-                                 HasQueriedFormId(), HasQueriedFieldId(), _,
-                                 SuggestionType::kIdentityCredential,
-                                 std::optional(EMAIL_ADDRESS)));
-
+              FillOrPreviewForm(mojom::ActionPersistence::kFill,
+                                HasQueriedFormId(), IsQueriedFieldId(), _, _));
   // Expect that the delegate gets notified.
   EXPECT_CALL(mock, NotifySuggestionAccepted(suggestion, _));
 
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 4fec2d29..54fb29e5 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -147,6 +147,11 @@
              "AutofillEnableLogFormEventsToAllParsedFormTypes",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// When enabled, the card benefits toggle in settings will show updated text.
+BASE_FEATURE(kAutofillEnableNewCardBenefitsToggleText,
+             "AutofillEnableNewCardBenefitsToggleText",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // When enabled, card and IBAN autofill will be shown in new FOP style.
 BASE_FEATURE(kAutofillEnableNewFopDisplayDesktop,
              "AutofillEnableNewFopDisplayDesktop",
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index 36bf7e7..e9c4608 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -54,6 +54,8 @@
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableLogFormEventsToAllParsedFormTypes);
 COMPONENT_EXPORT(AUTOFILL)
+BASE_DECLARE_FEATURE(kAutofillEnableNewCardBenefitsToggleText);
+COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableNewFopDisplayDesktop);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillEnableOffersInClankKeyboardAccessory);
diff --git a/components/autofill/core/common/form_data_unittest.cc b/components/autofill/core/common/form_data_unittest.cc
index 91fd7366..b130b1f 100644
--- a/components/autofill/core/common/form_data_unittest.cc
+++ b/components/autofill/core/common/form_data_unittest.cc
@@ -30,8 +30,8 @@
   pickle->WriteString(form_data.action().spec());
   pickle->WriteBool(true);  // Used to be |user_submitted|, which was removed.
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
 }
 
@@ -43,8 +43,8 @@
   pickle->WriteString(form_data.action().spec());
   pickle->WriteBool(true);  // Used to be |user_submitted|, which was removed.
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
 }
 
@@ -56,8 +56,8 @@
   pickle->WriteString(form_data.action().spec());
   pickle->WriteBool(true);  // Used to be |user_submitted|, which was removed.
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteBool(false);  // Used to be `is_form_tag`, which was removed
 }
@@ -69,8 +69,8 @@
   pickle->WriteString(form_data.url().spec());
   pickle->WriteString(form_data.action().spec());
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteBool(false);  // Used to be `is_form_tag`, which was removed
 }
@@ -82,8 +82,8 @@
   pickle->WriteString(form_data.url().spec());
   pickle->WriteString(form_data.action().spec());
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteBool(false);  // Used to be `is_form_tag`, which was removed
   pickle->WriteBool(/*is_formless_checkout=*/true);
@@ -96,8 +96,8 @@
   pickle->WriteString(form_data.url().spec());
   pickle->WriteString(form_data.action().spec());
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteBool(false);  // Used to be `is_form_tag`, which was removed
   pickle->WriteBool(/*is_formless_checkout=*/true);
@@ -111,8 +111,8 @@
   pickle->WriteString(form_data.url().spec());
   pickle->WriteString(form_data.action().spec());
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteBool(false);  // Used to be `is_form_tag`, which was removed
   pickle->WriteString(form_data.main_frame_origin().Serialize());
@@ -125,8 +125,8 @@
   pickle->WriteString(form_data.url().spec());
   pickle->WriteString(form_data.action().spec());
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
   pickle->WriteString(form_data.main_frame_origin().Serialize());
 }
@@ -139,8 +139,8 @@
   pickle->WriteString(form_data.action().spec());
   pickle->WriteBool(true);  // Used to be |user_submitted|, which was removed.
   pickle->WriteInt(static_cast<int>(form_data.fields().size()));
-  for (size_t i = 0; i < form_data.fields().size(); ++i) {
-    SerializeFormFieldData(form_data.fields()[i], pickle);
+  for (const FormFieldData& field : form_data.fields()) {
+    SerializeFormFieldData(field, pickle);
   }
 }
 
diff --git a/components/autofill/ios/DEPS b/components/autofill/ios/DEPS
index a78cb67..d3c1ff3 100644
--- a/components/autofill/ios/DEPS
+++ b/components/autofill/ios/DEPS
@@ -2,4 +2,7 @@
   "+google_apis/gaia",
   "+ios/testing",
   "+ios/web/public",
+
+  # For tests
+  "+ios/web/test/fakes",
 ]
diff --git a/components/autofill/ios/common/features.h b/components/autofill/ios/common/features.h
index 0074382..8e8683e1 100644
--- a/components/autofill/ios/common/features.h
+++ b/components/autofill/ios/common/features.h
@@ -25,6 +25,13 @@
 // instead of using true by default.
 BASE_DECLARE_FEATURE(kAutofillCorrectUserEditedBitInParsedField);
 
+// Dedupes form submission by only allowing one submission per form element.
+// This feature is meant to be used when preventDefault()ed submit events are
+// allowed (i.e. AutofillAllowDefaultPreventedSubmission enabled) which can
+// allow submitting the form multiple times as post-submit navigation can be
+// prevented.
+BASE_DECLARE_FEATURE(kAutofillDedupeFormSubmission);
+
 // Controls whether to dynamically load the address input fields in the save
 // flow and settings based on the country value.
 // TODO(crbug.com/40281788): Remove once launched.
diff --git a/components/autofill/ios/common/features.mm b/components/autofill/ios/common/features.mm
index a679590c..a07232d 100644
--- a/components/autofill/ios/common/features.mm
+++ b/components/autofill/ios/common/features.mm
@@ -28,6 +28,12 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 // LINT.ThenChange(/components/autofill/ios/form_util/resources/autofill_form_features.ts:autofill_correct_user_edited_bit_in_parsed_field)
 
+// LINT.IfChange(autofill_dedupe_form_submission)
+BASE_FEATURE(kAutofillDedupeFormSubmission,
+             "AutofillDedupeFormSubmission",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+// LINT.ThenChange(/components/autofill/ios/form_util/resources/autofill_form_features.ts:autofill_dedupe_form_submission)
+
 BASE_FEATURE(kAutofillDynamicallyLoadsFieldsForAddressInput,
              "AutofillDynamicallyLoadsFieldsForAddressInput",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/autofill/ios/form_util/BUILD.gn b/components/autofill/ios/form_util/BUILD.gn
index 96d6f3d..e931130 100644
--- a/components/autofill/ios/form_util/BUILD.gn
+++ b/components/autofill/ios/form_util/BUILD.gn
@@ -338,6 +338,7 @@
     "//components/autofill/ios/common",
     "//ios/web/public/js_messaging",
     "//ios/web/public/js_messaging:content_world_header",
+    "//ios/web/public/js_messaging:web_view_js_utils",
     "//ios/web/public/test:javascript_test",
     "//ios/web/public/test:test_fixture",
     "//ios/web/public/test:util",
diff --git a/components/autofill/ios/form_util/autofill_form_features_injector.mm b/components/autofill/ios/form_util/autofill_form_features_injector.mm
index bccecaf..4fe6b98 100644
--- a/components/autofill/ios/form_util/autofill_form_features_injector.mm
+++ b/components/autofill/ios/form_util/autofill_form_features_injector.mm
@@ -68,6 +68,11 @@
       ->SetAutofillAllowDefaultPreventedFormSubmission(
           web_frame, base::FeatureList::IsEnabled(
                          kAutofillAllowDefaultPreventedSubmission));
+
+  AutofillFormFeaturesJavaScriptFeature::GetInstance()
+      ->SetAutofillDedupeFormSubmission(
+          web_frame,
+          base::FeatureList::IsEnabled(kAutofillDedupeFormSubmission));
 }
 
 AutofillFormFeaturesInjector::~AutofillFormFeaturesInjector() = default;
diff --git a/components/autofill/ios/form_util/autofill_form_features_injector_unittest.mm b/components/autofill/ios/form_util/autofill_form_features_injector_unittest.mm
index a6e7bdd..f9c78e6d 100644
--- a/components/autofill/ios/form_util/autofill_form_features_injector_unittest.mm
+++ b/components/autofill/ios/form_util/autofill_form_features_injector_unittest.mm
@@ -64,7 +64,7 @@
        autofill::features::kAutofillAcrossIframesIosThrottling,
        autofill::features::kAutofillDisallowSlashDotLabels,
        kAutofillFixPaymentSheetSpam, kAutofillCorrectUserEditedBitInParsedField,
-       kAutofillAllowDefaultPreventedSubmission},
+       kAutofillAllowDefaultPreventedSubmission, kAutofillDedupeFormSubmission},
       /* disabled_features= */ {});
 
   AutofillFormFeaturesInjector injector(&fake_web_state_,
@@ -89,7 +89,9 @@
                     u"__gCrWeb.autofill_form_features."
                     u"setAutofillCorrectUserEditedBitInParsedField(true);",
                     u"__gCrWeb.autofill_form_features."
-                    u"setAutofillAllowDefaultPreventedSubmission(true);"));
+                    u"setAutofillAllowDefaultPreventedSubmission(true);",
+                    u"__gCrWeb.autofill_form_features."
+                    u"setAutofillDedupeFormSubmission(true);"));
   }
 }
 
diff --git a/components/autofill/ios/form_util/autofill_form_features_java_script_feature.h b/components/autofill/ios/form_util/autofill_form_features_java_script_feature.h
index 94c2229..de4531b 100644
--- a/components/autofill/ios/form_util/autofill_form_features_java_script_feature.h
+++ b/components/autofill/ios/form_util/autofill_form_features_java_script_feature.h
@@ -52,6 +52,9 @@
   void SetAutofillAllowDefaultPreventedFormSubmission(web::WebFrame* frame,
                                                       bool enabled);
 
+  // Enables/disables deduping form submission for Autofill.
+  void SetAutofillDedupeFormSubmission(web::WebFrame* frame, bool enabled);
+
  private:
   friend class base::NoDestructor<AutofillFormFeaturesJavaScriptFeature>;
 
diff --git a/components/autofill/ios/form_util/autofill_form_features_java_script_feature.mm b/components/autofill/ios/form_util/autofill_form_features_java_script_feature.mm
index e1c65d1..810a91f 100644
--- a/components/autofill/ios/form_util/autofill_form_features_java_script_feature.mm
+++ b/components/autofill/ios/form_util/autofill_form_features_java_script_feature.mm
@@ -97,4 +97,13 @@
       base::Value::List().Append(enabled));
 }
 
+void AutofillFormFeaturesJavaScriptFeature::SetAutofillDedupeFormSubmission(
+    web::WebFrame* frame,
+    bool enabled) {
+  CHECK(frame);
+  frame->CallJavaScriptFunction(
+      "autofill_form_features.setAutofillDedupeFormSubmission",
+      base::Value::List().Append(enabled));
+}
+
 }  // namespace autofill
diff --git a/components/autofill/ios/form_util/form_unittest.mm b/components/autofill/ios/form_util/form_unittest.mm
index 7267b62..aca60bd 100644
--- a/components/autofill/ios/form_util/form_unittest.mm
+++ b/components/autofill/ios/form_util/form_unittest.mm
@@ -2,22 +2,62 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "base/apple/foundation_util.h"
+#import "base/test/ios/wait_util.h"
+#import "base/time/time.h"
+#import "components/autofill/ios/browser/autofill_util.h"
+#import "ios/web/public/js_messaging/web_view_js_utils.h"
 #import "ios/web/public/test/javascript_test.h"
 #import "ios/web/public/test/js_test_util.h"
 #import "testing/gtest_mac.h"
 
 using web::test::ExecuteJavaScript;
 
+NSString* const kMessageHandlerName = @"TestHandler";
+
+//
+@interface FakeScriptMessageHandlerForFormTesting
+    : NSObject <WKScriptMessageHandler>
+
+@property(nonatomic, strong) WKScriptMessage* lastReceivedMessage;
+@property(nonatomic, assign) int messageCount;
+
+@end
+
+@implementation FakeScriptMessageHandlerForFormTesting
+
+- (void)userContentController:(WKUserContentController*)userContentController
+      didReceiveScriptMessage:(WKScriptMessage*)message {
+  _lastReceivedMessage = message;
+  ++_messageCount;
+}
+
+@end
+
 namespace autofill {
 
 // Text fixture to test form.js.
 class FormJsTest : public web::JavascriptTest {
  protected:
+  FormJsTest()
+      : handler_([[FakeScriptMessageHandlerForFormTesting alloc] init]) {
+    // Add an handler to get messages.
+    [web_view().configuration.userContentController
+        addScriptMessageHandler:handler_
+                           name:kMessageHandlerName];
+  }
+
   void SetUp() override {
     web::JavascriptTest::SetUp();
+    AddGCrWebScript();
+    AddCommonScript();
+    AddMessageScript();
     AddUserScript(@"fill");
     AddUserScript(@"form");
+    AddUserScript(@"autofill_form_features");
   }
+
+  FakeScriptMessageHandlerForFormTesting* handler_;
 };
 
 TEST_F(FormJsTest, GetIframeElements) {
@@ -41,4 +81,123 @@
               ExecuteJavaScript(web_view(), @"!!(frames[1].contentWindow);"));
 }
 
+// Tests that the `formSubmitted` handler does deduping.
+TEST_F(FormJsTest, FormSubmitted_Deduping) {
+  // Create arbitrary form elements to use as the submitted forms.
+  LoadHtml(@"<form name='form1'></form><form name='form2'></form>");
+
+  // Swizzle the webkit messaging posting method to count the number of messages
+  // sent over. It should only concern submission messages for this test.
+  NSString* swizzleScript =
+      @"var gMsgCount = 0; "
+       "let oldFn = UserMessageHandler.prototype.postMessage; "
+       " function newFn(...args) { ++gMsgCount; return oldFn.apply(this, "
+       "args); }; "
+       "UserMessageHandler.prototype.postMessage = newFn";
+  ExecuteJavaScript(web_view(), swizzleScript);
+
+  // Enable form submission deduping.
+  ExecuteJavaScript(web_view(), @"__gCrWeb.autofill_form_features."
+                                 "setAutofillDedupeFormSubmission(true);");
+
+  // == Submit first form ==
+
+  // Submit the first form for the first time.
+  ExecuteJavaScript(web_view(),
+                    @"__gCrWeb.form.formSubmitted("
+                     "document.forms[0], 'TestHandler', false, false)");
+
+  // Wait for the submission message for the first form to be received from the
+  // renderer. This verifies that the submission is at least reported once.
+  {
+    __block WKScriptMessage* messageFromForm;
+    __weak __typeof(handler_) weak_handler = handler_;
+    ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+        base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
+          messageFromForm = weak_handler.lastReceivedMessage;
+          return weak_handler.lastReceivedMessage;
+        }));
+    ASSERT_TRUE(messageFromForm);
+    NSDictionary* messageFromFormContent =
+        base::apple::ObjCCastStrict<NSDictionary>(messageFromForm.body);
+    EXPECT_NSEQ(@"form1", messageFromFormContent[@"formName"]);
+  }
+
+  // Attempt other submissions on the same form, where it should be deduped
+  // this time, hence ignored.
+  for (size_t i = 0; i < 4; ++i) {
+    ExecuteJavaScript(web_view(),
+                      @"__gCrWeb.form.formSubmitted("
+                       "document.forms[0], 'TestHandler', false, false)");
+  }
+
+  // Verify that the submission message was only sent over once despite
+  // triggering formSubmitted() 5 times on the same form (the first form in this
+  // occurrence). Since all the scripts are run in order in the same JS event
+  // loop, it is guaranteed that all formSubmitted() were made before verifying
+  // the number of calls.
+  EXPECT_NSEQ(@(1), ExecuteJavaScript(web_view(), @"gMsgCount"));
+
+  handler_.lastReceivedMessage = nil;
+
+  // == Submit other form ==
+
+  // Submit the other form that wasn't submitted yet.
+  ExecuteJavaScript(web_view(),
+                    @"__gCrWeb.form.formSubmitted("
+                     "document.forms[1], 'TestHandler', false, false)");
+
+  // Wait for the submission message for the other form to be received from the
+  // renderer. This verifies that the submission is at least reported once per
+  // form.
+  {
+    __weak __typeof(handler_) weak_handler = handler_;
+    __block WKScriptMessage* messageFromForm;
+    ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+        base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
+          messageFromForm = weak_handler.lastReceivedMessage;
+          return weak_handler.lastReceivedMessage;
+        }));
+    ASSERT_TRUE(messageFromForm);
+    NSDictionary* messageFromFormContent =
+        base::apple::ObjCCastStrict<NSDictionary>(messageFromForm.body);
+    EXPECT_NSEQ(@"form2", messageFromFormContent[@"formName"]);
+  }
+
+  // Attempt other submissions on the same form, where it should be deduped
+  // this time, hence ignored. Verify that the submission message count remains
+  // 2, one message for each form.
+  for (size_t i = 0; i < 4; ++i) {
+    ExecuteJavaScript(web_view(),
+                      @"__gCrWeb.form.formSubmitted("
+                       "document.forms[1], 'TestHandler', false, false)");
+  }
+  EXPECT_TRUE(ExecuteJavaScript(web_view(), @"gMsgCount == 2"));
+}
+
+// Tests that the `formSubmitted` handler doesn't do deduping when the feature
+// doesn't allow it.
+TEST_F(FormJsTest, FormSubmitted_NoDeduping) {
+  // Create an arbitrary form to used as the submitted form.
+  LoadHtml(@"<form></form>");
+
+  // Enable deduping.
+  ExecuteJavaScript(web_view(), @"__gCrWeb.autofill_form_features."
+                                 "setAutofillDedupeFormSubmission(false);");
+
+  // Submit the form 4 times where each event should be reported (messaged over)
+  // because there is no deduping.
+  for (size_t i = 0; i < 4; ++i) {
+    ExecuteJavaScript(web_view(),
+                      @"__gCrWeb.form.formSubmitted("
+                       "document.forms[0], 'TestHandler', false, false)");
+  }
+
+  // Wait for all submission messages to be sent over.
+  ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      base::test::ios::kWaitForJSCompletionTimeout, ^bool() {
+        return handler_.messageCount == 4;
+      }));
+}
+
 }  // namespace autofill
diff --git a/components/autofill/ios/form_util/resources/autofill_form_features.ts b/components/autofill/ios/form_util/resources/autofill_form_features.ts
index 6553ec33..3d5a3bf 100644
--- a/components/autofill/ios/form_util/resources/autofill_form_features.ts
+++ b/components/autofill/ios/form_util/resources/autofill_form_features.ts
@@ -65,6 +65,13 @@
 let autofillAllowDefaultPreventedSubmission: boolean = false;
 // LINT.ThenChange(//components/autofill/ios/common/features.mm:autofill_allow_default_prevented_submission)
 
+// LINT.IfChange(autofill_dedupe_form_submission)
+/**
+Dedupes form submission by only allowing one submission per form.
+*/
+let autofillDedupeFormSubmission: boolean = false;
+// LINT.ThenChange(//components/autofill/ios/common/features.mm:autofill_dedupe_form_submission)
+
 /**
  * @see autofillAcrossIframes
  */
@@ -164,6 +171,20 @@
   return autofillAllowDefaultPreventedSubmission;
 }
 
+/**
+ * @see autofillDedupeFormSubmission
+ */
+function setAutofillDedupeFormSubmission(enabled: boolean): void {
+  autofillDedupeFormSubmission = enabled;
+}
+
+/**
+ * @see autofillDedupeFormSubmission
+ */
+function isAutofillDedupeFormSubmissionEnabled(): boolean {
+  return autofillDedupeFormSubmission;
+}
+
 // Expose globally via `gCrWeb` instead of `export` to ensure state (feature
 // on/off) is maintained across imports.
 gCrWebLegacy.autofill_form_features = {
@@ -181,4 +202,6 @@
   isAutofillCorrectUserEditedBitInParsedField,
   setAutofillAllowDefaultPreventedSubmission,
   isAutofillAllowDefaultPreventedSubmission,
+  setAutofillDedupeFormSubmission,
+  isAutofillDedupeFormSubmissionEnabled,
 };
diff --git a/components/autofill/ios/form_util/resources/form.ts b/components/autofill/ios/form_util/resources/form.ts
index 732d28d9..27f54ef 100644
--- a/components/autofill/ios/form_util/resources/form.ts
+++ b/components/autofill/ios/form_util/resources/form.ts
@@ -30,6 +30,15 @@
 const wasEditedByUser: WeakMap<any, any> = new WeakMap();
 
 /**
+ * Registry that tracks the forms that were submitted during the frame's
+ * lifetime. Elements that are garbage collected will be removed from the
+ * registry so this can't memory leak. In the worst case the registry will get
+ * as big as the number of submitted forms that aren't yet deleted and we don't
+ * expect a lot of those.
+ */
+const formSubmissionRegistry: WeakSet<any> = new WeakSet();
+
+/**
  * Based on Element::isFormControlElement() (WebKit)
  * @param element A DOM element.
  * @return true if the `element` is a form control element.
@@ -322,6 +331,16 @@
     programmaticSubmission: boolean,
     includeRemoteFrameToken: boolean = false,
     ): void {
+  if (gCrWebLegacy.autofill_form_features
+          .isAutofillDedupeFormSubmissionEnabled()) {
+    // Handle deduping when the feature allows it.
+    if (formSubmissionRegistry.has(form)) {
+      // Do not double submit the same form.
+      return;
+    }
+    formSubmissionRegistry.add(form);
+  }
+
   // Default URL for action is the document's URL.
   const action = form.getAttribute('action') || document.URL;
 
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index 30c4d0b2..1188e20 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -1035,6 +1035,9 @@
     <message name="IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_LEARN_LINK" desc="Sublabel for the payments settings page card benefits toggle, including a hyperlinked text to learn about card benefits.">
       Show which rewards and benefits are available for your cards at checkout. <ph name="CARD_BENEFIT_HELP_LINK_BEGIN">&lt;a href="$1" aria-description="$2"&gt;</ph>Learn about card benefits<ph name="CARD_BENEFIT_HELP_LINK_END">&lt;/a&gt;</ph>
     </message>
+    <message name="IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_ISSUER_TERMS_APPLY_TEXT_AND_LEARN_LINK" desc="Sublabel for the payments settings page card benefits toggle that makes it clear to the user that issuer terms apply. Also includes a hyperlinked text to learn about card benefits.">
+      Show available card benefits and rewards at checkout. Issuer terms apply. <ph name="CARD_BENEFIT_HELP_LINK_BEGIN">&lt;a href="$1" aria-description="$2"&gt;</ph>Learn more<ph name="CARD_BENEFIT_HELP_LINK_END">&lt;/a&gt;</ph>
+    </message>
     <message name="IDS_AUTOFILL_SETTINGS_PAGE_BENEFITS_TERMS_TAG_FOR_CREDIT_CARD_LIST_ENTRY" desc="Tag present on each entry in the credit card list on the payments settings page if that entry has associated benefits and a product terms URL. It is also a hyperlink text which opens the product terms page.">
       See card benefit terms
     </message>
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_ISSUER_TERMS_APPLY_TEXT_AND_LEARN_LINK.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_ISSUER_TERMS_APPLY_TEXT_AND_LEARN_LINK.png.sha1
new file mode 100644
index 0000000..96799628
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SETTINGS_PAGE_CARD_BENEFITS_TOGGLE_SUBLABEL_WITH_ISSUER_TERMS_APPLY_TEXT_AND_LEARN_LINK.png.sha1
@@ -0,0 +1 @@
+6e07c7f205c8bcfe88fb18b167f6fab400b254af
\ No newline at end of file
diff --git a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/BaseNotificationManagerProxy.java b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/BaseNotificationManagerProxy.java
index 257c9e6..055d62a 100644
--- a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/BaseNotificationManagerProxy.java
+++ b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/BaseNotificationManagerProxy.java
@@ -20,7 +20,7 @@
  * Base interface for NofificationManagerProxy that only supports simple functionalities. Remove
  * this once AsyncNofificationManagerProxy is set to default.
  */
-@MockedInTests
+@MockedInTests // Needed due to R8's computeDelayedInterfaceMethodSyntheticBridges. b/147584922
 @NullMarked
 public interface BaseNotificationManagerProxy {
     /**
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
index 9c09b00..523c008 100644
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -1195,4 +1195,16 @@
   <message name="IDS_WEBSITE_SETTINGS_SERIAL_PORT_BLOCK" desc="Primary text corresponding to the block button in the serial port permission radio button group.">
     Don't allow sites to connect to serial ports
   </message>
+
+  <!-- Advanced protection -->
+  <message name="IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_TITLE" desc="Title for section on privacy settings page. Section displays information about how Android-OS advanced-protection 'on' setting affects Chrome settings. Section is shown for for a few days after the user has turned on advanced-protection in Android-OS-settings.">
+    Advanced Protection is on
+  </message>
+  <message name="IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_MESSAGE" desc="Displays information about how Android-OS advanced-protection 'on' setting affects Chrome settings.">
+Manage in <ph name="BEGIN_LINK1">&lt;link_android_advanced_protection&gt;</ph>Android settings<ph name="END_LINK1">&lt;/link_android_advanced_protection&gt;</ph>
+
+Advanced Protection controls these Chrome settings:
+• "Always use secure connections" is on.
+• "Javascript optimizer" is off. <ph name="BEGIN_LINK2">&lt;link_javascript_optimizer&gt;</ph>Manage Site exceptions<ph name="END_LINK2">&lt;/link_javascript_optimizer&gt;</ph>
+  </message>
 </grit-part>
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_MESSAGE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_MESSAGE.png.sha1
new file mode 100644
index 0000000..e1f2f8f0
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_MESSAGE.png.sha1
@@ -0,0 +1 @@
+e07a489e0b47a28bdf875f3594819ef25d916d8a
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_TITLE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_TITLE.png.sha1
new file mode 100644
index 0000000..e1f2f8f0
--- /dev/null
+++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_SETTINGS_PRIVACY_AND_SECURITY_ADVANCED_PROTECTION_SECTION_TITLE.png.sha1
@@ -0,0 +1 @@
+e07a489e0b47a28bdf875f3594819ef25d916d8a
\ No newline at end of file
diff --git a/components/browser_ui/styles/android/java/res/values/themes.xml b/components/browser_ui/styles/android/java/res/values/themes.xml
index 9c8a13e..afd6319 100644
--- a/components/browser_ui/styles/android/java/res/values/themes.xml
+++ b/components/browser_ui/styles/android/java/res/values/themes.xml
@@ -49,6 +49,7 @@
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_80</item>
         <item name="colorSurfaceVariant">@color/baseline_neutral_variant_30</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_dark</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_dark</item>
         <item name="colorPrimary">@color/baseline_primary_80</item>
         <item name="colorOnPrimary">@color/baseline_primary_20</item>
         <item name="colorPrimaryContainer">@color/baseline_primary_30</item>
diff --git a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
index 564206c..c65d721 100644
--- a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
+++ b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
@@ -226,4 +226,9 @@
     public static @ColorInt int getColorSurfaceContainerHighest(Context context) {
         return resolve(R.attr.colorSurfaceContainerHighest, context);
     }
+
+    /** Returns the semantic color values that correspond to colorSurfaceDim. */
+    public static @ColorInt int getColorSurfaceDim(Context context) {
+        return resolve(R.attr.colorSurfaceDim, context);
+    }
 }
diff --git a/components/browser_ui/theme/android/java/res/values-night/themes.xml b/components/browser_ui/theme/android/java/res/values-night/themes.xml
index 40fdacd..d561e158 100644
--- a/components/browser_ui/theme/android/java/res/values-night/themes.xml
+++ b/components/browser_ui/theme/android/java/res/values-night/themes.xml
@@ -25,6 +25,7 @@
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_80</item>
         <item name="colorOnSurfaceInverse">@color/baseline_neutral_20</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_dark</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_dark</item>
         <item name="colorSurfaceContainerLow">@color/gm3_baseline_surface_container_low_dark</item>
         <item name="colorSurfaceContainer">@color/gm3_baseline_surface_container_dark</item>
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_dark</item>
@@ -51,6 +52,7 @@
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_80</item>
         <item name="colorOnSurfaceInverse">@color/baseline_neutral_20</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_dark</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_dark</item>
         <item name="colorSurfaceContainerLow">@color/gm3_baseline_surface_container_low_dark</item>
         <item name="colorSurfaceContainer">@color/gm3_baseline_surface_container_dark</item>
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_dark</item>
@@ -77,6 +79,7 @@
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_80</item>
         <item name="colorOnSurfaceInverse">@color/baseline_neutral_20</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_dark</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_dark</item>
         <item name="colorSurfaceContainerLow">@color/gm3_baseline_surface_container_low_dark</item>
         <item name="colorSurfaceContainer">@color/gm3_baseline_surface_container_dark</item>
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_dark</item>
diff --git a/components/browser_ui/theme/android/java/res/values/themes.xml b/components/browser_ui/theme/android/java/res/values/themes.xml
index 45b2caa1..e7fc51b 100644
--- a/components/browser_ui/theme/android/java/res/values/themes.xml
+++ b/components/browser_ui/theme/android/java/res/values/themes.xml
@@ -31,6 +31,7 @@
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_light</item>
         <item name="colorSurfaceContainerHighest">@color/gm3_baseline_surface_container_highest_light</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_light</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_light</item>
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_30</item>
         <item name="colorOnSurfaceInverse">@color/baseline_neutral_95</item>
         <item name="colorOutline">@color/baseline_neutral_variant_50</item>
@@ -152,6 +153,7 @@
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_light</item>
         <item name="colorSurfaceContainerHighest">@color/gm3_baseline_surface_container_highest_light</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_light</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_light</item>
         <item name="colorOutline">@color/baseline_neutral_variant_50</item>
         <item name="colorError">@color/baseline_error_40</item>
 
@@ -228,6 +230,7 @@
         <item name="colorSurfaceContainerHigh">@color/gm3_baseline_surface_container_high_light</item>
         <item name="colorSurfaceContainerHighest">@color/gm3_baseline_surface_container_highest_light</item>
         <item name="colorSurfaceBright">@color/gm3_baseline_surface_bright_light</item>
+        <item name="colorSurfaceDim">@color/gm3_baseline_surface_dim_light</item>
         <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_30</item>
         <item name="colorOnSurfaceInverse">@color/baseline_neutral_95</item>
         <item name="colorOutline">@color/baseline_neutral_variant_50</item>
diff --git a/components/browser_ui/widget/android/java/res/values/dimens.xml b/components/browser_ui/widget/android/java/res/values/dimens.xml
index 5d90d69..8c1d6fe 100644
--- a/components/browser_ui/widget/android/java/res/values/dimens.xml
+++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -196,10 +196,10 @@
 
     <!-- Misc. app menu dimens -->
     <dimen name="app_menu_corner_size">24dp</dimen>
-    <dimen name="app_menu_shadow_length">@dimen/default_shadow_length_elev_2</dimen>
+    <dimen name="app_menu_shadow_length">6dp</dimen>
     <dimen name="app_menu_elevation">3dp</dimen>
-    <!-- app_menu_shadow_length + padding(8dp) -->
-    <dimen name="app_menu_padding">14dp</dimen>
+    <!-- app_menu_shadow_length + padding(4dp) -->
+    <dimen name="app_menu_padding">10dp</dimen>
 
     <!-- Empty view layout dimensions -->
     <dimen name="empty_state_text_width">341dp</dimen>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
index f6c7154..7157d63 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java
@@ -101,15 +101,15 @@
      * The modern way to handle back press. This method is only called when {@link
      * #getHandleBackPressChangedSupplier()} returns true; i.e. the back press has been intercepted
      * by chrome and the client must do something to consume the back press. So ideally, this is
-     * **always** expected to return {@link BackPressResult#SUCCESS}.
-     * A {@link BackPressResult#FAILURE} means the back press is intercepted but somehow the client
-     * does not consume; i.e. makes no change. This is usually because the client didn't update
-     * {@link #getHandleBackPressChangedSupplier()} such that this method is called even when the
-     * client does not want. A Failure means Chrome is now incorrectly working and should be
-     * fixed ASAP.
+     * **always** expected to return {@link BackPressResult#SUCCESS}. A {@link
+     * BackPressResult#FAILURE} means the back press is intercepted but somehow the client does not
+     * consume; i.e. makes no change. This is usually because the client didn't update {@link
+     * #getHandleBackPressChangedSupplier()} such that this method is called even when the client
+     * does not want. A Failure means Chrome is now incorrectly working and should be fixed ASAP.
      * The difference between this and the traditional way {@code boolean #onBackPressed} is that
      * the traditional one gives the client an opportunity to test if the client wants to intercept.
      * If it returns false, the tradition way will simply test other clients.
+     *
      * @return Whether the back press has been correctly handled.
      */
     default @BackPressResult int handleBackPress() {
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index d8b8b1b2..af05968 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "53.23",
-  "log_list_timestamp": "2025-04-24T12:54:26Z",
+  "version": "53.24",
+  "log_list_timestamp": "2025-04-25T12:54:02Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/collaboration/DEPS b/components/collaboration/DEPS
index 8513555..1c4b472 100644
--- a/components/collaboration/DEPS
+++ b/components/collaboration/DEPS
@@ -3,6 +3,7 @@
   "+components/data_sharing/test_support",
   "+components/keyed_service",
   "+components/prefs/pref_service.h",
+  "+components/prefs/pref_registry_simple.h",
   "+components/saved_tab_groups/public",
   "+components/saved_tab_groups/test_support",
   "+components/signin/public",
diff --git a/components/collaboration/public/BUILD.gn b/components/collaboration/public/BUILD.gn
index 17699ed..162f91f 100644
--- a/components/collaboration/public/BUILD.gn
+++ b/components/collaboration/public/BUILD.gn
@@ -106,6 +106,18 @@
   ]
 }
 
+source_set("prefs") {
+  sources = [
+    "pref_names.cc",
+    "pref_names.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/prefs",
+  ]
+}
+
 group("unit_tests") {
   testonly = true
 
diff --git a/components/collaboration/public/pref_names.cc b/components/collaboration/public/pref_names.cc
new file mode 100644
index 0000000..701b1adf
--- /dev/null
+++ b/components/collaboration/public/pref_names.cc
@@ -0,0 +1,19 @@
+// Copyright 2025 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/collaboration/public/pref_names.h"
+
+#include "components/prefs/pref_registry_simple.h"
+
+namespace collaboration::prefs {
+
+const char kSharedTabGroupsManagedAccountSetting[] =
+    "shared_tab_groups.managed_account_setting";
+
+void RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterIntegerPref(kSharedTabGroupsManagedAccountSetting,
+                                0 /* Allowed */);
+}
+
+}  // namespace collaboration::prefs
diff --git a/components/collaboration/public/pref_names.h b/components/collaboration/public/pref_names.h
new file mode 100644
index 0000000..7c2e708
--- /dev/null
+++ b/components/collaboration/public/pref_names.h
@@ -0,0 +1,20 @@
+// Copyright 2025 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_COLLABORATION_PUBLIC_PREF_NAMES_H_
+#define COMPONENTS_COLLABORATION_PUBLIC_PREF_NAMES_H_
+
+class PrefRegistrySimple;
+
+namespace collaboration::prefs {
+
+// Whether to allow shared tab group features for managed account.
+extern const char kSharedTabGroupsManagedAccountSetting[];
+
+// Registers user preferences related to permissions.
+void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+}  // namespace collaboration::prefs
+
+#endif  // COMPONENTS_COLLABORATION_PUBLIC_PREF_NAMES_H_
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index 013dafd2..f556735 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -213,16 +213,10 @@
 }
 
 bool CookieSettings::AreThirdPartyCookiesLimited() const {
-  // Checks whether we are in the limited state via Mode B or
-  // `CookieControlsMode`
-  return (tracking_protection_settings_ &&
-          tracking_protection_settings_->IsTrackingProtection3pcdEnabled() &&
-          !tracking_protection_settings_->AreAllThirdPartyCookiesBlocked()) ||
-         (static_cast<CookieControlsMode>(
-              pref_change_registrar_->prefs()->GetInteger(
-                  prefs::kCookieControlsMode)) ==
-              CookieControlsMode::kLimited &&
-          !is_incognito_);
+  // Checks whether we are in the limited state via Mode B.
+  return tracking_protection_settings_ &&
+         tracking_protection_settings_->IsTrackingProtection3pcdEnabled() &&
+         !tracking_protection_settings_->AreAllThirdPartyCookiesBlocked();
 }
 
 // TODO(crbug.com/40247160): Update to take in CookieSettingOverrides.
@@ -484,9 +478,8 @@
 void CookieSettings::OnCookiePreferencesChanged() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (base::FeatureList::IsEnabled(privacy_sandbox::kAddLimit3pcsSetting) ||
-      (tracking_protection_settings_ &&
-       tracking_protection_settings_->IsTrackingProtection3pcdEnabled())) {
+  if (tracking_protection_settings_ &&
+      tracking_protection_settings_->IsTrackingProtection3pcdEnabled()) {
     OnMitigationsEnabledChanged();
   }
 
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc
index 20e769f25..b74af1e 100644
--- a/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -812,13 +812,6 @@
 }
 
 TEST_P(AreThirdPartyCookiesLimited,
-       TrueWhenCookieControlsModePrefSetToLimited) {
-  prefs_.SetInteger(prefs::kCookieControlsMode,
-                    static_cast<int>(CookieControlsMode::kLimited));
-  EXPECT_TRUE(cookie_settings_->AreThirdPartyCookiesLimited());
-}
-
-TEST_P(AreThirdPartyCookiesLimited,
        FalseWhenCookieControlsModePrefSetToBlockThirdParty) {
   prefs_.SetInteger(prefs::kCookieControlsMode,
                     static_cast<int>(CookieControlsMode::kBlockThirdParty));
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index a016e13..d8dd401 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -106,6 +106,10 @@
 const base::FeatureParam<std::string> kIPHLensOverlayUrlPathMatchAllowPatterns{
     &feature_engagement::kIPHLensOverlayFeature,
     "x_url_path_match_allow_patterns", "[]"};
+const base::FeatureParam<std::string>
+    kIPHLensOverlayUrlForceAllowedUrlMatchPatterns{
+        &feature_engagement::kIPHLensOverlayFeature,
+        "x_url_forced_allowed_match_patterns", "[]"};
 const base::FeatureParam<std::string> kIPHLensOverlayUrlPathMatchBlockPatterns{
     &feature_engagement::kIPHLensOverlayFeature,
     "x_url_path_match_block_patterns", "[]"};
@@ -121,6 +125,9 @@
 BASE_FEATURE(kIPHPasswordsSavePrimingPromoFeature,
              "IPH_PasswordsSavePrimingPromo",
              base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kIPHPasswordsSaveRecoveryPromoFeature,
+             "IPH_PasswordsSaveRecoveryPromo",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kIPHPasswordsManagementBubbleAfterSaveFeature,
              "IPH_PasswordsManagementBubbleAfterSave",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index e4f31d2..3a438b5 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -65,6 +65,9 @@
     kIPHLensOverlayUrlPathMatchAllowPatterns;
 COMPONENT_EXPORT(FEATURE_ENGAGEMENT_FEATURE_CONSTANTS)
 extern const base::FeatureParam<std::string>
+    kIPHLensOverlayUrlForceAllowedUrlMatchPatterns;
+COMPONENT_EXPORT(FEATURE_ENGAGEMENT_FEATURE_CONSTANTS)
+extern const base::FeatureParam<std::string>
     kIPHLensOverlayUrlPathMatchBlockPatterns;
 COMPONENT_EXPORT(FEATURE_ENGAGEMENT_FEATURE_CONSTANTS)
 extern const base::FeatureParam<base::TimeDelta> kIPHLensOverlayDelayTime;
@@ -73,6 +76,7 @@
 FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHMerchantTrustFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHTabAudioMutingFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHPasswordsSavePrimingPromoFeature);
+FEATURE_CONSTANTS_DECLARE_FEATURE(kIPHPasswordsSaveRecoveryPromoFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(
     kIPHPasswordsManagementBubbleAfterSaveFeature);
 FEATURE_CONSTANTS_DECLARE_FEATURE(
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index b3d1d399..e46a934 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -219,6 +219,7 @@
     &kIPHMerchantTrustFeature,
     &kIPHTabAudioMutingFeature,
     &kIPHPasswordsSavePrimingPromoFeature,
+    &kIPHPasswordsSaveRecoveryPromoFeature,
     &kIPHPasswordsManagementBubbleAfterSaveFeature,
     &kIPHPasswordsManagementBubbleDuringSigninFeature,
     &kIPHPasswordsWebAppProfileSwitchFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index 3436823..a4aa756 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -378,6 +378,8 @@
 DEFINE_VARIATION_PARAM(kIPHMerchantTrustFeature, "IPH_MerchantTrust");
 DEFINE_VARIATION_PARAM(kIPHPasswordsSavePrimingPromoFeature,
                        "IPH_PasswordsSavePrimingPromo");
+DEFINE_VARIATION_PARAM(kIPHPasswordsSaveRecoveryPromoFeature,
+                       "IPH_PasswordsSaveRecoveryPromo");
 DEFINE_VARIATION_PARAM(kIPHPasswordsManagementBubbleAfterSaveFeature,
                        "IPH_PasswordsManagementBubbleAfterSave");
 DEFINE_VARIATION_PARAM(kIPHPasswordsManagementBubbleDuringSigninFeature,
diff --git a/components/live_caption/caption_controller_base.cc b/components/live_caption/caption_controller_base.cc
index 52cb4667..e9b858d 100644
--- a/components/live_caption/caption_controller_base.cc
+++ b/components/live_caption/caption_controller_base.cc
@@ -68,6 +68,12 @@
                          : std::make_unique<CaptionControllerDelgateImpl>()),
       pref_change_registrar_(std::make_unique<PrefChangeRegistrar>()) {
   pref_change_registrar_->Init(profile_prefs_);
+
+  // Turn off headless captioning when we first start, so that it does not get
+  // stuck on.
+  if (profile_prefs_->FindPreference(prefs::kHeadlessCaptionEnabled)) {
+    profile_prefs_->SetBoolean(prefs::kHeadlessCaptionEnabled, false);
+  }
 }
 
 void CaptionControllerBase::CreateUI() {
@@ -169,10 +175,8 @@
     const media::SpeechRecognitionResult& result) {
   bool success = false;
 
-  // Once there are more listeners than just the caption bubble controller, be
-  // sure that the caption bubble controller expects that it can return false
-  // and still get future calls.  Alternatively, cause it not to get future
-  // calls without stopping transcription if there are other listeners.
+  // Consider deleting the listener if it returns false.  It's unclear if
+  // `caption_bubble_controller_` would allow this, but maybe.
   for (auto& listener : listeners_) {
     success |= listener->OnTranscription(caption_bubble_context, result);
   }
diff --git a/components/live_caption/caption_controller_base.h b/components/live_caption/caption_controller_base.h
index b3d5868..e0987a43 100644
--- a/components/live_caption/caption_controller_base.h
+++ b/components/live_caption/caption_controller_base.h
@@ -129,7 +129,7 @@
   // about it.
   void RemoveListener(Listener*);
 
-  const raw_ptr<PrefService> profile_prefs_;
+  const raw_ptr<PrefService> profile_prefs_ = nullptr;
   const std::string application_locale_;
   const std::unique_ptr<Delegate> delegate_;
 
diff --git a/components/live_caption/caption_util.cc b/components/live_caption/caption_util.cc
index 51856708..9ead5d4 100644
--- a/components/live_caption/caption_util.cc
+++ b/components/live_caption/caption_util.cc
@@ -15,6 +15,7 @@
 #include "build/build_config.h"
 #include "components/live_caption/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "media/base/media_switches.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/native_theme/native_theme.h"
 
@@ -133,6 +134,10 @@
 #endif  // !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_ANDROID)
 }
 
+bool IsHeadlessCaptionFeatureSupported() {
+  return base::FeatureList::IsEnabled(media::kHeadlessLiveCaption);
+}
+
 std::string GetCaptionSettingsUrl() {
 #if BUILDFLAG(IS_CHROMEOS)
   return "chrome://os-settings/audioAndCaptions";
diff --git a/components/live_caption/caption_util.h b/components/live_caption/caption_util.h
index 7aef663..fd5a6ff 100644
--- a/components/live_caption/caption_util.h
+++ b/components/live_caption/caption_util.h
@@ -28,6 +28,9 @@
 // depend on e.g. Chrome feature flags, platform/OS, supported CPU instructions.
 bool IsLiveCaptionFeatureSupported();
 
+// Returns whether Headless Caption feature is enabled.
+bool IsHeadlessCaptionFeatureSupported();
+
 std::string GetCaptionSettingsUrl();
 
 }  // namespace captions
diff --git a/components/live_caption/live_caption_controller.h b/components/live_caption/live_caption_controller.h
index 43ce11f..b3b6acb 100644
--- a/components/live_caption/live_caption_controller.h
+++ b/components/live_caption/live_caption_controller.h
@@ -96,8 +96,8 @@
 
   void MaybeSetLiveCaptionLanguage();
 
-  raw_ptr<PrefService> global_prefs_;
-  raw_ptr<content::BrowserContext> browser_context_;
+  raw_ptr<PrefService> global_prefs_ = nullptr;
+  raw_ptr<content::BrowserContext> browser_context_ = nullptr;
   const std::unique_ptr<LiveCaptionBubbleSettings> caption_bubble_settings_;
 
   // Whether Live Caption is enabled.
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerCoordinator.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerCoordinator.java
index d7c2e7ab..0058d1b 100644
--- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerCoordinator.java
+++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerCoordinator.java
@@ -15,7 +15,6 @@
 import androidx.core.view.accessibility.AccessibilityEventCompat;
 
 import org.chromium.base.supplier.Supplier;
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.components.messages.MessageStateHandler.Position;
@@ -26,7 +25,6 @@
 import org.chromium.ui.util.RunnableTimer;
 
 /** Coordinator responsible for creating a message banner. */
-@MockedInTests
 @NullMarked
 class MessageBannerCoordinator {
     private final MessageBannerMediator mMediator;
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResult.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResult.java
index a9d2150..920ebc8 100644
--- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResult.java
+++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResult.java
@@ -12,7 +12,6 @@
 import org.jni_zero.CalledByNative;
 import org.jni_zero.NativeMethods;
 
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.components.omnibox.GroupsProto.GroupsInfo;
@@ -24,7 +23,6 @@
 import java.util.List;
 
 /** AutocompleteResult encompasses and manages autocomplete results. */
-@MockedInTests
 @NullMarked
 public class AutocompleteResult {
     @IntDef({
diff --git a/components/optimization_guide/core/feature_registry/feature_registration.cc b/components/optimization_guide/core/feature_registry/feature_registration.cc
index f401dd8a7..f4251c96 100644
--- a/components/optimization_guide/core/feature_registry/feature_registration.cc
+++ b/components/optimization_guide/core/feature_registry/feature_registration.cc
@@ -45,6 +45,10 @@
 const char kPasswordChangeSubmissionEnterprisePolicyAllowed[] =
     "optimization_guide.model_execution.password_change_submission_"
     "enterprise_policy_allowed";
+
+const char kNotificationContentDetectionEnterprisePolicyAllowed[] =
+    "optimization_guide.model_execution.notification_content_detection_"
+    "enterprise_policy_allowed";
 }  // namespace prefs
 
 namespace features {
@@ -76,6 +80,10 @@
              "PasswordChangeSubmissionMqlsLogging",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kNotificationContentDetectionMqlsLogging,
+             "NotificationContentDetectionMqlsLogging",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 }  // namespace features
 
 namespace {
@@ -237,6 +245,24 @@
           &features::kFormsClassificationsMqlsLogging, FeedbackUnspecified()));
 }
 
+void RegisterNotificationContentDetection() {
+  EnterprisePolicyPref enterprise_policy =
+      EnterprisePolicyRegistry::GetInstance().Register(
+          prefs::kNotificationContentDetectionEnterprisePolicyAllowed);
+  UserFeedbackCallback logging_callback =
+      base::BindRepeating([](proto::LogAiDataRequest& request_proto) {
+        return request_proto.notification_content_detection()
+            .quality()
+            .user_feedback();
+      });
+  auto metadata = std::make_unique<MqlsFeatureMetadata>(
+      "NotificationContentDetection",
+      proto::LogAiDataRequest::FeatureCase::kNotificationContentDetection,
+      enterprise_policy, &features::kNotificationContentDetectionMqlsLogging,
+      logging_callback);
+  MqlsFeatureRegistry::GetInstance().Register(std::move(metadata));
+}
+
 }  // anonymous namespace
 
 void RegisterGenAiFeatures(PrefRegistrySimple* pref_registry) {
@@ -254,6 +280,7 @@
     RegisterProductSpecifications();
     RegisterAutofillPredictions();
     RegisterPasswordChangeSubmission();
+    RegisterNotificationContentDetection();
     features_registered = true;
   }
   EnterprisePolicyRegistry::GetInstance().RegisterProfilePrefs(pref_registry);
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index 0d3bfd7..7d0a3c2 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit 0d3bfd72d3a7957232b6e5a7e9c67ea38775a661
+Subproject commit 7d0a3c2435fe79279ba2a404cecb24a8b6015e4a
diff --git a/components/optimization_guide/proto/features/common_quality_data.proto b/components/optimization_guide/proto/features/common_quality_data.proto
index 279c2c7a..314b5819 100644
--- a/components/optimization_guide/proto/features/common_quality_data.proto
+++ b/components/optimization_guide/proto/features/common_quality_data.proto
@@ -337,15 +337,15 @@
 
 // The interaction information for the content node. This indicates whether the
 // node is interactive and what type of interaction it supports.
-// Next ID: 13
+// Next ID: 14
 message InteractionInfo {
   // Set if the content node is scrollable.
   ScrollerInfo scroller_info = 12;
 
   // DEPRECATED: Use `scroller_info` instead.
-  bool scrolls_overflow_x = 1;
+  bool scrolls_overflow_x = 1 [deprecated = true];
 
-  bool scrolls_overflow_y = 2;
+  bool scrolls_overflow_y = 2 [deprecated = true];
 
   // Whether the content node is selectable.
   bool is_selectable = 3;
@@ -380,6 +380,17 @@
   // Note: The label may be an ancestor of the input node.
   int32 for_dom_node_id = 11;
 
+  // The z-order of the content node relative to other nodes in the same
+  // Document. A higher value means the node is in front of other nodes with
+  // lower values.
+  //
+  // Since all content within a Document is rendered as a single layer, nodes
+  // behind the iframe in the embedder draw behind all nodes inside the
+  // iframe's Document (similar for nodes on top of the iframe node).
+  //
+  // Note: This value is only set for nodes in the viewport.
+  int32 document_scoped_z_order = 13;
+
   reserved 8;
 }
 
@@ -442,7 +453,7 @@
 
   // DEPRECATED: Provides the URL for this image if available. For example,
   // data: URLs for inline images will be skipped.
-  string source_url = 3;
+  string source_url = 3 [deprecated = true];
 
   // Provides the source origin for the image.
   SecurityOrigin security_origin = 4;
@@ -545,7 +556,7 @@
 message IframeData {
   // DEPRECATED in favor of Security Origin in FrameData.
   // The URL of the iframe.
-  string url = 1;
+  string url = 1 [deprecated = true];
 
   FrameData frame_data = 3;
 
@@ -577,6 +588,8 @@
   // if paid content was checked.
   PaidContentMetadata paid_content_metadata = 6;
 
+  // DEPRECATED: USE `document_scoped_z_order` IN InteractionInfo INSTEAD.
+  //
   // The ordered list of DOM nodes which are eligible for hit testing in the
   // viewport. This list is ordered back-to-front, i.e., in the given list :
   // [0, 1], node 1 draws on top of node 0.
@@ -593,7 +606,7 @@
   // 2. If a node is eligible for hit testing and is in the viewport, but
   //    isn't actionable or satisfies any other criteria for generating a
   //    ContentNode, it will still be in this list.
-  repeated HitTestNode hit_test_nodes = 7;
+  repeated HitTestNode hit_test_nodes = 7 [deprecated = true];
 }
 
 // The interaction information for the frame. This is for interactions that
diff --git a/components/page_load_metrics/browser/page_load_tracker_unittest.cc b/components/page_load_metrics/browser/page_load_tracker_unittest.cc
index aaf56b6ee..a049caf 100644
--- a/components/page_load_metrics/browser/page_load_tracker_unittest.cc
+++ b/components/page_load_metrics/browser/page_load_tracker_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "components/page_load_metrics/browser/observers/page_load_metrics_observer_content_test_harness.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/fenced_frame_test_util.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/prerender_test_util.h"
@@ -251,8 +252,13 @@
   // disabled, the same RenderFrameHost will be reused and not be deleted.
 
 #if BUILDFLAG(IS_ANDROID)
+  // With default SiteInstanceGroup enabled, the navigations are all
+  // cross-SiteInstance, so there will be as many RenderFrameHost deletions as
+  // in the (non-Android) Site Isolation cases, which is possibly more than the
+  // RenderDocument cases. (Applies here and below.)
   if (content::WillSameSiteNavigationChangeRenderFrameHosts(
-          /*is_main_frame=*/true)) {
+          /*is_main_frame=*/true) ||
+      base::FeatureList::IsEnabled(features::kDefaultSiteInstanceGroups)) {
     EXPECT_EQ(1u, GetEvents().render_frame_deleted_count);
   } else {
     EXPECT_EQ(0u, GetEvents().render_frame_deleted_count);
@@ -280,6 +286,9 @@
   if (content::WillSameSiteNavigationChangeRenderFrameHosts(
           /*is_main_frame=*/true)) {
     EXPECT_EQ(1u, GetEvents().render_frame_deleted_count);
+  } else if (base::FeatureList::IsEnabled(
+                 features::kDefaultSiteInstanceGroups)) {
+    EXPECT_EQ(2u, GetEvents().render_frame_deleted_count);
   } else {
     EXPECT_EQ(0u, GetEvents().render_frame_deleted_count);
   }
@@ -296,6 +305,9 @@
   if (content::WillSameSiteNavigationChangeRenderFrameHosts(
           /*is_main_frame=*/true)) {
     EXPECT_EQ(2u, GetEvents().render_frame_deleted_count);
+  } else if (base::FeatureList::IsEnabled(
+                 features::kDefaultSiteInstanceGroups)) {
+    EXPECT_EQ(3u, GetEvents().render_frame_deleted_count);
   } else {
     EXPECT_EQ(1u, GetEvents().render_frame_deleted_count);
   }
@@ -310,6 +322,9 @@
   if (content::WillSameSiteNavigationChangeRenderFrameHosts(
           /*is_main_frame=*/true)) {
     EXPECT_EQ(3u, GetEvents().render_frame_deleted_count);
+  } else if (base::FeatureList::IsEnabled(
+                 features::kDefaultSiteInstanceGroups)) {
+    EXPECT_EQ(4u, GetEvents().render_frame_deleted_count);
   } else {
     EXPECT_EQ(2u, GetEvents().render_frame_deleted_count);
   }
diff --git a/components/passage_embeddings/passage_embeddings_service_controller.cc b/components/passage_embeddings/passage_embeddings_service_controller.cc
index c6e052a..492e842 100644
--- a/components/passage_embeddings/passage_embeddings_service_controller.cc
+++ b/components/passage_embeddings/passage_embeddings_service_controller.cc
@@ -143,6 +143,7 @@
 
 void PassageEmbeddingsServiceController::LoadModelsToService(
     mojo::PendingReceiver<mojom::PassageEmbedder> receiver,
+    base::ElapsedTimer service_launch_timer,
     mojom::PassageEmbeddingsLoadModelsParamsPtr params) {
   if (!service_remote_) {
     // Close the model files in a background thread.
@@ -150,20 +151,28 @@
         FROM_HERE, {base::MayBlock()},
         base::DoNothingWithBoundArgs(std::move(params)),
         base::BindOnce(&PassageEmbeddingsServiceController::OnLoadModelsResult,
-                       weak_ptr_factory_.GetWeakPtr(), /*success=*/false));
+                       weak_ptr_factory_.GetWeakPtr(),
+                       std::move(service_launch_timer), /*success=*/false));
     return;
   }
 
   service_remote_->LoadModels(
       std::move(params), MakeEmbedderParams(), std::move(receiver),
       base::BindOnce(&PassageEmbeddingsServiceController::OnLoadModelsResult,
-                     weak_ptr_factory_.GetWeakPtr()));
+                     weak_ptr_factory_.GetWeakPtr(),
+                     std::move(service_launch_timer)));
 }
 
-void PassageEmbeddingsServiceController::OnLoadModelsResult(bool success) {
+void PassageEmbeddingsServiceController::OnLoadModelsResult(
+    base::ElapsedTimer service_launch_timer,
+    bool success) {
   if (!success) {
     ResetEmbedderRemote();
+    return;
   }
+
+  base::UmaHistogramTimes("History.Embeddings.Embedder.LaunchDuration",
+                          service_launch_timer.Elapsed());
 }
 
 Embedder* PassageEmbeddingsServiceController::GetEmbedder() {
@@ -200,6 +209,7 @@
   }
 
   if (!embedder_remote_) {
+    base::ElapsedTimer service_launch_timer;
     MaybeLaunchService();
 
     auto receiver = embedder_remote_.BindNewPipeAndPassReceiver();
@@ -218,16 +228,19 @@
         base::BindOnce(&MakeModelParams, embeddings_model_path_, sp_model_path_,
                        model_metadata_->input_window_size()),
         base::BindOnce(&PassageEmbeddingsServiceController::LoadModelsToService,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(receiver)));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(receiver),
+                       std::move(service_launch_timer)));
   }
 
   pending_requests_.push_back(next_request_id_);
+  base::ElapsedTimer generate_embeddings_timer;
   embedder_remote_->GenerateEmbeddings(
       std::move(passages), PassagePriorityToMojom(priority),
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
           base::BindOnce(&PassageEmbeddingsServiceController::OnGotEmbeddings,
                          weak_ptr_factory_.GetWeakPtr(), next_request_id_,
-                         std::move(callback)),
+                         std::move(callback),
+                         std::move(generate_embeddings_timer), priority),
           std::vector<mojom::PassageEmbeddingsResultPtr>()));
   next_request_id_++;
 }
@@ -256,6 +269,8 @@
 void PassageEmbeddingsServiceController::OnGotEmbeddings(
     RequestId request_id,
     GetEmbeddingsResultCallback callback,
+    base::ElapsedTimer generate_embeddings_timer,
+    PassagePriority priority,
     std::vector<mojom::PassageEmbeddingsResultPtr> results) {
   // Mojo invokes the callbacks in the order in which `GenerateEmbeddings()` was
   // called. Therefore, `request_id` should be expected at the front of
@@ -272,6 +287,16 @@
   auto status = results.empty() ? ComputeEmbeddingsStatus::kExecutionFailure
                                 : ComputeEmbeddingsStatus::kSuccess;
   std::move(callback).Run(std::move(results), status);
+
+  if (status == ComputeEmbeddingsStatus::kSuccess) {
+    const base::TimeDelta duration = generate_embeddings_timer.Elapsed();
+    base::UmaHistogramTimes("History.Embeddings.TaskDuration", duration);
+    const char* const priority_histogram =
+        priority == kUserInitiated
+            ? "History.Embeddings.TaskDuration.UserInitiated"
+            : "History.Embeddings.TaskDuration.Passive";
+    base::UmaHistogramTimes(priority_histogram, duration);
+  }
 }
 
 }  // namespace passage_embeddings
diff --git a/components/passage_embeddings/passage_embeddings_service_controller.h b/components/passage_embeddings/passage_embeddings_service_controller.h
index 719da18..280d78c 100644
--- a/components/passage_embeddings/passage_embeddings_service_controller.h
+++ b/components/passage_embeddings/passage_embeddings_service_controller.h
@@ -9,6 +9,7 @@
 
 #include "base/callback_list.h"
 #include "base/observer_list.h"
+#include "base/timer/elapsed_timer.h"
 #include "base/types/optional_ref.h"
 #include "components/optimization_guide/core/model_info.h"
 #include "components/optimization_guide/proto/passage_embeddings_model_metadata.pb.h"
@@ -87,14 +88,18 @@
   // the service.
   void LoadModelsToService(
       mojo::PendingReceiver<mojom::PassageEmbedder> receiver,
+      base::ElapsedTimer service_launch_timer,
       mojom::PassageEmbeddingsLoadModelsParamsPtr params);
 
   // Called when an attempt to load models to service finishes.
-  void OnLoadModelsResult(bool success);
+  void OnLoadModelsResult(base::ElapsedTimer service_launch_timer,
+                          bool success);
 
   // Called when an attempt to generate embeddings finishes.
   void OnGotEmbeddings(RequestId request_id,
                        GetEmbeddingsResultCallback callback,
+                       base::ElapsedTimer generate_embeddings_timer,
+                       PassagePriority priority,
                        std::vector<mojom::PassageEmbeddingsResultPtr> results);
 
   // Version of the embeddings model.
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestParams.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestParams.java
index e35c0be..849f295 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestParams.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestParams.java
@@ -4,7 +4,6 @@
 
 package org.chromium.components.payments;
 
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
@@ -15,7 +14,6 @@
 import java.util.Map;
 
 /** The parameters of PaymentRequest specified by the merchant. */
-@MockedInTests // Tell R8 not to break the ability to mock the class.
 @NullMarked
 public interface PaymentRequestParams {
     /**
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/OsAdditionalSecurityPermissionProvider.java b/components/permissions/android/java/src/org/chromium/components/permissions/OsAdditionalSecurityPermissionProvider.java
index 5042f8a..42cdff1 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/OsAdditionalSecurityPermissionProvider.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/OsAdditionalSecurityPermissionProvider.java
@@ -5,6 +5,8 @@
 package org.chromium.components.permissions;
 
 import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
 
 import androidx.annotation.Nullable;
 
@@ -62,10 +64,25 @@
     }
 
     /**
+     * Returns non-black-and-white icon to use for operating-system-provided advanced protection
+     * branding.
+     */
+    @Nullable
+    public Drawable getColorfulAdvancedProtectionIcon(Context context) {
+        return null;
+    }
+
+    /**
      * Returns resource id for string to display to inform that strict-https-first-mode is enforced
      * by the operating-system-provided advanced protection setting.
      */
     public int getHttpsFirstModeEnforcedByAndroidAdvancedProtectionWarningResourceId() {
         return 0;
     }
+
+    /** Returns intent which launches OS-advanced-protection settings. */
+    @Nullable
+    public Intent getIntentForOsAdvancedProtectionSettings() {
+        return null;
+    }
 }
diff --git a/components/plus_addresses/resources/BUILD.gn b/components/plus_addresses/resources/BUILD.gn
index 97919428c..f4967148 100644
--- a/components/plus_addresses/resources/BUILD.gn
+++ b/components/plus_addresses/resources/BUILD.gn
@@ -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("//build/util/branding.gni")
+import("//build/config/chrome_build.gni")
 import("//components/vector_icons/vector_icons.gni")
 
 aggregate_vector_icons("plus_addresses_vector_icons") {
diff --git a/components/plus_addresses/resources/strings/BUILD.gn b/components/plus_addresses/resources/strings/BUILD.gn
index 9779f328..7abfa69 100644
--- a/components/plus_addresses/resources/strings/BUILD.gn
+++ b/components/plus_addresses/resources/strings/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/locales.gni")
-import("//build/util/branding.gni")
 import("//tools/grit/grit_rule.gni")
 
 if (is_android) {
diff --git a/components/policy/resources/templates/policies.yaml b/components/policy/resources/templates/policies.yaml
index 0a090ff..4d81d76 100644
--- a/components/policy/resources/templates/policies.yaml
+++ b/components/policy/resources/templates/policies.yaml
@@ -1356,6 +1356,7 @@
   1355: DefaultSmartCardConnectSetting
   1356: DeviceUserInitiatedFirmwareUpdatesEnabled
   1357: BuiltInAIAPIsEnabled
+  1358: TabGroupSharingSettings
 
 atomic_groups:
   1: Homepage
diff --git a/components/policy/resources/templates/policy_definitions/Sharing/.group.details.yaml b/components/policy/resources/templates/policy_definitions/Sharing/.group.details.yaml
new file mode 100644
index 0000000..b6be7cd
--- /dev/null
+++ b/components/policy/resources/templates/policy_definitions/Sharing/.group.details.yaml
@@ -0,0 +1,2 @@
+caption: Sharing Settings
+desc: Configure policies to control whether user is allowed to access shared data and features.
diff --git a/components/policy/resources/templates/policy_definitions/Sharing/TabGroupSharingSettings.yaml b/components/policy/resources/templates/policy_definitions/Sharing/TabGroupSharingSettings.yaml
new file mode 100644
index 0000000..b67ec0b
--- /dev/null
+++ b/components/policy/resources/templates/policy_definitions/Sharing/TabGroupSharingSettings.yaml
@@ -0,0 +1,37 @@
+caption: Tab group sharing settings
+desc: |-
+  Control whether an entreprise user can access tab group sharing feature in Chrome.
+
+  Tab group sharing feature allows user to share and collaborate in tab groups.
+
+  Setting the policy to 0 or not set, indicates that tab groups can be shared.
+  Setting the policy to 1, indicates that tab groups can not be shared.
+owners:
+- haileywang@google.com
+- file://components/collaboration/OWNERS
+future_on:
+- android
+- chrome.*
+- chrome_os
+- ios
+features:
+  cloud_only: true
+  dynamic_refresh: true
+  per_profile: true
+  user_only: true
+type: int-enum
+schema:
+  enum:
+  - 0
+  - 1
+  type: integer
+items:
+- caption: Use the Shared Tab Group feature.
+  name: UseSharedTabGroup
+  value: 0
+- caption: Do not use the Shared Tab Group feature.
+  name: DoNotUseSharedTabGroup
+  value: 1
+default: 0
+example_value: 0
+tags: []
diff --git a/components/policy/test/data/pref_mapping/TabGroupSharingSettings.json b/components/policy/test/data/pref_mapping/TabGroupSharingSettings.json
new file mode 100644
index 0000000..1e8a106
--- /dev/null
+++ b/components/policy/test/data/pref_mapping/TabGroupSharingSettings.json
@@ -0,0 +1,19 @@
+[
+  {
+    "os": [
+      "win",
+      "linux",
+      "mac",
+      "chromeos",
+      "android"
+    ],
+    "simple_policy_pref_mapping_test": {
+      "pref_name": "shared_tab_groups.managed_account_setting",
+      "pref_location": "user_profile",
+      "default_value": 0,
+      "values_to_test": [
+        0, 1
+      ]
+    }
+  }
+]
diff --git a/components/privacy_sandbox/privacy_sandbox_features.cc b/components/privacy_sandbox/privacy_sandbox_features.cc
index c147d9af..03301e5 100644
--- a/components/privacy_sandbox/privacy_sandbox_features.cc
+++ b/components/privacy_sandbox/privacy_sandbox_features.cc
@@ -123,10 +123,6 @@
              "RelatedWebsiteSetsDevUI",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kAddLimit3pcsSetting,
-             "AddLimit3pcsSetting",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kAlwaysBlock3pcsIncognito,
              "AlwaysBlock3pcsIncognito",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -207,10 +203,6 @@
              "PrivacySandboxAdTopicsContentParity",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kPrivacySandboxPrivacyPolicy,
-             "PrivacySandboxPrivacyPolicy",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kPrivacySandboxNoticeQueue,
              "PrivacySandboxNoticeQueue",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/privacy_sandbox/privacy_sandbox_features.h b/components/privacy_sandbox/privacy_sandbox_features.h
index 4d64654..c16606a 100644
--- a/components/privacy_sandbox/privacy_sandbox_features.h
+++ b/components/privacy_sandbox/privacy_sandbox_features.h
@@ -150,10 +150,6 @@
 BASE_DECLARE_FEATURE(kRelatedWebsiteSetsDevUI);
 
 // Privacy UX features start
-// See go/ps-privacy-ux-launch-features for more information
-
-COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES)
-BASE_DECLARE_FEATURE(kAddLimit3pcsSetting);
 
 COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES)
 BASE_DECLARE_FEATURE(kAlwaysBlock3pcsIncognito);
@@ -232,10 +228,6 @@
 COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES)
 BASE_DECLARE_FEATURE(kPrivacySandboxAdTopicsContentParity);
 
-// If true, provides a link to the Privacy Policy on the Topics Consent notice.
-COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES)
-BASE_DECLARE_FEATURE(kPrivacySandboxPrivacyPolicy);
-
 // If true, adds the privacy sandbox notice to product messaging controller
 // queue.
 COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES)
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
index 9d41f1d..bb8beed 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
@@ -201,11 +201,6 @@
       base::BindRepeating(
           &PrivacySandboxSettingsImpl::OnRelatedWebsiteSetsEnabledPrefChanged,
           base::Unretained(this)));
-  pref_change_registrar_.Add(
-      prefs::kCookieControlsMode,
-      base::BindRepeating(
-          &PrivacySandboxSettingsImpl::OnCookieControlsModePrefChanged,
-          base::Unretained(this)));
 }
 
 PrivacySandboxSettingsImpl::~PrivacySandboxSettingsImpl() = default;
@@ -894,23 +889,6 @@
   }
 }
 
-void PrivacySandboxSettingsImpl::OnCookieControlsModePrefChanged() {
-  if (!base::FeatureList::IsEnabled(privacy_sandbox::kAddLimit3pcsSetting)) {
-    return;
-  }
-
-  CookieControlsMode mode = static_cast<CookieControlsMode>(
-      pref_change_registrar_.prefs()->GetInteger(prefs::kCookieControlsMode));
-  if (mode == CookieControlsMode::kOff ||
-      mode == CookieControlsMode::kIncognitoOnly) {
-    return;
-  }
-
-  for (Observer& obs : observers_) {
-    obs.OnRelatedWebsiteSetsEnabledChanged(AreRelatedWebsiteSetsEnabled());
-  }
-}
-
 void PrivacySandboxSettingsImpl::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
@@ -1023,11 +1001,9 @@
 }
 
 bool PrivacySandboxSettingsImpl::AreRelatedWebsiteSetsEnabled() const {
-  if (tracking_protection_settings_->IsTrackingProtection3pcdEnabled() ||
-      base::FeatureList::IsEnabled(privacy_sandbox::kAddLimit3pcsSetting)) {
+  if (tracking_protection_settings_->IsTrackingProtection3pcdEnabled()) {
     return cookie_settings_->AreThirdPartyCookiesLimited();
   }
-
   return pref_service_->GetBoolean(
       prefs::kPrivacySandboxRelatedWebsiteSetsEnabled);
 }
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.h b/components/privacy_sandbox/privacy_sandbox_settings_impl.h
index ff2c081..9c097c07 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl.h
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.h
@@ -139,9 +139,6 @@
   // Called when the Related Website Sets enabled preference is changed.
   void OnRelatedWebsiteSetsEnabledPrefChanged();
 
-  // Called when the CookieControlsMode preference is changed.
-  void OnCookieControlsModePrefChanged();
-
   void SetTopicsDataAccessibleFromNow() const;
 
   // These values are persisted to logs. Entries should not be renumbered and
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
index dc97fac..2f2fcb9b 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
@@ -70,8 +70,6 @@
 // using enum content_settings::CookieControlsMode;
 constexpr auto kBlockThirdParty =
     content_settings::CookieControlsMode::kBlockThirdParty;
-constexpr auto kLimitedThirdParty =
-    content_settings::CookieControlsMode::kLimited;
 
 constexpr int kTestTaxonomyVersion = 1;
 
@@ -2020,7 +2018,7 @@
                              kM1FledgeEnabledUserPrefValue,
                              kM1AdMeasurementEnabledUserPrefValue},
            true},
-          {kCookieControlsModeUserPrefValue, kLimitedThirdParty},
+          {kTrackingProtection3pcdEnabledUserPrefValue, true},
           {kAttestationsMap,
            PrivacySandboxAttestationsMap{
                {net::SchemefulSite(enrollee_url),
@@ -2638,34 +2636,4 @@
                  {kIsSharedStorageBlockSiteSettingSpecific, &kFalse_}});
 }
 
-class PrivacySandboxSettingsCookieControlsModeTest
-    : public PrivacySandboxSettingsTest {
- public:
-  PrivacySandboxSettingsCookieControlsModeTest() {
-    feature_list_.InitWithFeatures(
-        {kAddLimit3pcsSetting},
-        {content_settings::features::kTrackingProtection3pcd});
-  }
-};
-
-TEST_F(PrivacySandboxSettingsCookieControlsModeTest,
-       OnRelatedWebsiteSetsEnabledChangedCalledWhen3pcBlockingChanges) {
-  prefs()->SetBoolean(prefs::kPrivacySandboxRelatedWebsiteSetsEnabled, false);
-
-  privacy_sandbox_test_util::MockPrivacySandboxObserver observer;
-  privacy_sandbox_settings()->AddObserver(&observer);
-
-  EXPECT_CALL(observer, OnRelatedWebsiteSetsEnabledChanged(/*enabled=*/true));
-  prefs()->SetInteger(
-      prefs::kCookieControlsMode,
-      static_cast<int>(content_settings::CookieControlsMode::kLimited));
-  testing::Mock::VerifyAndClearExpectations(&observer);
-
-  EXPECT_CALL(observer, OnRelatedWebsiteSetsEnabledChanged(/*enabled=*/false));
-  prefs()->SetInteger(
-      prefs::kCookieControlsMode,
-      static_cast<int>(content_settings::CookieControlsMode::kBlockThirdParty));
-  testing::Mock::VerifyAndClearExpectations(&observer);
-}
-
 }  // namespace privacy_sandbox
diff --git a/components/privacy_sandbox_chrome_strings.grdp b/components/privacy_sandbox_chrome_strings.grdp
index 6b81175..1deef416 100644
--- a/components/privacy_sandbox_chrome_strings.grdp
+++ b/components/privacy_sandbox_chrome_strings.grdp
@@ -46,7 +46,7 @@
   <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_3" desc="* This is 3 of 3 bullets. The label above the bullets is 'More about ad topics'. That string appears on the Consent page as an actionable label that leads the user to more information (this page) about the Ad topics setting. * 'How you can manage your data:': This string appears in bold and serves as a label for this bullet. * 'auto-deletes': this could also read 'Chrome also deletes...' We included the 'auto' to reinforce that this is part of a system and the deletion is done regularly. * 'As you keep browsing...': If a user visits similar sites every week for months on end, the same topic may appear on their list of topics and appear 'permanent'. This sentence explains why a topic might persist despite having just said that topics are deleted every 4 weeks. **** CONTEXT PRIVACY SANDBOX **** Chrome’s Privacy Sandbox initiative 1) deprecates third-party cookies in Chrome, 2) supports free and open content on the web (by finding better ways to support ads online), 3) while providing stronger privacy protections for users. You can see a high-level description of this public project at www.privacysanbox.com. " formatter_data="android_java">
     <ph name="BEGIN_BOLD">&lt;b&gt;</ph>How you can manage your data:<ph name="END_BOLD">&lt;/b&gt;</ph> Chrome auto-deletes topics that are older than 4 weeks. As you keep browsing, a topic might reappear on the list. You can also block topics you don’t want Chrome to share with sites and turn ad topics off at any time in Chrome settings.
   </message>
-  <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_LINK" desc="A sentence that appears alone at the bottom of the learn more page. It offers the user a path towards additional information about how Google protects their data." formatter_data="android_java">
+  <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_LINK" desc="A sentence that appears alone at the bottom of the learn more page. It offers the user a path towards additional information about how Google protects their data.">
     Learn more about how Google protects your data in our Privacy Policy.
   </message>
 
diff --git a/components/privacy_sandbox_strings.grd b/components/privacy_sandbox_strings.grd
index 8f1c7de9..f9ce85d 100644
--- a/components/privacy_sandbox_strings.grd
+++ b/components/privacy_sandbox_strings.grd
@@ -290,7 +290,7 @@
       <message name="IDS_SETTINGS_THIRD_PARTY_COOKIES_LINK_ROW_SUB_LABEL_LIMITED" desc="Sub-label for a button that links to the 'Third-party cookies' settings page when the user has third-party cookies limited.">
         Third-party cookies are limited
       </message>
-      <!-- Private State Tokens -->
+      <!-- PS Internals UI - Private State Tokens -->
       <message name="IDS_PRIVATE_STATE_TOKENS_HEADING_LABEL" desc="Title of the page that contains information about Private State Tokens." translateable="false">
         Private State Tokens
       </message>
@@ -314,9 +314,6 @@
       <message name="IDS_TRACKING_PROTECTION_BUBBLE_3PC_LIMITED_SUBTITLE" desc="The subtitle label for the third-party cookies item in User Bypass when 3PC are limited (i.e. blocked with mitigations).">
         Limited
       </message>
-      <message name="IDS_TRACKING_PROTECTION_BUBBLE_MANAGED_PROTECTIONS_LABEL" desc="The title label for the section in User Bypass containing managed Tracking Protection features." translateable="false">
-        Managed protections
-      </message>
       <message name="IDS_COOKIE_CONTROLS_BUBBLE_COOKIES_LIMITED_TITLE" desc="Title shown on the cookie controls bubble when third-party cookies are limited.">
         Third-party cookies limited
       </message>
@@ -325,33 +322,6 @@
       <message name="IDS_SETTINGS_THIRD_PARTY_COOKIES_ONLY_EXCEPTION_LABEL" desc="Label for an exception in the Tracking Protection exceptions list indicating that the exception only applies to third-party cookie blocking." translateable="false">
         Only applies to third-party cookie blocking
       </message>
-      <!-- ACT -->
-      <message name="IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LABEL" desc="Label for a toggle that controls the IP protection feature.">
-        Hide your IP address
-      </message>
-      <message name="IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LEARN_MORE_ARIA_LABEL" desc="Screenreader text for the help center article link in the sub-label text of the IP protection toggle.">
-       Learn more about hiding your IP address
-      </message>
-      <message name="IDS_SETTINGS_TRACKING_PROTECTION_FINGERPRINTING_PROTECTION_TOGGLE_LABEL" desc="Label for a toggle that controls the fingerprinting protection feature." translateable="false">
-        Limit digital fingerprinting
-      </message>
-      <message name="IDS_SETTINGS_TRACKING_PROTECTION_FINGERPRINTING_PROTECTION_TOGGLE_SUB_LABEL" desc="Sub-label for the fingerprinting protection toggle. Explains that the feature helps prevent sites from tracking users via identifiers related to their device or browser." translateable="false">
-        This setting makes it harder for sites to identify you using data about your device and browser, such as your device model or browser version
-      </message>
-
-      <if expr="_google_chrome">
-        <then>
-          <message name="IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL" desc="Sub-label for the IP protection toggle. Explains that the feature only works for signed-in users and that some traffic may be sent through privacy servers when the feature is on. Provides a link to a help center article.">
-              When you're signed in to Chrome, this setting helps keep your IP address private. If Chrome suspects a site may be tracking you, some of your traffic may be sent through privacy servers. Learn more about <ph name="LINK_BEGIN">&lt;a href="#" aria-label="$1" aria-description="$2" target="_blank"&gt;</ph>how IP protection works<ph name="LINK_END">&lt;/a&gt;</ph>
-          </message>
-        </then>
-        <else>
-          <message name="IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL" desc="Sub-label for the IP protection toggle. Explains that the feature only works for signed-in users and that some traffic may be sent through privacy servers when the feature is on. Provides a link to a help center article.">
-              When you're signed in to Chromium, this setting helps keep your IP address private. If Chromium suspects a site may be tracking you, some of your traffic may be sent through privacy servers. Learn more about <ph name="LINK_BEGIN">&lt;a href="#" aria-label="$1" aria-description="$2" target="_blank"&gt;</ph>how IP protection works<ph name="LINK_END">&lt;/a&gt;</ph>
-          </message>
-        </else>
-      </if>
-
       <!-- Privacy Sandbox Ads Notice -->
       <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_LEARN_MORE_V2_CLANK" desc="A sentence that appears alone at the bottom of the learn more page. It offers the user a path towards additional information about how Google protects their data." formatter_data="android_java">
         Learn more about how Google protects your data in our <ph name="BEGIN_LINK">&lt;link&gt;</ph>Privacy Policy<ph name="END_LINK">&lt;/link&gt;</ph>.
@@ -381,9 +351,6 @@
       <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_CLANK" desc="This string appears when the user expands on the “More about ad topics” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
         Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more in our Privacy Policy<ph name="END_LINK">&lt;/link&gt;</ph>
       </message>
-      <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK" desc="This string appears when the user expands on the “More about ad topics” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
-        Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. Learn more in our Privacy Policy.
-      </message>
       <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_3_V2" desc="This string appears when the user expands on the “More about ad topics” label. “Auto-deletes” is short for “automatically deletes”. “A topic” refers to one of the ad topics generated by Chrome. “Block topics” means a user can stop Chrome from sharing an ad topic with sites. " formatter_data="android_java">
         <ph name="BEGIN_BOLD">&lt;b&gt;</ph>How can you manage this data?<ph name="END_BOLD">&lt;/b&gt;</ph> Chrome auto-deletes topics that are older than 4 weeks. As you keep browsing, a topic might reappear on the list. You can also block topics you don't want Chrome to share with sites and turn ad topics off at any time in Chrome settings.
       </message>
@@ -520,9 +487,6 @@
       <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_1_DESCRIPTION_CLANK" desc="This string appears when the user expands on the “More about ad topics” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This string is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
         Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more in our Privacy Policy<ph name="END_LINK">&lt;/link&gt;</ph>
       </message>
-      <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_1_DESCRIPTION_NO_LINK" desc="This string appears when the user expands on the “More about ad topics” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This string is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
-        Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. Learn more in our Privacy Policy.
-      </message>
       <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_2" desc="This string appears when the user expands on the “More about ad topics” label and explains to the user how they can manage what data is used by websites. “Auto-deletes” is short for “automatically deletes”." formatter_data="android_java">
        <ph name="BEGIN_BOLD">&lt;b&gt;</ph>How can you manage this data?<ph name="END_BOLD">&lt;/b&gt;</ph> Chrome auto-deletes sites that are older than 30 days. A site you visit again might reappear on the list. You can also block a site from suggesting ads for you and turn site-suggested ads off at any time in Chrome settings.
       </message>
@@ -557,9 +521,6 @@
       <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_5_V2_CLANK" desc="This string appears when the user expands on the “More about ads in Chrome” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
         Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more in our Privacy Policy<ph name="END_LINK">&lt;/link&gt;</ph>
       </message>
-      <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_5_V2_NO_LINK" desc="This string appears when the user expands on the “More about ads in Chrome” label.  “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
-        Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. Learn more in our Privacy Policy.
-      </message>
       <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LAST_TEXT" desc="This string notifies users that they can make changes to their ad topics in the “ad privacy” section of settings." formatter_data="android_java">
         You can make changes in ad privacy settings
       </message>
@@ -812,9 +773,6 @@
       <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_CONTENT_PARITY" desc="This string appears at the bottom of the “Ad topics” settings page. “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language.">
         Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also store ad topics for longer than 4 weeks and combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. <ph name="BEGIN_LINK1">&lt;a href="#" id="$1" aria-description="$2" on-click="$3"&gt;</ph>Learn more in our Privacy Policy<ph name="LINK_END1">&lt;/a&gt;</ph>
       </message>
-      <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK_CONTENT_PARITY" desc="This string appears at the bottom of the “Ad topics” settings page. “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
-        Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also store ad topics for longer than 4 weeks and combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. Learn more in our Privacy Policy.
-      </message>
       <message name="IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_CONTENT_PARITY_CLANK" desc="This string appears at the bottom of the “Ad topics” settings page. “Sites” refers to websites that the user visits. The tone is informative. “Companies” refers to businesses or organizations that these websites belong to. This is intended to explain the possible user risks currently available with our evolving privacy-preserving technologies, in neutral language." formatter_data="android_java">
         Google requires companies to state publicly that they won't use this data to track you across sites. Some sites may use your activity to personalize your experience for more than just ads. They may also store ad topics for longer than 4 weeks and combine it with other information they already know about you. Companies are responsible for letting you know how they use your data. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Learn more in our Privacy Policy<ph name="END_LINK">&lt;/link&gt;</ph>.
       </message>
@@ -826,29 +784,7 @@
         Back
       </message>
 
-      <!-- Auto-verify (Anti-abuse) Page -->
-      <!-- TODO(b:330892594): Make auto-verify string updates translatable -->
-      <message name="IDS_SETTINGS_AUTO_VERIFY_DESCRIPTION" desc="" translateable="false">
-        Sites you visit (and their fraud prevention partners) can help prevent fraud by sharing small amounts of info, for example to verify you aren't a bot or to validate transactions
-      </message>
-      <message name="IDS_SETTINGS_AUTO_VERIFY_WHEN_ON_SECTION_ONE" desc="" translateable="false">
-        As you keep browsing, sites can check with Chrome and verify with a previous site you visited that you're likely a real person
-      </message>
-      <message name="IDS_SETTINGS_AUTO_VERIFY_WHEN_ON_SECTION_TWO" desc="" translateable="false">
-        Browsing is faster because a site is less likely to ask you to verify you're a real person
-      </message>
-      <message name="IDS_SETTINGS_AUTO_VERIFY_THINGS_TO_CONSIDER" desc="" translateable="false">
-        This setting works without identifying you or allowing sites to see your browsing history, though sites can share a small amount of info as part of the verification
-      </message>
-      <message name="IDS_SETTINGS_AUTO_VERIFY_THINGS_TO_CONSIDER_LEARN_MORE" desc="" translateable="false">
-        Learn more about <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1" aria-label="$2" aria-description="$3"&gt;</ph>how auto-verify works<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
-      </message>
-      <!-- TODO(b:330892146): Update screenreader text after confirming with content team -->
-      <message name="IDS_SETTINGS_AUTO_VERIFY_THINGS_TO_CONSIDER_LEARN_MORE_ARIA_LABEL" desc="Screenreader text for the help center article link in the things to consider section of the auto-verify settings." translateable="false">
-        Learn more about how auto-verify works
-      </message>
-
-      <!-- Cookies Settings - Settings P1 -->
+      <!-- 3PC Settings -->
       <message name="IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_SETTINGS_ALLOW_BULLET_ONE" desc="This text is for a bullet that provides detail about the first setting option. It describes the primary privacy and content impacts of selecting the “Allow third-party cookies” option." formatter_data="android_java">
         Sites can use third-party cookies to personalize content and ads, and learn about actions you take on other sites
       </message>
diff --git a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK.png.sha1
deleted file mode 100644
index 6c6bed5..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8248e5f94c5d217bb9935154fd3524f478ac178b
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK_CONTENT_PARITY.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK_CONTENT_PARITY.png.sha1
deleted file mode 100644
index 1d16f11..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2_DESCRIPTION_NO_LINK_CONTENT_PARITY.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8df469de7881f813006d9b100b54f90a277dd36a
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_1_DESCRIPTION_NO_LINK.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_1_DESCRIPTION_NO_LINK.png.sha1
deleted file mode 100644
index e754ca7..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_SITE_SUGGESTED_ADS_LEARN_MORE_BULLET_1_DESCRIPTION_NO_LINK.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a3b1e13264b52533db5b38f8cbee58486241f33c
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_5_V2_NO_LINK.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_5_V2_NO_LINK.png.sha1
deleted file mode 100644
index a7cc5cd..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_5_V2_NO_LINK.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-581cb43d9c42b196b96dff8e4ffc811c05793b37
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LABEL.png.sha1
deleted file mode 100644
index 76af5874..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LABEL.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-78a61f2135394de2907083f444db8727795f55db
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LEARN_MORE_ARIA_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LEARN_MORE_ARIA_LABEL.png.sha1
deleted file mode 100644
index 6b0b99fd0..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_LEARN_MORE_ARIA_LABEL.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3c3e5f816cd9864badb91af786faec1b83cf297d
\ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL.png.sha1
deleted file mode 100644
index cf77ae7..0000000
--- a/components/privacy_sandbox_strings_grd/IDS_SETTINGS_TRACKING_PROTECTION_IP_PROTECTION_TOGGLE_SUB_LABEL.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-308f36c4a65b995b3131d2e8fd85e0245fcede60
\ No newline at end of file
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index a1f40cc7..f1a9b942 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -301,6 +301,11 @@
              "ReportNotificationContentDetectionData",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+constexpr base::FeatureParam<int> kReportNotificationContentDetectionDataRate{
+    &kReportNotificationContentDetectionData,
+    "ReportNotificationContentDetectionDataRate",
+    /*default_value=*/100};
+
 BASE_FEATURE(kSafeBrowsingDailyPhishingReportsLimit,
              "SafeBrowsingDailyPhishingReportsLimit",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h
index 535e957c..c9936d8 100644
--- a/components/safe_browsing/core/common/features.h
+++ b/components/safe_browsing/core/common/features.h
@@ -288,6 +288,12 @@
 // Enables reporting notification contents and metadata to the server, upon user
 // consent.
 BASE_DECLARE_FEATURE(kReportNotificationContentDetectionData);
+// Determines how often we should log the reported notification to the server.
+// For the default rate of 100, the notification will always be reported where a
+// rate of 0 means there is no reporting. This will help limit data volume, if
+// it becomes excessive.
+extern const base::FeatureParam<int>
+    kReportNotificationContentDetectionDataRate;
 
 // Enables client side phishing daily reports limit to be configured via Finch
 // for ESB and SBER users
diff --git a/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java b/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java
index 31ee2a8..639170d3 100644
--- a/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java
+++ b/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java
@@ -6,7 +6,6 @@
 import org.jni_zero.CalledByNative;
 import org.jni_zero.NativeMethods;
 
-import org.chromium.build.annotations.MockedInTests;
 import org.chromium.build.annotations.NullMarked;
 
 import java.util.Locale;
@@ -16,7 +15,6 @@
  * from native side. Any class uses this need to register a {@link TemplateUrlServiceObserver} on
  * {@link TemplatUrlService} to listen the native changes in case the native pointer is destroyed.
  */
-@MockedInTests
 @NullMarked
 public class TemplateUrl {
     private final long mTemplateUrlPtr;
diff --git a/components/supervised_user/core/browser/supervised_user_metrics_service.cc b/components/supervised_user/core/browser/supervised_user_metrics_service.cc
index 4e23af20..6f16ec2 100644
--- a/components/supervised_user/core/browser/supervised_user_metrics_service.cc
+++ b/components/supervised_user/core/browser/supervised_user_metrics_service.cc
@@ -67,21 +67,18 @@
 
 void SupervisedUserMetricsService::CheckForNewDay() {
   int day_id = pref_service_->GetInteger(prefs::kSupervisedUserMetricsDayId);
-  base::Time now = base::Time::Now();
+  int current_day_id = GetDayId(base::Time::Now());
   // The OnNewDay() event can fire sooner or later than 24 hours due to clock or
   // time zone changes.
-  bool should_update_day_id = false;
-  if (day_id < GetDayId(now)) {
-    if (url_filter_->EmitURLFilterMetrics()) {
-      should_update_day_id = true;
-    }
+  if (day_id < current_day_id) {
+    bool should_update_day_id = url_filter_->EmitURLFilterMetrics();
     if (extensions_metrics_delegate_ &&
         extensions_metrics_delegate_->RecordExtensionsMetrics()) {
       should_update_day_id = true;
     }
     if (should_update_day_id) {
       pref_service_->SetInteger(prefs::kSupervisedUserMetricsDayId,
-                                GetDayId(now));
+                                current_day_id);
     }
   }
 }
diff --git a/components/supervised_user/core/browser/supervised_user_service.cc b/components/supervised_user/core/browser/supervised_user_service.cc
index 7d1013b..501b85a 100644
--- a/components/supervised_user/core/browser/supervised_user_service.cc
+++ b/components/supervised_user/core/browser/supervised_user_service.cc
@@ -166,13 +166,8 @@
       user_prefs, std::move(url_filter_delegate));
 }
 
-void SupervisedUserService::SetActive(bool active) {
-  if (active_ == active) {
-    return;
-  }
-  active_ = active;
-
-  settings_service_->SetActive(active_);
+void SupervisedUserService::SetSettingsServiceActive(bool active) {
+  settings_service_->SetActive(active);
 
   // Trigger a sync reconfig to enable/disable the right SU data types.
   // The logic to do this lives in the
@@ -185,15 +180,27 @@
     // immediately releasing it again (via the temporary unique_ptr going away).
     std::ignore = sync_service_->GetSetupInProgressHandle();
   }
+}
 
+void SupervisedUserService::SetActive(bool active) {
+  if (active_ == active) {
+    return;
+  }
+  active_ = active;
+
+  // If-else branches should work in Li-Fo manner.
   if (active_) {
-    // Initialize SafeSites URL checker.
+    // 1. Activate the subservice.
+    SetSettingsServiceActive(active_);
+
+    // 2. Initialize SafeSites URL checker.
     GetURLFilter()->SetURLCheckerClient(
         std::make_unique<KidsChromeManagementURLCheckerClient>(
             identity_manager_, url_loader_factory_,
             platform_delegate_->GetCountryCode(),
             platform_delegate_->GetChannel()));
 
+    // 3. Start observing prefs.
     pref_change_registrar_.Add(
         prefs::kDefaultSupervisedUserFilteringBehavior,
         base::BindRepeating(
@@ -218,21 +225,29 @@
                               base::Unretained(this)));
     }
 
+    // 4. Initialize approvals.
     remote_web_approvals_manager_.AddApprovalRequestCreator(
         std::make_unique<PermissionRequestCreatorImpl>(identity_manager_,
                                                        url_loader_factory_));
 
-    // Initialize the filter.
+    // 5. Initialize the filter.
     OnDefaultFilteringBehaviorChanged();
     OnSafeSitesSettingChanged();
     UpdateManualHosts();
     UpdateManualURLs();
-
     GetURLFilter()->SetFilterInitialized(true);
     current_web_filter_type_ = url_filter_->GetWebFilterType();
   } else {
+    // 5. Destroy filter.
+    url_filter_->Clear();
+    for (SupervisedUserServiceObserver& observer : observer_list_) {
+      observer.OnURLFilterChanged();
+    }
+
+    // 4. Destroy approvals.
     remote_web_approvals_manager_.ClearApprovalRequestsCreators();
 
+    // 3. Stop observing prefs.
     pref_change_registrar_.Remove(
         prefs::kDefaultSupervisedUserFilteringBehavior);
     pref_change_registrar_.Remove(prefs::kSupervisedUserSafeSites);
@@ -242,10 +257,9 @@
       pref_change_registrar_.Remove(pref);
     }
 
-    url_filter_->Clear();
-    for (SupervisedUserServiceObserver& observer : observer_list_) {
-      observer.OnURLFilterChanged();
-    }
+    // 2. SafeSites URL checker is gone with filter from 5.
+    // 1. Shut down settings.
+    SetSettingsServiceActive(active_);
   }
 }
 
@@ -287,8 +301,7 @@
   }
 
   WebFilterType filter_type = url_filter_->GetWebFilterType();
-  if (!AreWebFilterPrefsDefault(*user_prefs_) &&
-      current_web_filter_type_ != filter_type) {
+  if (current_web_filter_type_ != filter_type) {
     url_filter_->ReportWebFilterTypeMetrics();
     current_web_filter_type_ = filter_type;
   }
@@ -296,8 +309,7 @@
 
 void SupervisedUserService::OnSafeSitesSettingChanged() {
   WebFilterType filter_type = url_filter_->GetWebFilterType();
-  if (!AreWebFilterPrefsDefault(*user_prefs_) &&
-      current_web_filter_type_ != filter_type) {
+  if (current_web_filter_type_ != filter_type) {
     url_filter_->ReportWebFilterTypeMetrics();
     current_web_filter_type_ = filter_type;
   }
@@ -311,13 +323,11 @@
     DCHECK(it.second.is_bool());
     host_map[it.first] = it.second.GetIfBool().value_or(false);
   }
-  url_filter_->SetManualHosts(std::move(host_map));
 
-  for (SupervisedUserServiceObserver& observer : observer_list_) {
-    observer.OnURLFilterChanged();
-  }
-
-  if (!AreWebFilterPrefsDefault(*user_prefs_)) {
+  if (url_filter_->SetManualHosts(std::move(host_map))) {
+    for (SupervisedUserServiceObserver& observer : observer_list_) {
+      observer.OnURLFilterChanged();
+    }
     url_filter_->ReportManagedSiteListMetrics();
   }
 }
@@ -330,13 +340,11 @@
     DCHECK(it.second.is_bool());
     url_map[GURL(it.first)] = it.second.GetIfBool().value_or(false);
   }
-  url_filter_->SetManualURLs(std::move(url_map));
 
-  for (SupervisedUserServiceObserver& observer : observer_list_) {
-    observer.OnURLFilterChanged();
-  }
-
-  if (!AreWebFilterPrefsDefault(*user_prefs_)) {
+  if (url_filter_->SetManualURLs(std::move(url_map))) {
+    for (SupervisedUserServiceObserver& observer : observer_list_) {
+      observer.OnURLFilterChanged();
+    }
     url_filter_->ReportManagedSiteListMetrics();
   }
 }
diff --git a/components/supervised_user/core/browser/supervised_user_service.h b/components/supervised_user/core/browser/supervised_user_service.h
index 9776d05..373749a 100644
--- a/components/supervised_user/core/browser/supervised_user_service.h
+++ b/components/supervised_user/core/browser/supervised_user_service.h
@@ -187,6 +187,8 @@
 
   void SetActive(bool active);
 
+  void SetSettingsServiceActive(bool active);
+
   void OnCustodianInfoChanged();
 
   void OnSupervisedUserIdChanged();
@@ -243,8 +245,10 @@
   // WebFilterType::kCertainSites, both
   // prefs::kDefaultSupervisedUserFilteringBehavior and
   // prefs::kSupervisedUserSafeSites change. Uses this member to avoid duplicate
-  // reports. Initialized in the SetActive().
-  WebFilterType current_web_filter_type_ = WebFilterType::kMaxValue;
+  // reports. Initialized in the SetActive(). This default value is derived from
+  // default value of both prefs.
+  WebFilterType current_web_filter_type_ =
+      WebFilterType::kTryToBlockMatureSites;
 
   base::WeakPtrFactory<SupervisedUserService> weak_ptr_factory_{this};
 };
diff --git a/components/supervised_user/core/browser/supervised_user_url_filter.cc b/components/supervised_user/core/browser/supervised_user_url_filter.cc
index 32140d3..c1164be 100644
--- a/components/supervised_user/core/browser/supervised_user_url_filter.cc
+++ b/components/supervised_user/core/browser/supervised_user_url_filter.cc
@@ -4,6 +4,7 @@
 
 #include "components/supervised_user/core/browser/supervised_user_url_filter.h"
 
+#include <algorithm>
 #include <memory>
 #include <optional>
 #include <string>
@@ -154,6 +155,14 @@
   return base::BindOnce(&WrappedCallbackWithMetrics, std::move(callback),
                         context, transition_type);
 }
+
+// Returns true when two OrderedContainers have the same values.
+template <typename OrderedContainer>
+bool ContainersAreEqual(const OrderedContainer& lhs,
+                        const OrderedContainer& rhs) {
+  return lhs.size() == rhs.size() &&
+         std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
 }  // namespace
 
 supervised_user::FilteringBehavior GetBehaviorFromSafeSearchClassification(
@@ -640,29 +649,46 @@
   return default_behavior_;
 }
 
-void SupervisedUserURLFilter::SetManualHosts(
+bool SupervisedUserURLFilter::SetManualHosts(
     std::map<std::string, bool> host_map) {
   // TODO(b/305229682): Update this method to received the two
   // parental lists.
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  blocked_host_list_.clear();
-  allowed_host_list_.clear();
+
+  std::set<std::string> new_blocked_host_list;
+  std::set<std::string> new_allowed_host_list;
+
   for (const auto& host_entry : host_map) {
     if (host_entry.second) {
-      allowed_host_list_.emplace(host_entry.first);
+      new_allowed_host_list.emplace(host_entry.first);
     } else {
-      blocked_host_list_.emplace(host_entry.first);
+      new_blocked_host_list.emplace(host_entry.first);
     }
   }
+
+  if (ContainersAreEqual(blocked_host_list_, new_blocked_host_list) &&
+      ContainersAreEqual(allowed_host_list_, new_allowed_host_list)) {
+    return false;
+  }
+
+  blocked_host_list_ = std::move(new_blocked_host_list);
+  allowed_host_list_ = std::move(new_allowed_host_list);
+  return true;
 }
 
 bool SupervisedUserURLFilter::IsManualHostsEmpty() const {
   return allowed_host_list_.empty() && blocked_host_list_.empty();
 }
 
-void SupervisedUserURLFilter::SetManualURLs(std::map<GURL, bool> url_map) {
+bool SupervisedUserURLFilter::SetManualURLs(std::map<GURL, bool> url_map) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (ContainersAreEqual(url_map_, url_map)) {
+    return false;
+  }
+
   url_map_ = std::move(url_map);
+  return true;
 }
 
 void SupervisedUserURLFilter::Clear() {
diff --git a/components/supervised_user/core/browser/supervised_user_url_filter.h b/components/supervised_user/core/browser/supervised_user_url_filter.h
index d165f33..b8b3496f 100644
--- a/components/supervised_user/core/browser/supervised_user_url_filter.h
+++ b/components/supervised_user/core/browser/supervised_user_url_filter.h
@@ -206,13 +206,19 @@
 
   FilteringBehavior GetDefaultFilteringBehavior() const;
 
-  // Sets the set of manually allowed or blocked hosts.
-  void SetManualHosts(std::map<std::string, bool> host_map);
+  // Sets the set of manually allowed or blocked hosts. Returns true if new
+  // value held different value from existing values.
+  // TODO(crbug.com/413654322): change name to reflect that the operation is
+  // no-op if new value is equal to current one.
+  bool SetManualHosts(std::map<std::string, bool> host_map);
 
   bool IsManualHostsEmpty() const;
 
-  // Sets the set of manually allowed or blocked URLs.
-  void SetManualURLs(std::map<GURL, bool> url_map);
+  // Sets the set of manually allowed or blocked URLs. Returns true if new value
+  // held different value from existing values.
+  // TODO(crbug.com/413654322): change name to reflect that the operation is
+  // no-op if new value is equal to current one.
+  bool SetManualURLs(std::map<GURL, bool> url_map);
 
   // Removes all filter entries, clears the async checker if present, and resets
   // the default behavior to "allow".
diff --git a/components/supervised_user/core/browser/supervised_user_utils.cc b/components/supervised_user/core/browser/supervised_user_utils.cc
index 854da880..63b8cda 100644
--- a/components/supervised_user/core/browser/supervised_user_utils.cc
+++ b/components/supervised_user/core/browser/supervised_user_utils.cc
@@ -313,14 +313,6 @@
   return url_matcher::util::Normalize(effective_url);
 }
 
-bool AreWebFilterPrefsDefault(const PrefService& pref_service) {
-  return pref_service
-             .FindPreference(prefs::kDefaultSupervisedUserFilteringBehavior)
-             ->IsDefaultValue() ||
-         pref_service.FindPreference(prefs::kSupervisedUserSafeSites)
-             ->IsDefaultValue();
-}
-
 bool EmitLogRecordHistograms(
     const std::vector<FamilyLinkUserLogRecord>& records) {
   bool did_emit_histogram = false;
diff --git a/components/supervised_user/core/browser/supervised_user_utils.h b/components/supervised_user/core/browser/supervised_user_utils.h
index ba1c278..54b4648 100644
--- a/components/supervised_user/core/browser/supervised_user_utils.h
+++ b/components/supervised_user/core/browser/supervised_user_utils.h
@@ -20,7 +20,6 @@
 #include "url/gurl.h"
 
 class GURL;
-class PrefService;
 
 namespace supervised_user {
 
@@ -100,9 +99,6 @@
 // Strips user-specific tokens in a URL to generalize it.
 GURL NormalizeUrl(const GURL& url);
 
-// Check if web filtering prefs are set to default values.
-bool AreWebFilterPrefsDefault(const PrefService& pref_service);
-
 // Given a list of records that map to the supervision state of primary
 // accounts on the user's device, emits metrics that reflect the FamilyLink
 // settings of the user.
diff --git a/components/sync_preferences/common_syncable_prefs_database.cc b/components/sync_preferences/common_syncable_prefs_database.cc
index c7aae364..09626e0 100644
--- a/components/sync_preferences/common_syncable_prefs_database.cc
+++ b/components/sync_preferences/common_syncable_prefs_database.cc
@@ -7,6 +7,8 @@
 #include <string_view>
 
 #include "base/containers/fixed_flat_map.h"
+#include "base/containers/fixed_flat_set.h"
+#include "base/feature_list.h"
 #include "build/build_config.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
@@ -27,6 +29,7 @@
 #include "components/search_engines/search_engines_pref_names.h"
 #include "components/sharing_message/pref_names.h"
 #include "components/sync/base/data_type.h"
+#include "components/sync/base/features.h"
 #include "components/translate/core/browser/translate_pref_names.h"
 #include "components/translate/core/browser/translate_prefs.h"
 #include "components/variations/service/google_groups_manager_prefs.h"
@@ -128,6 +131,8 @@
   kAutofillBnplEnabled = 81,
   kAutofillHasSeenBnpl = 82,
   kAutomaticPasskeyUpgrades = 83,
+  kSyncablePriorityPrefForTesting = 84,               // For tests.
+  kSyncableAlwaysSyncingPriorityPrefForTesting = 85,  // For tests.
   // See components/sync_preferences/README.md about adding new entries here.
   // vvvvv IMPORTANT! vvvvv
   // Note to the reviewer: IT IS YOUR RESPONSIBILITY to ensure that new syncable
@@ -343,6 +348,14 @@
           PrefSensitivity::kNone, MergeBehavior::kNone}},
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
         // BUILDFLAG(IS_CHROMEOS)
+        {kSyncablePriorityPrefForTesting,
+         {syncable_prefs_ids::kSyncablePriorityPrefForTesting,
+          syncer::PRIORITY_PREFERENCES, PrefSensitivity::kNone,
+          MergeBehavior::kNone}},
+        {kSyncableAlwaysSyncingPriorityPrefForTesting,
+         {syncable_prefs_ids::kSyncableAlwaysSyncingPriorityPrefForTesting,
+          syncer::PRIORITY_PREFERENCES, PrefSensitivity::kNone,
+          MergeBehavior::kNone}},
     });
 
 }  // namespace
@@ -363,4 +376,18 @@
           kCommonSyncablePrefsAllowlist.end()};
 }
 
+bool CommonSyncablePrefsDatabase::IsPreferenceAlwaysSyncing(
+    std::string_view pref_name) const {
+  CHECK(base::FeatureList::IsEnabled(
+      syncer::kSyncSupportAlwaysSyncingPriorityPreferences));
+  // TODO(crbug.com/412602018): Consider renaming and using the
+  // `PrefSensitivity` enum instead, since it currently helps with something
+  // similar in regards to history opt-in and the options would be mutually
+  // exclusive.
+  static constexpr auto kAlwaysSyncingPrefsAllowlist =
+      base::MakeFixedFlatSet<std::string_view>(
+          {kSyncableAlwaysSyncingPriorityPrefForTesting});
+  return kAlwaysSyncingPrefsAllowlist.contains(pref_name);
+}
+
 }  // namespace sync_preferences
diff --git a/components/sync_preferences/common_syncable_prefs_database.h b/components/sync_preferences/common_syncable_prefs_database.h
index d5a03bb..2c3520b 100644
--- a/components/sync_preferences/common_syncable_prefs_database.h
+++ b/components/sync_preferences/common_syncable_prefs_database.h
@@ -20,6 +20,10 @@
     "syncable-mergeable-list-test-preference";
 inline constexpr char kSyncableHistorySensitiveListPrefForTesting[] =
     "syncable-history-sensitive-list-test-preference";
+inline constexpr char kSyncablePriorityPrefForTesting[] =
+    "syncable-test-priority-preference";
+inline constexpr char kSyncableAlwaysSyncingPriorityPrefForTesting[] =
+    "syncable-always-syncing-test-priority-preference";
 
 // This class provides an implementation for SyncablePrefsDatabase for common
 // syncable preferences, i.e. preferences which are shared between all
@@ -33,6 +37,8 @@
 
   std::map<std::string_view, SyncablePrefMetadata> GetAllSyncablePrefsForTest()
       const;
+
+  bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const override;
 };
 
 }  // namespace sync_preferences
diff --git a/components/sync_preferences/syncable_prefs_database.h b/components/sync_preferences/syncable_prefs_database.h
index f8dfbbac..b66bb35 100644
--- a/components/sync_preferences/syncable_prefs_database.h
+++ b/components/sync_preferences/syncable_prefs_database.h
@@ -112,6 +112,10 @@
   // Return true if `pref_name` is a mergeable syncable preference.
   // Note: `pref_name` must be syncable.
   bool IsPreferenceMergeable(std::string_view pref_name) const;
+
+  // Returns whether `pref_name` is part of the allowlist of preferences that
+  // are always synced, irrespective of the preference sync user toggle.
+  virtual bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const = 0;
 };
 
 }  // namespace sync_preferences
diff --git a/components/sync_preferences/test_syncable_prefs_database.cc b/components/sync_preferences/test_syncable_prefs_database.cc
index 0354a8b..c738ad46 100644
--- a/components/sync_preferences/test_syncable_prefs_database.cc
+++ b/components/sync_preferences/test_syncable_prefs_database.cc
@@ -24,4 +24,9 @@
   return std::nullopt;
 }
 
+bool TestSyncablePrefsDatabase::IsPreferenceAlwaysSyncing(
+    std::string_view pref_name) const {
+  return false;
+}
+
 }  // namespace sync_preferences
diff --git a/components/sync_preferences/test_syncable_prefs_database.h b/components/sync_preferences/test_syncable_prefs_database.h
index c2c76b5b..6c63f47 100644
--- a/components/sync_preferences/test_syncable_prefs_database.h
+++ b/components/sync_preferences/test_syncable_prefs_database.h
@@ -25,6 +25,8 @@
   std::optional<sync_preferences::SyncablePrefMetadata> GetSyncablePrefMetadata(
       std::string_view pref_name) const override;
 
+  bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const override;
+
  private:
   PrefsMap syncable_prefs_map_;
 };
diff --git a/components/tabs/BUILD.gn b/components/tabs/BUILD.gn
index 65bc8665..8776c3f 100644
--- a/components/tabs/BUILD.gn
+++ b/components/tabs/BUILD.gn
@@ -6,6 +6,7 @@
   sources = [
     "public/split_tab_id.h",
     "public/supports_handles.h",
+    "public/tab_collection_node_interface.h",
     "public/tab_interface.h",
   ]
   public_deps = [
diff --git a/components/tabs/public/tab_collection_node_interface.h b/components/tabs/public/tab_collection_node_interface.h
new file mode 100644
index 0000000..f2959b5
--- /dev/null
+++ b/components/tabs/public/tab_collection_node_interface.h
@@ -0,0 +1,48 @@
+// Copyright 2025 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_TABS_PUBLIC_TAB_COLLECTION_NODE_INTERFACE_H_
+#define COMPONENTS_TABS_PUBLIC_TAB_COLLECTION_NODE_INTERFACE_H_
+
+namespace tabs {
+
+class TabCollection;
+class TabInterface;
+
+// A generic node in a tab collection tree. This is essentially a `std::variant`
+// wrapper that abstracts away the underlying concete types and their memory
+// management models.
+//
+// The need for this class arises from the fact that on Desktop tabs are stored
+// as `std::unique_ptr<TabModel>` whereas on Android we use `TabAndroid*`. The
+// semantics of interacting with a unique_ptr and raw ptr are sufficiently
+// different that a simple typedef is insufficient to resolve the difference and
+// so a wrapper indirection is required.
+class TabCollectionNodeInterface {
+ public:
+  enum class Type {
+    kTabInterface,
+    kTabCollection,
+  };
+
+  TabCollectionNodeInterface() = default;
+  virtual ~TabCollectionNodeInterface() = default;
+  TabCollectionNodeInterface(const TabCollectionNodeInterface& other) = delete;
+  void operator=(const TabCollectionNodeInterface& other) = delete;
+
+  // Returns the `Type` corresponding to the object stored in this collection.
+  virtual Type GetType() const = 0;
+
+  // Returns the stored `TabInterface`. Crashes if `Type` is not
+  // `kTabInterface`.
+  virtual TabInterface* GetTabInterface() const = 0;
+
+  // Returns the stored `TabCollection`. Crashes if `Type` is not
+  // `kTabCollection`.
+  virtual TabCollection* GetTabCollection() const = 0;
+};
+
+}  // namespace tabs
+
+#endif  // COMPONENTS_TABS_PUBLIC_TAB_COLLECTION_NODE_INTERFACE_H_
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 468c92c..8a22a01b 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -73,8 +73,8 @@
 );
 
 #if BUILDFLAG(IS_ANDROID)
-BASE_FEATURE(kUseFrameIntervalDeciderNewAndroidFeatures,
-             "UseFrameIntervalDeciderNewAndroidFeatures",
+BASE_FEATURE(kUseFrameIntervalDeciderAdaptiveFrameRate,
+             "UseFrameIntervalDeciderAdaptiveFrameRate",
              base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index c59a1e1..a3736c3 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -56,7 +56,7 @@
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kUseFrameIntervalDecider);
 #if BUILDFLAG(IS_ANDROID)
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(
-    kUseFrameIntervalDeciderNewAndroidFeatures);
+    kUseFrameIntervalDeciderAdaptiveFrameRate);
 #endif
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kTemporalSkipOverlaysWithRootCopyOutputRequests);
diff --git a/components/viz/common/frame_sinks/external_begin_frame_source_ios.mm b/components/viz/common/frame_sinks/external_begin_frame_source_ios.mm
index 9a46870..5139fed 100644
--- a/components/viz/common/frame_sinks/external_begin_frame_source_ios.mm
+++ b/components/viz/common/frame_sinks/external_begin_frame_source_ios.mm
@@ -7,6 +7,8 @@
 #import <Foundation/Foundation.h>
 #import <QuartzCore/QuartzCore.h>
 
+#include <algorithm>
+
 #include "base/apple/mach_logging.h"
 #include "base/logging.h"
 #include "base/numerics/checked_math.h"
@@ -138,7 +140,7 @@
     // part can result in exceeding the maximum rate because of the division
     // operation.
     _preferredRefreshRate =
-        refresh_rate > _maximumRefreshRate ? _maximumRefreshRate : refresh_rate;
+        std::clamp(refresh_rate, kMinimumRefreshRate, _maximumRefreshRate);
     if (@available(iOS 15, *)) {
       [_displayLink
           setPreferredFrameRateRange:CAFrameRateRange{
diff --git a/components/viz/common/quads/frame_interval_inputs.cc b/components/viz/common/quads/frame_interval_inputs.cc
index 0fa35ee..33dad74 100644
--- a/components/viz/common/quads/frame_interval_inputs.cc
+++ b/components/viz/common/quads/frame_interval_inputs.cc
@@ -14,6 +14,8 @@
       return "animating_image";
     case ContentFrameIntervalType::kScrollBarFadeOutAnimation:
       return "scrollbar_fade_out";
+    case ContentFrameIntervalType::kCompositorScroll:
+      return "compositor_scroll";
   }
 }
 
diff --git a/components/viz/common/quads/frame_interval_inputs.h b/components/viz/common/quads/frame_interval_inputs.h
index 3254e9a..cab7284 100644
--- a/components/viz/common/quads/frame_interval_inputs.h
+++ b/components/viz/common/quads/frame_interval_inputs.h
@@ -29,6 +29,7 @@
   kVideo,
   kAnimatingImage,  // Gifs.
   kScrollBarFadeOutAnimation,
+  kCompositorScroll,
 };
 
 VIZ_COMMON_EXPORT std::string ContentFrameIntervalTypeToString(
@@ -38,7 +39,7 @@
   // Type of content that has fixed content frame interval.
   ContentFrameIntervalType type = ContentFrameIntervalType::kVideo;
 
-  // Content frame interval.
+  // Content frame interval. 0 for kCompositorScroll.
   base::TimeDelta frame_interval;
 
   // Number of _additional_ content this entry refers to. Eg if there are 2
@@ -61,8 +62,13 @@
   // as touch scrolling, in the future.
   bool has_input = false;
 
+  // Frame has input from user. This intentionally excludes non-user input
+  // events such as fling. In contrast to `has_input`, this only applies to the
+  // current frame, is set to false immediately instead of with a delay; this
+  // also means it can flip back and forth frequently.
+  bool has_user_input = false;
+
   // The maximum of x or y scroll speed.
-  // TODO(crbug.com/402442892): Serialize and use this.
   float major_scroll_speed_in_pixels_per_second = 0.f;
 
   // Any content that has a fixed or specified content frame interval can be
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index f64be32..77b0daa 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -622,7 +622,8 @@
       allowed_yuv_overlay_count_(allowed_yuv_overlay_count),
       is_on_battery_power_(
           base::PowerMonitor::GetInstance()
-              ->AddPowerStateObserverAndReturnOnBatteryState(this)),
+              ->AddPowerStateObserverAndReturnBatteryPowerStatus(this) ==
+          base::PowerStateObserver::BatteryPowerStatus::kBatteryPower),
       no_undamaged_overlay_promotion_(
           base::FeatureList::IsEnabled(features::kNoUndamagedOverlayPromotion)),
       disable_video_overlay_if_moving_(disable_video_overlay_if_moving) {
diff --git a/components/viz/service/display/frame_interval_decider.cc b/components/viz/service/display/frame_interval_decider.cc
index f47e3ee0..bb576f9c 100644
--- a/components/viz/service/display/frame_interval_decider.cc
+++ b/components/viz/service/display/frame_interval_decider.cc
@@ -72,7 +72,7 @@
 void FrameIntervalDecider::Decide(
     base::TimeTicks frame_time,
     base::flat_map<FrameSinkId, FrameIntervalInputs> inputs_map) {
-  FrameIntervalMatcher::Inputs matcher_inputs(settings_);
+  FrameIntervalMatcher::Inputs matcher_inputs(settings_, frame_id_++);
   matcher_inputs.aggregated_frame_time = frame_time;
   matcher_inputs.inputs_map = std::move(inputs_map);
 
diff --git a/components/viz/service/display/frame_interval_decider.h b/components/viz/service/display/frame_interval_decider.h
index df46059..e10a264 100644
--- a/components/viz/service/display/frame_interval_decider.h
+++ b/components/viz/service/display/frame_interval_decider.h
@@ -89,6 +89,7 @@
 
   base::TimeTicks current_result_frame_time_;
   std::optional<Result> current_result_;
+  uint64_t frame_id_ = 0u;
 };
 
 }  // namespace viz
diff --git a/components/viz/service/display/frame_interval_matchers.cc b/components/viz/service/display/frame_interval_matchers.cc
index ddbb7e5..58b7a0c 100644
--- a/components/viz/service/display/frame_interval_matchers.cc
+++ b/components/viz/service/display/frame_interval_matchers.cc
@@ -22,7 +22,8 @@
 // have the same content frame interval. Then return that interval.
 std::optional<FrameIntervalMatcher::Result> MatchContentIntervalType(
     const FrameIntervalMatcher::Inputs& matcher_inputs,
-    ContentFrameIntervalType type) {
+    ContentFrameIntervalType type,
+    FrameIntervalMatcher::ResultIntervalType interval_type) {
   std::optional<base::TimeDelta> content_interval;
   for (const auto& [frame_sink_id, inputs] : matcher_inputs.inputs_map) {
     // Skip frame sinks that are old.
@@ -119,7 +120,7 @@
             return content_interval.value();
           }),
       matcher_inputs.settings->interval_settings);
-  return FrameIntervalMatcher::ResultInterval{interval};
+  return FrameIntervalMatcher::ResultInterval{interval, interval_type};
 }
 
 }  // namespace
@@ -147,8 +148,9 @@
 FrameIntervalMatcher::Settings& FrameIntervalMatcher::Settings::operator=(
     Settings&& other) = default;
 
-FrameIntervalMatcher::Inputs::Inputs(const Settings& settings)
-    : settings(settings) {}
+FrameIntervalMatcher::Inputs::Inputs(const Settings& settings,
+                                     uint64_t frame_id)
+    : settings(settings), frame_id(frame_id) {}
 FrameIntervalMatcher::Inputs::~Inputs() = default;
 FrameIntervalMatcher::Inputs::Inputs(const Inputs& other) = default;
 FrameIntervalMatcher::Inputs& FrameIntervalMatcher::Inputs::operator=(
@@ -216,12 +218,16 @@
       return "None";
     case FrameIntervalMatcherType::kInputBoost:
       return "InputBoost";
+    case FrameIntervalMatcherType::kSlowScrollThrottle:
+      return "SlowScrollThrottle";
     case FrameIntervalMatcherType::kOnlyVideo:
       return "OnlyVideo";
     case FrameIntervalMatcherType::kVideoConference:
       return "VideoConference";
     case FrameIntervalMatcherType::kOnlyAnimatingImage:
       return "kOnlyAnimatingImage";
+    case FrameIntervalMatcherType::kUserInputBoost:
+      return "UserInputBoost";
     case FrameIntervalMatcherType::kOnlyScrollBarFadeOut:
       return "OnlyScrollBarFadeOut";
   }
@@ -283,7 +289,8 @@
 std::optional<FrameIntervalMatcher::Result> OnlyVideoMatcher::Match(
     const Inputs& matcher_inputs) {
   return MatchContentIntervalType(matcher_inputs,
-                                  ContentFrameIntervalType::kVideo);
+                                  ContentFrameIntervalType::kVideo,
+                                  ResultIntervalType::kExact);
 }
 
 // Matches video conference case by using heuristic of 2 or more videos.
@@ -358,7 +365,8 @@
 std::optional<FrameIntervalMatcher::Result> OnlyAnimatingImageMatcher::Match(
     const Inputs& matcher_inputs) {
   return MatchContentIntervalType(matcher_inputs,
-                                  ContentFrameIntervalType::kAnimatingImage);
+                                  ContentFrameIntervalType::kAnimatingImage,
+                                  ResultIntervalType::kExact);
 }
 
 DefineSimpleMatcherConstructorDestructor(OnlyScrollBarFadeOutAnimationMatcher,
@@ -366,7 +374,99 @@
 std::optional<FrameIntervalMatcher::Result>
 OnlyScrollBarFadeOutAnimationMatcher::Match(const Inputs& matcher_inputs) {
   return MatchContentIntervalType(
-      matcher_inputs, ContentFrameIntervalType::kScrollBarFadeOutAnimation);
+      matcher_inputs, ContentFrameIntervalType::kScrollBarFadeOutAnimation,
+      ResultIntervalType::kAtLeast);
+}
+
+DefineSimpleMatcherConstructorDestructor(UserInputBoostMatcher,
+                                         kUserInputBoost);
+std::optional<FrameIntervalMatcher::Result> UserInputBoostMatcher::Match(
+    const Inputs& matcher_inputs) {
+  for (const auto& [frame_sink_id, inputs] : matcher_inputs.inputs_map) {
+    if (inputs.has_user_input &&
+        (matcher_inputs.aggregated_frame_time - inputs.frame_time) <
+            matcher_inputs.settings->ignore_frame_sink_timeout) {
+      return std::visit(
+          base::Overloaded(
+              [](const std::monostate& monostate) -> Result {
+                return FrameIntervalClass::kBoost;
+              },
+              [](const FixedIntervalSettings& fixed_interval_settings)
+                  -> Result {
+                return ResultInterval{
+                    *fixed_interval_settings.supported_intervals.begin(),
+                    ResultIntervalType::kAtLeast};
+              },
+              [](const ContinuousRangeSettings& continuous_range_settings)
+                  -> Result {
+                return ResultInterval{continuous_range_settings.min_interval,
+                                      ResultIntervalType::kAtLeast};
+              }),
+          matcher_inputs.settings->interval_settings);
+    }
+  }
+  return std::nullopt;
+}
+
+SlowScrollThrottleMatcher::SlowScrollThrottleMatcher(float device_scale_factor)
+    : FrameIntervalMatcher(FrameIntervalMatcherType::kSlowScrollThrottle),
+      device_scale_factor_(device_scale_factor) {}
+SlowScrollThrottleMatcher::~SlowScrollThrottleMatcher() = default;
+
+std::optional<FrameIntervalMatcher::Result> SlowScrollThrottleMatcher::Match(
+    const Inputs& matcher_inputs) {
+  CHECK(std::holds_alternative<std::monostate>(
+      matcher_inputs.settings->interval_settings));
+  float scroll_speed = 0.f;
+  bool ignored_extra_update = false;
+  for (const auto& [frame_sink_id, inputs] : matcher_inputs.inputs_map) {
+    // Skip frame sinks that are old.
+    if (matcher_inputs.aggregated_frame_time - inputs.frame_time >=
+        matcher_inputs.settings->ignore_frame_sink_timeout) {
+      continue;
+    }
+    bool has_non_scroll_update =
+        !inputs.has_only_content_frame_interval_updates ||
+        std::any_of(
+            inputs.content_interval_info.begin(),
+            inputs.content_interval_info.end(),
+            [](const ContentFrameIntervalInfo& content_frame_interval_info) {
+              return content_frame_interval_info.type !=
+                     ContentFrameIntervalType::kCompositorScroll;
+            });
+    // Scroll can occasionally have new tiles rastered or new content recorded
+    // in a commit. Ignore these one off frames that has updates beyond just
+    // scroll. Otherwise, do not match.
+    if (has_non_scroll_update &&
+        (matcher_inputs.frame_id - last_frame_id_matched_without_extra_update_ >
+         1)) {
+      return std::nullopt;
+    }
+    if (has_non_scroll_update) {
+      ignored_extra_update = true;
+    }
+    if (inputs.major_scroll_speed_in_pixels_per_second > scroll_speed) {
+      scroll_speed = inputs.major_scroll_speed_in_pixels_per_second;
+    }
+  }
+
+  // No scroll.
+  if (scroll_speed <= 0) {
+    return std::nullopt;
+  }
+
+  if (!ignored_extra_update) {
+    last_frame_id_matched_without_extra_update_ = matcher_inputs.frame_id;
+  }
+  float speed_dps = scroll_speed / device_scale_factor_;
+  // The hard-coded values are copied from AOSP View.convertVelocityToFrameRate.
+  if (speed_dps > 300) {
+    return FrameIntervalClass::kBoost;
+  } else if (speed_dps > 125) {
+    return ResultInterval{base::Hertz(80), ResultIntervalType::kAtLeast};
+  } else {
+    return ResultInterval{base::Hertz(60), ResultIntervalType::kAtLeast};
+  }
 }
 
 }  // namespace viz
diff --git a/components/viz/service/display/frame_interval_matchers.h b/components/viz/service/display/frame_interval_matchers.h
index 0f84a6d5..1659c90 100644
--- a/components/viz/service/display/frame_interval_matchers.h
+++ b/components/viz/service/display/frame_interval_matchers.h
@@ -31,7 +31,9 @@
   kVideoConference = 3,
   kOnlyAnimatingImage = 4,
   kOnlyScrollBarFadeOut = 5,
-  kMaxValue = kOnlyScrollBarFadeOut,
+  kUserInputBoost = 6,
+  kSlowScrollThrottle = 7,
+  kMaxValue = kSlowScrollThrottle,
 };
 
 // Works with `FrameIntervalDecider` to compute the ideal frame interval.
@@ -124,7 +126,7 @@
   };
 
   struct VIZ_SERVICE_EXPORT Inputs {
-    explicit Inputs(const Settings& settings);
+    Inputs(const Settings& settings, uint64_t frame_id);
     ~Inputs();
 
     Inputs(const Inputs& other);
@@ -134,6 +136,8 @@
     void WriteIntoTrace(perfetto::TracedValue trace_context) const;
 
     base::raw_ref<const Settings> settings;
+    // Increasing id for each viz frame.
+    uint64_t frame_id;
     base::TimeTicks aggregated_frame_time;
     base::flat_map<FrameSinkId, FrameIntervalInputs> inputs_map;
   };
@@ -171,9 +175,22 @@
 DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(VideoConferenceMatcher);
 DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(OnlyAnimatingImageMatcher);
 DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(OnlyScrollBarFadeOutAnimationMatcher);
+DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(UserInputBoostMatcher);
 
 #undef DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER
 
+class VIZ_SERVICE_EXPORT SlowScrollThrottleMatcher
+    : public FrameIntervalMatcher {
+ public:
+  explicit SlowScrollThrottleMatcher(float device_scale_factor);
+  ~SlowScrollThrottleMatcher() override;
+  std::optional<Result> Match(const Inputs& matcher_inputs) override;
+
+ private:
+  const float device_scale_factor_;
+  uint64_t last_frame_id_matched_without_extra_update_ = 0u;
+};
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_FRAME_INTERVAL_MATCHERS_H_
diff --git a/components/viz/service/display/frame_interval_matchers_unittest.cc b/components/viz/service/display/frame_interval_matchers_unittest.cc
index e7c5e80f..da49336 100644
--- a/components/viz/service/display/frame_interval_matchers_unittest.cc
+++ b/components/viz/service/display/frame_interval_matchers_unittest.cc
@@ -15,6 +15,7 @@
 namespace {
 
 using FrameIntervalClass = FrameIntervalMatcher::FrameIntervalClass;
+using ResultIntervalType = FrameIntervalMatcher::ResultIntervalType;
 using ResultInterval = FrameIntervalMatcher::ResultInterval;
 using Result = FrameIntervalMatcher::Result;
 using FixedIntervalSettings = FrameIntervalMatcher::FixedIntervalSettings;
@@ -33,11 +34,13 @@
 }
 
 void ExpectResult(const std::optional<Result> result_opt,
-                  base::TimeDelta interval) {
+                  base::TimeDelta interval,
+                  ResultIntervalType interval_type) {
   ASSERT_TRUE(result_opt.has_value());
   const Result& result = result_opt.value();
   ASSERT_TRUE(std::holds_alternative<ResultInterval>(result));
   EXPECT_EQ(interval, std::get<ResultInterval>(result).interval);
+  EXPECT_EQ(interval_type, std::get<ResultInterval>(result).type);
 }
 
 void ExpectNullResult(const std::optional<Result> result_opt) {
@@ -74,7 +77,7 @@
 }
 
 Inputs BuildDefaultInputs(Settings& settings, uint32_t num_sinks) {
-  Inputs inputs(settings);
+  Inputs inputs(settings, /*frame_id=*/0u);
 
   inputs.aggregated_frame_time = kNow;
   for (uint32_t sink_id = 1; sink_id <= num_sinks; ++sink_id) {
@@ -106,7 +109,8 @@
   InputBoostMatcher matcher;
 
   inputs.inputs_map[FrameSinkId(0, 1)].has_input = true;
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(8));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(8),
+               ResultIntervalType::kAtLeast);
 
   inputs.inputs_map[FrameSinkId(0, 1)].has_input = false;
   ExpectNullResult(matcher.Match(inputs));
@@ -136,7 +140,8 @@
       {ContentFrameIntervalType::kVideo, base::Milliseconds(32)});
   frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(32));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(32),
+               ResultIntervalType::kExact);
 
   frame_interval_inputs.has_only_content_frame_interval_updates = false;
   ExpectNullResult(matcher.Match(inputs));
@@ -154,7 +159,8 @@
       {ContentFrameIntervalType::kVideo, base::Milliseconds(24)});
   frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(8));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(8),
+               ResultIntervalType::kExact);
 }
 
 TEST(FrameIntervalMatchersTest, OnlyVideoFixedIntervalNoSimpleCadence) {
@@ -171,7 +177,8 @@
 
   // Should return default if there is no simple cadence with any fixed
   // supported intervals.
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(16));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(16),
+               ResultIntervalType::kExact);
 }
 
 TEST(FrameIntervalMatchersTest, OnlyVideoDifferentIntervals) {
@@ -193,7 +200,8 @@
 
   interval_inputs2.content_interval_info[0].frame_interval =
       base::Milliseconds(32);
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(32));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(32),
+               ResultIntervalType::kExact);
 }
 
 TEST(FrameIntervalMatchersTest, OnlyVideoContinuousRange) {
@@ -212,7 +220,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(60)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(60));
+    ExpectResult(matcher.Match(inputs), base::Hertz(60),
+                 ResultIntervalType::kExact);
   }
 
   // Verify that the lowest perfect cadence (= 2) is chosen when the target
@@ -225,7 +234,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(35)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(70));
+    ExpectResult(matcher.Match(inputs), base::Hertz(70),
+                 ResultIntervalType::kExact);
   }
 
   // Verify the same (where the expected cadence = 3).
@@ -237,7 +247,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(15)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(45));
+    ExpectResult(matcher.Match(inputs), base::Hertz(45),
+                 ResultIntervalType::kExact);
   }
 
   // Verify that the lowest perfect cadence (= 2) is chosen when the target
@@ -250,7 +261,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(160)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(80));
+    ExpectResult(matcher.Match(inputs), base::Hertz(80),
+                 ResultIntervalType::kExact);
   }
 
   // Verify the same (where the expected cadence = 4).
@@ -262,7 +274,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(400)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(100));
+    ExpectResult(matcher.Match(inputs), base::Hertz(100),
+                 ResultIntervalType::kExact);
   }
 
   settings.interval_settings =
@@ -278,7 +291,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(40)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(48));
+    ExpectResult(matcher.Match(inputs), base::Hertz(48),
+                 ResultIntervalType::kExact);
   }
 
   // Verify that the maximum supported interval is chosen if there is no perfect
@@ -291,7 +305,8 @@
         {ContentFrameIntervalType::kVideo, base::Hertz(80)});
     frame_interval_inputs.has_only_content_frame_interval_updates = true;
 
-    ExpectResult(matcher.Match(inputs), base::Hertz(60));
+    ExpectResult(matcher.Match(inputs), base::Hertz(60),
+                 ResultIntervalType::kExact);
   }
 }
 
@@ -306,7 +321,8 @@
   FrameIntervalInputs& interval_inputs2 = inputs.inputs_map[FrameSinkId(0, 2)];
   interval_inputs2.content_interval_info.push_back(
       {ContentFrameIntervalType::kVideo, base::Milliseconds(24)});
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(24));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(24),
+               ResultIntervalType::kExact);
 
   interval_inputs2.content_interval_info.clear();
   ExpectNullResult(matcher.Match(inputs));
@@ -324,7 +340,8 @@
   FrameIntervalInputs& interval_inputs2 = inputs.inputs_map[FrameSinkId(0, 2)];
   interval_inputs2.content_interval_info.push_back(
       {ContentFrameIntervalType::kVideo, base::Milliseconds(24)});
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(16));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(16),
+               ResultIntervalType::kExact);
 }
 
 TEST(FrameIntervalMatchersTest, VideoConferenceDenseFixedInterval) {
@@ -358,7 +375,8 @@
         inputs.inputs_map[FrameSinkId(0, 2)];
     interval_inputs2.content_interval_info.push_back(
         {ContentFrameIntervalType::kVideo, input1_interval});
-    ExpectResult(matcher.Match(inputs), base::Hertz(59.94));
+    ExpectResult(matcher.Match(inputs), base::Hertz(59.94),
+                 ResultIntervalType::kExact);
   }
 
   // Verify the same when the input interval is closer to the other side.
@@ -372,7 +390,8 @@
         inputs.inputs_map[FrameSinkId(0, 2)];
     interval_inputs2.content_interval_info.push_back(
         {ContentFrameIntervalType::kVideo, input2_interval});
-    ExpectResult(matcher.Match(inputs), base::Hertz(60));
+    ExpectResult(matcher.Match(inputs), base::Hertz(60),
+                 ResultIntervalType::kExact);
   }
 }
 
@@ -384,7 +403,8 @@
   FrameIntervalInputs& interval_inputs1 = inputs.inputs_map[FrameSinkId(0, 1)];
   interval_inputs1.content_interval_info.push_back(
       {ContentFrameIntervalType::kVideo, base::Milliseconds(32), 2u});
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(32));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(32),
+               ResultIntervalType::kExact);
 }
 
 TEST(FrameIntervalMatchersTest, VideoConferenceIgnoreOldSinks) {
@@ -398,7 +418,8 @@
   FrameIntervalInputs& interval_inputs2 = inputs.inputs_map[FrameSinkId(0, 2)];
   interval_inputs2.content_interval_info.push_back(
       {ContentFrameIntervalType::kVideo, base::Milliseconds(24)});
-  ExpectResult(matcher.Match(inputs), base::Milliseconds(24));
+  ExpectResult(matcher.Match(inputs), base::Milliseconds(24),
+               ResultIntervalType::kExact);
 
   interval_inputs2.frame_time = kNow - base::Seconds(1);
   ExpectNullResult(matcher.Match(inputs));
@@ -421,7 +442,8 @@
         inputs.inputs_map[FrameSinkId(0, 2)];
     interval_inputs2.content_interval_info.push_back(
         {ContentFrameIntervalType::kVideo, base::Hertz(50)});
-    ExpectResult(matcher.Match(inputs), base::Hertz(60));
+    ExpectResult(matcher.Match(inputs), base::Hertz(60),
+                 ResultIntervalType::kExact);
   }
 
   // Verify the minimum possible interval is chosen when the minimum content
@@ -436,7 +458,8 @@
         inputs.inputs_map[FrameSinkId(0, 2)];
     interval_inputs2.content_interval_info.push_back(
         {ContentFrameIntervalType::kVideo, base::Hertz(50)});
-    ExpectResult(matcher.Match(inputs), base::Hertz(120));
+    ExpectResult(matcher.Match(inputs), base::Hertz(120),
+                 ResultIntervalType::kExact);
   }
 
   // Verify the maximum possible interval is chosen when the minimum content
@@ -451,7 +474,8 @@
         inputs.inputs_map[FrameSinkId(0, 2)];
     interval_inputs2.content_interval_info.push_back(
         {ContentFrameIntervalType::kVideo, base::Hertz(35)});
-    ExpectResult(matcher.Match(inputs), base::Hertz(40));
+    ExpectResult(matcher.Match(inputs), base::Hertz(40),
+                 ResultIntervalType::kExact);
   }
 }
 
@@ -469,5 +493,93 @@
             "content_info_0:{type:video,interval_us:32000,duplicate_count:0}}");
 }
 
+TEST(FrameIntervalMatchersTest, UserInputBoostMatcher) {
+  Settings settings;
+  Inputs inputs = BuildDefaultInputs(settings, /*num_sinks=*/2u);
+  UserInputBoostMatcher matcher;
+
+  inputs.inputs_map[FrameSinkId(0, 1)].has_user_input = true;
+  ExpectResult(matcher.Match(inputs), FrameIntervalClass::kBoost);
+
+  inputs.inputs_map[FrameSinkId(0, 1)].has_user_input = false;
+  ExpectNullResult(matcher.Match(inputs));
+}
+
+TEST(FrameIntervalMatchersTest, SlowScrollThrottleSlowSpeedThrottle) {
+  Settings settings;
+  Inputs inputs = BuildDefaultInputs(settings, /*num_sinks=*/1u);
+  SlowScrollThrottleMatcher matcher(/*device_scale_factor=*/1.0f);
+
+  FrameIntervalInputs& interval_input = inputs.inputs_map[FrameSinkId(0, 1)];
+  interval_input.content_interval_info.push_back(
+      {ContentFrameIntervalType::kCompositorScroll, base::TimeDelta()});
+  interval_input.has_only_content_frame_interval_updates = true;
+
+  interval_input.major_scroll_speed_in_pixels_per_second = 1000.0f;
+  ExpectResult(matcher.Match(inputs), FrameIntervalClass::kBoost);
+
+  interval_input.major_scroll_speed_in_pixels_per_second = 250.0f;
+  ExpectResult(matcher.Match(inputs), base::Hertz(80),
+               ResultIntervalType::kAtLeast);
+
+  interval_input.major_scroll_speed_in_pixels_per_second = 10.0f;
+  ExpectResult(matcher.Match(inputs), base::Hertz(60),
+               ResultIntervalType::kAtLeast);
+
+  interval_input.major_scroll_speed_in_pixels_per_second = 0.0f;
+  ExpectNullResult(matcher.Match(inputs));
+}
+
+TEST(FrameIntervalMatchersTest, SlowScrollThrottleInputSlowScroll) {
+  Settings settings;
+  Inputs inputs = BuildDefaultInputs(settings, /*num_sinks=*/1u);
+  SlowScrollThrottleMatcher matcher(/*device_scale_factor=*/1.0f);
+
+  FrameIntervalInputs& interval_input = inputs.inputs_map[FrameSinkId(0, 1)];
+  interval_input.content_interval_info.push_back(
+      {ContentFrameIntervalType::kCompositorScroll, base::TimeDelta()});
+  interval_input.has_only_content_frame_interval_updates = true;
+
+  interval_input.major_scroll_speed_in_pixels_per_second = 10.0f;
+  ExpectResult(matcher.Match(inputs), base::Hertz(60),
+               ResultIntervalType::kAtLeast);
+}
+
+TEST(FrameIntervalMatchersTest, SlowScrollThrottleIgnoreOneOffUpdate) {
+  Settings settings;
+  Inputs inputs = BuildDefaultInputs(settings, /*num_sinks=*/1u);
+  SlowScrollThrottleMatcher matcher(/*device_scale_factor=*/1.0f);
+
+  FrameIntervalInputs& interval_input = inputs.inputs_map[FrameSinkId(0, 1)];
+  interval_input.content_interval_info.push_back(
+      {ContentFrameIntervalType::kCompositorScroll, base::TimeDelta()});
+  interval_input.has_only_content_frame_interval_updates = true;
+  interval_input.major_scroll_speed_in_pixels_per_second = 10.0f;
+
+  inputs.frame_id = 10u;
+  ExpectResult(matcher.Match(inputs), base::Hertz(60),
+               ResultIntervalType::kAtLeast);
+
+  inputs.frame_id = 11u;
+  interval_input.has_only_content_frame_interval_updates = false;
+  // Ignore one off non-scroll update.
+  ExpectResult(matcher.Match(inputs), base::Hertz(60),
+               ResultIntervalType::kAtLeast);
+
+  // Continuous non-scroll update should not match.
+  inputs.frame_id = 12u;
+  interval_input.has_only_content_frame_interval_updates = false;
+  ExpectNullResult(matcher.Match(inputs));
+  inputs.frame_id = 13u;
+  interval_input.has_only_content_frame_interval_updates = false;
+  ExpectNullResult(matcher.Match(inputs));
+
+  // Match if there are no non-scroll updates.
+  inputs.frame_id = 14u;
+  interval_input.has_only_content_frame_interval_updates = true;
+  ExpectResult(matcher.Match(inputs), base::Hertz(60),
+               ResultIntervalType::kAtLeast);
+}
+
 }  // namespace
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index b16eec7..ead81263 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -487,7 +487,12 @@
     float suggested_high,
     const std::vector<float>& supported_refresh_rates,
     float device_scale_factor) {
-  // TODO(crbug.com/402442892): Use this info.
+  supports_adaptive_refresh_rate_ =
+      has_support && base::FeatureList::IsEnabled(
+                         features::kUseFrameIntervalDeciderAdaptiveFrameRate);
+  suggested_frame_interval_high_ = base::Hertz(suggested_high);
+  device_scale_factor_ = device_scale_factor;
+  UpdateFrameIntervalDeciderSettings();
 }
 
 void RootCompositorFrameSinkImpl::PreserveChildSurfaceControls() {
@@ -680,12 +685,22 @@
 
   // Note that matcher order defines precedence.
   std::vector<std::unique_ptr<FrameIntervalMatcher>> matchers;
+
+#if BUILDFLAG(IS_ANDROID)
+  if (supports_adaptive_refresh_rate_) {
+    matchers.push_back(std::make_unique<UserInputBoostMatcher>());
+    matchers.push_back(
+        std::make_unique<SlowScrollThrottleMatcher>(device_scale_factor_));
+  } else {
+    matchers.push_back(std::make_unique<InputBoostMatcher>());
+  }
+#else
   matchers.push_back(std::make_unique<InputBoostMatcher>());
+#endif
 
 #if BUILDFLAG(IS_ANDROID)
   matchers.push_back(std::make_unique<OnlyVideoMatcher>());
-  if (base::FeatureList::IsEnabled(
-          features::kUseFrameIntervalDeciderNewAndroidFeatures)) {
+  if (supports_adaptive_refresh_rate_) {
     matchers.push_back(std::make_unique<OnlyAnimatingImageMatcher>());
     matchers.push_back(
         std::make_unique<OnlyScrollBarFadeOutAnimationMatcher>());
@@ -743,10 +758,15 @@
   std::pair<base::TimeDelta, gfx::SurfaceControlFrameRateCompatibility>
       interval_and_compat = std::visit(
           base::Overloaded(
-              [](FrameIntervalDecider::FrameIntervalClass
-                     frame_interval_class) {
+              [this](FrameIntervalDecider::FrameIntervalClass
+                         frame_interval_class) {
                 switch (frame_interval_class) {
                   case FrameIntervalDecider::FrameIntervalClass::kBoost:
+                    if (supports_adaptive_refresh_rate_) {
+                      return std::pair(
+                          suggested_frame_interval_high_,
+                          gfx::SurfaceControlFrameRateCompatibility::kAtLeast);
+                    }
                     return std::pair(base::Milliseconds(0),
                                      gfx::SurfaceControlFrameRateCompatibility::
                                          kFixedSource);
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
index f44ffbd..59f60d19 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -251,6 +251,10 @@
 #if BUILDFLAG(IS_ANDROID)
   // Let client control whether it wants `DidCompleteSwapWithSize`.
   bool enable_swap_completion_callback_ = false;
+
+  bool supports_adaptive_refresh_rate_ = false;
+  base::TimeDelta suggested_frame_interval_high_;
+  float device_scale_factor_ = 1.0f;
 #endif
 
   // Map which retains the exact supported refresh rates, keyed by their
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 24f6f89cf..48363b9 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -662,7 +662,18 @@
 
   MainFunctionParams main_params(command_line);
   main_params.zygote_child = true;
-  main_params.needs_startup_tracing_after_mojo_init = true;
+
+  if (process_type == switches::kGpuProcess) {
+    // Once Zygote forks and feature list initializes we can start a thread to
+    // begin tracing immediately.
+    // TODO(https://crbug.com/380411640): Enable for more processes other than
+    // GPU process.
+    tracing::EnableStartupTracingIfNeeded(/*with_thread=*/true);
+    tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
+    main_params.needs_startup_tracing_after_mojo_init = false;
+  } else {
+    main_params.needs_startup_tracing_after_mojo_init = true;
+  }
 
   // The hang watcher needs to be created once the feature list is available
   // but before the IO thread is started.
@@ -892,15 +903,27 @@
 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
   // A sandboxed process won't be able to allocate the SMB needed for startup
   // tracing until Mojo IPC support is brought up, at which point the Mojo
-  // broker will transparently broker the SMB creation.
-  if (!sandbox::policy::IsUnsandboxedSandboxType(
+  // broker will transparently broker the SMB creation. Unless the sandboxed
+  // process stops the trace threads when entering sandbox.
+  // TODO(https://crbug.com/380411640): Implement for other processes other than
+  // GPU process.
+  if (process_type != switches::kGpuProcess &&
+      !sandbox::policy::IsUnsandboxedSandboxType(
           sandbox::policy::SandboxTypeFromCommandLine(command_line))) {
     enable_startup_tracing = false;
     needs_startup_tracing_after_mojo_init_ = true;
   }
 #endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
   if (enable_startup_tracing) {
-    tracing::EnableStartupTracingIfNeeded();
+    if (process_type == switches::kGpuProcess) {
+      // Without Zygote and posix sandbox we can start a thread to begin tracing
+      // immediately.
+      // TODO(https://crbug.com/380411640): Enable for more processes other than
+      // GPU process.
+      tracing::EnableStartupTracingIfNeeded(/*with_thread=*/true);
+    } else {
+      tracing::EnableStartupTracingIfNeeded(/*with_thread=*/false);
+    }
   }
   TRACE_EVENT0("startup,benchmark,rail", "ContentMainRunnerImpl::Initialize");
 
@@ -1116,6 +1139,9 @@
               ContentMainDelegate::InvokedInChildProcess())) {
         InitializeFieldTrialAndFeatureList();
       }
+      if (process_type == switches::kGpuProcess) {
+        tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
+      }
       if (delegate_->ShouldInitializeMojo(
               ContentMainDelegate::InvokedInChildProcess())) {
         InitializeMojoCore();
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 551242b..c303e0a2 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -4576,6 +4576,11 @@
   RunCSSTest(FILE_PATH_LITERAL("carousel-positioned-buttons.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeWithCarouselTest,
+                       AccessibilityCSSReadingScrollMarker) {
+  RunCSSTest(FILE_PATH_LITERAL("reading-flow-scroll-marker.html"));
+}
+
 //
 // These tests cover features of the testing infrastructure itself.
 //
diff --git a/content/browser/android/battery_metrics.cc b/content/browser/android/battery_metrics.cc
index 162e30c..9363fa28 100644
--- a/content/browser/android/battery_metrics.cc
+++ b/content/browser/android/battery_metrics.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
+#include "base/power_monitor/energy_monitor_android.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
@@ -87,6 +88,7 @@
 }
 
 void Report30SecondDrain(int capacity_consumed,
+                         std::optional<int64_t> energy_consumed_mwh,
                          bool is_exclusive_measurement,
                          const std::string& scenario) {
   // Drain over the last 30 seconds in uAh. We assume a max current of 10A which
@@ -97,6 +99,12 @@
       std::string("Power.ForegroundBatteryDrainPerScenario.30Seconds.") +
           scenario,
       capacity_consumed);
+  if (energy_consumed_mwh.has_value()) {
+    base::UmaHistogramCounts100000(
+        std::string("Power.ForegroundEnergyConsumedPerScenario.30Seconds.") +
+            scenario,
+        *energy_consumed_mwh);
+  }
 
   // Record a separate metric for power drain that was completely observed while
   // we were the foreground app. This avoids attributing power draw from other
@@ -109,6 +117,13 @@
             "Power.ForegroundBatteryDrainPerScenario.30Seconds.Exclusive.") +
             scenario,
         capacity_consumed);
+    if (energy_consumed_mwh.has_value()) {
+      base::UmaHistogramCounts100000(
+          std::string("Power.ForegroundEnergyConsumedPerScenario.30Seconds."
+                      "Exclusive.") +
+              scenario,
+          *energy_consumed_mwh);
+    }
   }
 }
 
@@ -322,8 +337,9 @@
 
   if (should_be_enabled && !metrics_timer_.IsRunning()) {
     // Capture first capacity measurement and enable the repeating timer.
-    last_remaining_capacity_uah_ =
-        base::PowerMonitor::GetInstance()->GetRemainingBatteryCapacity();
+    last_remaining_capacity_uah_ = base::android::GetRemainingBatteryCapacity();
+    last_total_energy_uws_ = base::android::GetTotalEnergyConsumed();
+
     skipped_timers_ = 0;
     observed_capacity_drops_ = 0;
     performance_scenario_tracker_.UseLatestScenarios();
@@ -341,19 +357,33 @@
 }
 
 void AndroidBatteryMetrics::CaptureAndReportMetrics(bool disabling) {
-  int remaining_capacity_uah =
-      base::PowerMonitor::GetInstance()->GetRemainingBatteryCapacity();
+  int remaining_capacity_uah = base::android::GetRemainingBatteryCapacity();
+  int64_t total_energy_uws = base::android::GetTotalEnergyConsumed();
 
   const std::string scenario = performance_scenario_tracker_.GetMetricSuffix();
   performance_scenario_tracker_.UseLatestScenarios();
 
+  std::optional<int64_t> energy_consumed_mwh;
+  // 0 means an error for total energy, in which case we can't report the delta.
+  // The underlying API has throttling (in which case the old value is reported
+  // again, but no errors), so if we call this method because the battery state
+  // is changing rather than by timer, the delta is likely to be (misleadingly)
+  // 0. Let's not report such values.
+  if (last_total_energy_uws_ != 0 && total_energy_uws != 0 && !disabling) {
+    energy_consumed_mwh =
+        std::max(static_cast<int64_t>(0),
+                 (total_energy_uws - last_total_energy_uws_) / 3600);
+  }
+  last_total_energy_uws_ = total_energy_uws;
+
   if (remaining_capacity_uah >= last_remaining_capacity_uah_) {
     // No change in battery capacity, or it increased. The latter could happen
     // if we detected the switch off battery power to a charger late, or if the
     // device reports bogus values. We don't change last_remaining_capacity_uah_
     // here to avoid overreporting in case of fluctuating values.
     skipped_timers_++;
-    Report30SecondDrain(0, IsMeasuringDrainExclusively(), scenario);
+    Report30SecondDrain(0, energy_consumed_mwh, IsMeasuringDrainExclusively(),
+                        scenario);
 
     if (disabling) {
       // Disabling the timer, but without a change in capacity counter -- We
@@ -372,8 +402,8 @@
 
   // Report the consumed capacity delta over the last 30 seconds.
   int capacity_consumed = last_remaining_capacity_uah_ - remaining_capacity_uah;
-  Report30SecondDrain(capacity_consumed, IsMeasuringDrainExclusively(),
-                      scenario);
+  Report30SecondDrain(capacity_consumed, energy_consumed_mwh,
+                      IsMeasuringDrainExclusively(), scenario);
 
   // Also record drain over 30 second intervals, but averaged since the last
   // time we recorded an increase (or started recording samples). Because the
diff --git a/content/browser/android/battery_metrics.h b/content/browser/android/battery_metrics.h
index 45b1e5a..d873c627 100644
--- a/content/browser/android/battery_metrics.h
+++ b/content/browser/android/battery_metrics.h
@@ -107,6 +107,7 @@
   PowerStateObserver::BatteryPowerStatus battery_power_status_ =
       PowerStateObserver::BatteryPowerStatus::kUnknown;
   int last_remaining_capacity_uah_ = 0;
+  int64_t last_total_energy_uws_ = 0;
   base::RepeatingTimer metrics_timer_;
   int skipped_timers_ = 0;
 
diff --git a/content/browser/attribution_reporting/attribution_debug_report.cc b/content/browser/attribution_reporting/attribution_debug_report.cc
index 53788de..2155d99 100644
--- a/content/browser/attribution_reporting/attribution_debug_report.cc
+++ b/content/browser/attribution_reporting/attribution_debug_report.cc
@@ -6,7 +6,6 @@
 
 #include <stdint.h>
 
-#include <algorithm>
 #include <optional>
 #include <string_view>
 #include <utility>
@@ -52,16 +51,16 @@
 
 struct DebugDataTypeAndBody {
   DebugDataType debug_data_type;
-  base::Value limit;
-  base::Value::Dict additional_fields;
+  base::Value::Dict body;
 
-  explicit DebugDataTypeAndBody(
-      DebugDataType debug_data_type,
-      base::Value limit = base::Value(),
-      base::Value::Dict additional_fields = base::Value::Dict())
-      : debug_data_type(debug_data_type),
-        limit(std::move(limit)),
-        additional_fields(std::move(additional_fields)) {}
+  explicit DebugDataTypeAndBody(DebugDataType debug_data_type,
+                                base::Value limit = base::Value(),
+                                base::Value::Dict body = base::Value::Dict())
+      : debug_data_type(debug_data_type), body(std::move(body)) {
+    if (!limit.is_none()) {
+      this->body.Set("limit", std::move(limit));
+    }
+  }
 };
 
 template <typename T>
@@ -73,14 +72,14 @@
     const StoreSourceResult& result) {
   const auto make_report_body = [&](DebugDataType type,
                                     base::Value limit = base::Value()) {
-    base::Value::Dict additional_fields;
+    base::Value::Dict body;
     if (result.destination_limit().has_value()) {
-      additional_fields.Set("source_destination_limit",
-                            GetLimit(result.destination_limit().value()));
+      body.Set("source_destination_limit",
+               GetLimit(result.destination_limit().value()));
     }
 
-    return std::make_optional<DebugDataTypeAndBody>(
-        type, std::move(limit), std::move(additional_fields));
+    return std::make_optional<DebugDataTypeAndBody>(type, std::move(limit),
+                                                    std::move(body));
   };
 
   return std::visit(
@@ -299,14 +298,6 @@
       result);
 }
 
-void SetAdditionalFields(base::Value::Dict& data_body,
-                         base::Value::Dict additional_fields) {
-  CHECK(std::ranges::none_of(additional_fields, [&](const auto& e) {
-    return data_body.contains(e.first);
-  }));
-  data_body.Merge(std::move(additional_fields));
-}
-
 void SetSourceData(base::Value::Dict& data_body,
                    uint64_t source_event_id,
                    const net::SchemefulSite& source_site,
@@ -318,10 +309,6 @@
   }
 }
 
-void SetLimit(base::Value::Dict& data_body, base::Value limit) {
-  data_body.Set("limit", std::move(limit));
-}
-
 base::Value::Dict GetReportDataBody(DebugDataTypeAndBody data,
                                     const CreateReportResult& result) {
   if (data.debug_data_type == DebugDataType::kTriggerEventExcessiveReports ||
@@ -330,34 +317,27 @@
     return result.dropped_event_level_report()->ReportBody();
   }
 
-  base::Value::Dict data_body;
-  data_body.Set(
+  data.body.Set(
       kAttributionDestination,
       net::SchemefulSite(result.trigger().destination_origin()).Serialize());
+
   if (std::optional<uint64_t> debug_key =
           result.trigger().registration().debug_key) {
-    data_body.Set("trigger_debug_key", base::NumberToString(*debug_key));
+    data.body.Set("trigger_debug_key", base::NumberToString(*debug_key));
   }
 
   if (const std::optional<StoredSource>& source = result.source()) {
-    SetSourceData(data_body, source->source_event_id(),
+    SetSourceData(data.body, source->source_event_id(),
                   source->common_info().source_site(), source->debug_key());
   }
 
-  if (!data.limit.is_none()) {
-    SetLimit(data_body, std::move(data.limit));
-  }
-
-  SetAdditionalFields(data_body, std::move(data.additional_fields));
-
-  return data_body;
+  return std::move(data.body);
 }
 
 base::Value::Dict GetReportData(DebugDataType type, base::Value::Dict body) {
-  base::Value::Dict dict;
-  dict.Set("type", attribution_reporting::SerializeDebugDataType(type));
-  dict.Set("body", std::move(body));
-  return dict;
+  return base::Value::Dict()
+      .Set("type", attribution_reporting::SerializeDebugDataType(type))
+      .Set("body", std::move(body));
 }
 
 void RecordVerboseDebugReportType(DebugDataType type) {
@@ -394,24 +374,18 @@
 
   RecordVerboseDebugReportType(data->debug_data_type);
 
-  base::Value::Dict body;
-  if (!data->limit.is_none()) {
-    SetLimit(body, std::move(data->limit));
-  }
-
   const attribution_reporting::SourceRegistration& registration =
       source.registration();
 
-  body.Set(kAttributionDestination, registration.destination_set.ToJson());
-  SetSourceData(body, registration.source_event_id,
+  data->body.Set(kAttributionDestination,
+                 registration.destination_set.ToJson());
+  SetSourceData(data->body, registration.source_event_id,
                 source.common_info().source_site(), registration.debug_key);
 
-  SetAdditionalFields(body, std::move(data->additional_fields));
-
-  base::Value::List report_body;
-  report_body.Append(GetReportData(data->debug_data_type, std::move(body)));
-  return AttributionDebugReport(std::move(report_body),
-                                source.common_info().reporting_origin());
+  return AttributionDebugReport(
+      base::Value::List::with_capacity(1).Append(
+          GetReportData(data->debug_data_type, std::move(data->body))),
+      source.common_info().reporting_origin());
 }
 
 // static
@@ -491,18 +465,17 @@
       break;
   }
 
-  base::Value::Dict data_body;
-  data_body.Set("context_site",
-                net::SchemefulSite(registration.top_level_origin).Serialize());
-  data_body.Set("registration_url", registration_item.url.spec());
-
-  base::Value::List report_body;
-  report_body.Append(GetReportData(data_type, std::move(data_body)));
-
   RecordVerboseDebugReportType(data_type);
 
-  return AttributionDebugReport(std::move(report_body),
-                                *std::move(registration_origin));
+  return AttributionDebugReport(
+      base::Value::List::with_capacity(1).Append(GetReportData(
+          data_type,
+          base::Value::Dict()
+              .Set(
+                  "context_site",
+                  net::SchemefulSite(registration.top_level_origin).Serialize())
+              .Set("registration_url", registration_item.url.spec()))),
+      *std::move(registration_origin));
 }
 
 std::optional<AttributionDebugReport> AttributionDebugReport::Create(
@@ -515,20 +488,18 @@
     return std::nullopt;
   }
 
-  base::Value::Dict data_body;
-  data_body.Set("context_site", net::SchemefulSite(context_origin).Serialize());
-  data_body.Set("header", error.HeaderName());
-  data_body.Set("value", std::move(error.header_value));
+  constexpr DebugDataType kDataType = DebugDataType::kHeaderParsingError;
 
-  const DebugDataType data_type = DebugDataType::kHeaderParsingError;
+  RecordVerboseDebugReportType(kDataType);
 
-  base::Value::List report_body;
-  report_body.Append(GetReportData(data_type, std::move(data_body)));
-
-  RecordVerboseDebugReportType(data_type);
-
-  return AttributionDebugReport(std::move(report_body),
-                                std::move(reporting_origin));
+  return AttributionDebugReport(
+      base::Value::List::with_capacity(1).Append(GetReportData(
+          kDataType, base::Value::Dict()
+                         .Set("context_site",
+                              net::SchemefulSite(context_origin).Serialize())
+                         .Set("header", error.HeaderName())
+                         .Set("value", std::move(error.header_value)))),
+      std::move(reporting_origin));
 }
 
 AttributionDebugReport::AttributionDebugReport(
diff --git a/content/browser/back_forward_cache_basics_browsertest.cc b/content/browser/back_forward_cache_basics_browsertest.cc
index 7e6affd4..0cb2693 100644
--- a/content/browser/back_forward_cache_basics_browsertest.cc
+++ b/content/browser/back_forward_cache_basics_browsertest.cc
@@ -405,9 +405,10 @@
   RenderFrameHostImplWrapper rfh_b(popup_root->current_frame_host());
   EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
   EXPECT_EQ(2u, rfh_b->GetSiteInstance()->GetRelatedActiveContentsCount());
-  // A and B use different SiteInstances if site isolation is turned on, and
-  // shares the same SiteInstance otherwise.
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  // A and B use different SiteInstances if site isolation or default
+  // SiteInstanceGroups are turned on, and share the same SiteInstance
+  // otherwise.
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
   } else {
     EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
@@ -423,8 +424,7 @@
   // BackForwardCache, because of the opener.
   ASSERT_TRUE(NavigateToURLFromRenderer(rfh_b.get(), url_c));
 
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
-      ShouldCreateNewHostForAllFrames()) {
+  if (AreStrictSiteInstancesEnabled() || ShouldCreateNewHostForAllFrames()) {
     ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
   } else {
     ASSERT_FALSE(rfh_b->IsInBackForwardCache());
@@ -479,9 +479,10 @@
   RenderFrameHostImplWrapper rfh_b1(popup_root->current_frame_host());
   EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
   EXPECT_EQ(2u, rfh_b1->GetSiteInstance()->GetRelatedActiveContentsCount());
-  // A and B use different SiteInstances if site isolation is turned on, and
-  // shares the same SiteInstance otherwise.
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  // A and B use different SiteInstances if site isolation or default
+  // SiteInstanceGroups are turned on, and share the same SiteInstance
+  // otherwise.
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b1->GetSiteInstance());
   } else {
     EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b1->GetSiteInstance());
@@ -559,12 +560,13 @@
   EXPECT_EQ(2u, rfh_b->GetSiteInstance()->GetRelatedActiveContentsCount());
 
   // The opener A and the iframe A uses the same SiteInstance. Meanwhile, A and
-  // B use different SiteInstances if site isolation is turned on, and shares
-  // the same SiteInstance otherwise.
+  // B use different SiteInstances if site isolation or default
+  // SiteInstanceGroups are turned on, and share the same SiteInstance
+  // otherwise.
   RenderFrameHostImplWrapper rfh_a_iframe(
       rfh_b->child_at(0)->current_frame_host());
   EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_a_iframe->GetSiteInstance());
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
   } else {
     EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
@@ -582,8 +584,7 @@
   // BackForwardCache, because of the opener.
   ASSERT_TRUE(NavigateToURLFromRenderer(rfh_b.get(), url_c));
 
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
-      ShouldCreateNewHostForAllFrames()) {
+  if (AreStrictSiteInstancesEnabled() || ShouldCreateNewHostForAllFrames()) {
     ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
   } else {
     ASSERT_FALSE(rfh_b->IsInBackForwardCache());
@@ -851,8 +852,7 @@
   // 2) Navigate to B in the opener.  A1 can't enter the BackForwardCache,
   // because of the popup.
   ASSERT_TRUE(NavigateToURLFromRenderer(rfh_a1.get(), url_b));
-  if (ShouldCreateNewHostForAllFrames() ||
-      SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  if (ShouldCreateNewHostForAllFrames() || AreStrictSiteInstancesEnabled()) {
     ASSERT_TRUE(rfh_a1.WaitUntilRenderFrameDeleted());
   } else {
     ASSERT_FALSE(rfh_a1->IsInBackForwardCache());
@@ -945,7 +945,7 @@
   EXPECT_EQ(1u, rfh_a2->GetSiteInstance()->GetRelatedActiveContentsCount());
   EXPECT_FALSE(rfh_a2->GetSiteInstance()->IsRelatedSiteInstance(
       rfh_a1->GetSiteInstance()));
-  if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  if (!AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(rfh_a1->GetProcess(), rfh_a2->GetProcess());
   }
 
@@ -980,8 +980,7 @@
   // 5) Navigate to B again from A1, now A1 can't enter BackForwardCache because
   // it has related active contents.
   ASSERT_TRUE(NavigateToURLFromRenderer(rfh_a1.get(), url_b));
-  if (ShouldCreateNewHostForAllFrames() ||
-      SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+  if (ShouldCreateNewHostForAllFrames() || AreStrictSiteInstancesEnabled()) {
     ASSERT_TRUE(rfh_a1.WaitUntilRenderFrameDeleted());
   } else {
     ASSERT_FALSE(rfh_a1->IsInBackForwardCache());
diff --git a/content/browser/child_process_launcher_helper_ios.mm b/content/browser/child_process_launcher_helper_ios.mm
index 0d7ea77..c1fd96b 100644
--- a/content/browser/child_process_launcher_helper_ios.mm
+++ b/content/browser/child_process_launcher_helper_ios.mm
@@ -217,8 +217,7 @@
   std::string process_type = GetProcessType();
   std::string utility_sub_type =
       command_line()->GetSwitchValueASCII(switches::kUtilitySubType);
-  if (process_type == switches::kUtilityProcess &&
-      utility_sub_type == network::mojom::NetworkService::Name_) {
+  if (process_type == switches::kUtilityProcess) {
     void (^process_launch_complete)(BENetworkingProcess* process,
                                     NSError* error) =
         ^void(BENetworkingProcess* process, NSError* error) {
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
index 064e9300..6757bdff 100644
--- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc
+++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -839,48 +839,6 @@
       check_coordinator_;
 };
 
-AggregatableReportRequest GenerateReportRequest(
-    PrivateAggregationHost::ReportRequestGenerator generator,
-    PrivateAggregationPendingContributions::Wrapper contributions) {
-  if (!base::FeatureList::IsEnabled(
-          blink::features::kPrivateAggregationApiErrorReporting)) {
-    return std::move(generator).Run(
-        std::move(contributions.GetContributionsVector()));
-  }
-
-  EXPECT_TRUE(
-      contributions.GetPendingContributions().are_contributions_finalized());
-
-  // This function should only be used for flows that don't call
-  // `PrivateAggregationHost::ContributeToHistogramOnEvent()`.
-  EXPECT_TRUE(contributions.GetPendingContributions()
-                  .GetConditionalContributionsForTesting()
-                  .empty());
-
-  std::vector<PrivateAggregationPendingContributions::BudgeterResult>
-      all_approved(
-          /*n=*/contributions.GetPendingContributions()
-              .unconditional_contributions()
-              .size(),
-          PrivateAggregationPendingContributions::BudgeterResult::kApproved);
-
-  const std::vector<blink::mojom::AggregatableReportHistogramContribution>&
-      final_unmerged_contributions =
-          contributions.GetPendingContributions()
-              .CompileFinalUnmergedContributions(
-                  /*test_budgeter_results=*/all_approved,
-                  PrivateAggregationPendingContributions::
-                      PendingReportLimitResult::kNotAtLimit,
-                  PrivateAggregationPendingContributions::NullReportBehavior::
-                      kSendNullReport);
-
-  all_approved.resize(final_unmerged_contributions.size());
-
-  return std::move(generator).Run(
-      std::move(contributions.GetPendingContributions())
-          .TakeFinalContributions(all_approved));
-}
-
 }  // namespace
 
 // Tests the interest group management functionality of AdAuctionServiceImpl --
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index d0979b6..bb8ba1d 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -9130,8 +9130,8 @@
                 PrivateAggregationBudgetKey budget_key,
                 PrivateAggregationHost::NullReportBehavior
                     null_report_behavior) {
-              AggregatableReportRequest request = std::move(generator).Run(
-                  std::move(contributions.GetContributionsVector()));
+              AggregatableReportRequest request = GenerateReportRequest(
+                  std::move(generator), std::move(contributions));
               ASSERT_EQ(request.payload_contents().contributions.size(), 1u);
               EXPECT_EQ(request.payload_contents().contributions[0].bucket,
                         bucket);
@@ -9434,8 +9434,8 @@
               PrivateAggregationPendingContributions::Wrapper contributions,
               PrivateAggregationBudgetKey budget_key,
               PrivateAggregationHost::NullReportBehavior null_report_behavior) {
-            request_returned = std::move(generator).Run(
-                std::move(contributions.GetContributionsVector()));
+            request_returned = GenerateReportRequest(std::move(generator),
+                                                     std::move(contributions));
 
             EXPECT_EQ(budget_key.caller_api(),
                       PrivateAggregationCallerApi::kProtectedAudience);
@@ -20908,8 +20908,8 @@
               PrivateAggregationPendingContributions::Wrapper contributions,
               PrivateAggregationBudgetKey budget_key,
               PrivateAggregationHost::NullReportBehavior null_report_behavior) {
-            AggregatableReportRequest request = std::move(generator).Run(
-                std::move(contributions.GetContributionsVector()));
+            AggregatableReportRequest request = GenerateReportRequest(
+                std::move(generator), std::move(contributions));
             ASSERT_EQ(request.payload_contents().contributions.size(), 1u);
             EXPECT_EQ(request.payload_contents().contributions[0].bucket, 3);
             EXPECT_EQ(request.payload_contents().contributions[0].value, 5);
diff --git a/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm b/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
index d95972d..e1944dc 100644
--- a/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
+++ b/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
@@ -125,6 +125,14 @@
 
  private:
   void OnMouseMoved(const NSPoint& location_in_window) {
+    // Ignore mouse movements if the window is inactive or the view is hidden.
+    // This can happen if the mouse is dragged with a button pressed, as these
+    // events are not tied to the specific NSView.
+    if ((view_.window && ![view_.window isKeyWindow]) ||
+        view_.hiddenOrHasHiddenAncestor) {
+      return;
+    }
+
     const bool cursor_within_surface =
         NSPointInRect(location_in_window, NSRectFromCGRect([view_ bounds]));
 
diff --git a/content/browser/media/session/media_session_controller.cc b/content/browser/media/session/media_session_controller.cc
index cf1145d..4f3b326 100644
--- a/content/browser/media/session/media_session_controller.cc
+++ b/content/browser/media/session/media_session_controller.cc
@@ -329,7 +329,8 @@
 
 void MediaSessionController::OnAutoPictureInPictureInfoChanged(
     int player_id,
-    std::string_view auto_picture_in_picture_info) {
+    const media::PictureInPictureEventsInfo::AutoPipInfo&
+        auto_picture_in_picture_info) {
   DCHECK_EQ(player_id_, player_id);
 
   auto* observer = web_contents_->media_web_contents_observer();
@@ -338,7 +339,7 @@
   }
 
   observer->GetMediaPlayerRemote(id_)->RecordAutoPictureInPictureInfo(
-      std::string(auto_picture_in_picture_info));
+      auto_picture_in_picture_info);
 }
 
 }  // namespace content
diff --git a/content/browser/media/session/media_session_controller.h b/content/browser/media/session/media_session_controller.h
index d31d703b..e4db1a3 100644
--- a/content/browser/media/session/media_session_controller.h
+++ b/content/browser/media/session/media_session_controller.h
@@ -17,6 +17,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/media_content_type.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "services/media_session/public/cpp/media_position.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
 
@@ -84,7 +85,8 @@
   media::MediaContentType GetMediaContentType() const override;
   void OnAutoPictureInPictureInfoChanged(
       int player_id,
-      std::string_view auto_picture_in_picture_info) override;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override;
 
   // Test helpers.
   int get_player_id_for_testing() const { return player_id_; }
diff --git a/content/browser/media/session/media_session_controller_unittest.cc b/content/browser/media/session/media_session_controller_unittest.cc
index a0c4171..7bd5d805 100644
--- a/content/browser/media/session/media_session_controller_unittest.cc
+++ b/content/browser/media/session/media_session_controller_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "content/browser/media/session/media_session_controller.h"
+
 #include <memory>
 #include <tuple>
 
@@ -9,13 +11,13 @@
 #include "base/time/time.h"
 #include "content/browser/media/media_web_contents_observer.h"
 #include "content/browser/media/session/audio_focus_delegate.h"
-#include "content/browser/media/session/media_session_controller.h"
 #include "content/browser/media/session/media_session_impl.h"
 #include "content/public/browser/media_device_id.h"
 #include "content/test/mock_agent_scheduling_group_host.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
 #include "media/audio/audio_device_description.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "media/mojo/mojom/media_player.mojom.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -176,7 +178,8 @@
   }
 
   void RecordAutoPictureInPictureInfo(
-      const std::string& auto_picture_in_picture_info) override {
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {
     auto_picture_in_picture_info_ = auto_picture_in_picture_info;
     run_loop_->Quit();
   }
@@ -206,7 +209,8 @@
     return received_set_audio_sink_id_;
   }
 
-  const std::string& received_auto_picture_in_picture_info() const {
+  const media::PictureInPictureEventsInfo::AutoPipInfo&
+  received_auto_picture_in_picture_info() const {
     return auto_picture_in_picture_info_;
   }
 
@@ -223,7 +227,7 @@
   base::TimeDelta received_seek_to_time_;
   std::string received_set_audio_sink_id_;
   bool expected_visibility_ = false;
-  std::string auto_picture_in_picture_info_;
+  media::PictureInPictureEventsInfo::AutoPipInfo auto_picture_in_picture_info_;
 };
 
 // Helper class to mock `RequestVisibility` callbacks.
@@ -826,16 +830,45 @@
 }
 
 TEST_F(MediaSessionControllerTest, AutoPictureInPictureInfoChanged) {
-  EXPECT_TRUE(media_player_->received_auto_picture_in_picture_info().empty());
+  auto received_info = media_player_->received_auto_picture_in_picture_info();
+  EXPECT_EQ(received_info.auto_pip_reason,
+            media::PictureInPictureEventsInfo::AutoPipReason::kUnknown);
+  EXPECT_FALSE(received_info.has_audio_focus);
+  EXPECT_FALSE(received_info.is_playing);
+  EXPECT_FALSE(received_info.was_recently_audible);
+  EXPECT_FALSE(received_info.has_safe_url);
+  EXPECT_FALSE(received_info.meets_media_engagement_conditions);
+  EXPECT_FALSE(received_info.blocked_due_to_content_setting);
 
-  const std::string auto_picture_in_picture_info =
-      "Auto Picture In Picture Info";
+  const media::PictureInPictureEventsInfo::AutoPipInfo
+      auto_picture_in_picture_info{
+          .auto_pip_reason =
+              media::PictureInPictureEventsInfo::AutoPipReason::kMediaPlayback,
+          .has_audio_focus = true,
+          .is_playing = true,
+          .was_recently_audible = true,
+          .has_safe_url = true,
+          .meets_media_engagement_conditions = true,
+          .blocked_due_to_content_setting = true,
+      };
   controller_->OnAutoPictureInPictureInfoChanged(
       controller_->get_player_id_for_testing(), auto_picture_in_picture_info);
   media_player_->WaitUntilReceivedMessage();
+  received_info = media_player_->received_auto_picture_in_picture_info();
 
-  EXPECT_EQ(media_player_->received_auto_picture_in_picture_info(),
-            auto_picture_in_picture_info);
+  EXPECT_EQ(received_info.auto_pip_reason,
+            auto_picture_in_picture_info.auto_pip_reason);
+  EXPECT_EQ(received_info.has_audio_focus,
+            auto_picture_in_picture_info.has_audio_focus);
+  EXPECT_EQ(received_info.is_playing, auto_picture_in_picture_info.is_playing);
+  EXPECT_EQ(received_info.was_recently_audible,
+            auto_picture_in_picture_info.was_recently_audible);
+  EXPECT_EQ(received_info.has_safe_url,
+            auto_picture_in_picture_info.has_safe_url);
+  EXPECT_EQ(received_info.meets_media_engagement_conditions,
+            auto_picture_in_picture_info.meets_media_engagement_conditions);
+  EXPECT_EQ(received_info.blocked_due_to_content_setting,
+            auto_picture_in_picture_info.blocked_due_to_content_setting);
 }
 
 }  // namespace content
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index 7a3cf3f..ce4d203 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -1440,11 +1440,12 @@
 void MediaSessionImpl::ReportAutoPictureInPictureInfoChanged() {
   ContentClient* content_client = GetContentClient();
   const auto auto_picture_in_picture_info =
-      media::PictureInPictureEventsInfo::AutoPipInfoToString(
-          content_client->browser()->GetAutoPipInfo(*web_contents()));
+      media::PictureInPictureEventsInfo::AutoPipInfo{
+          content_client->browser()->GetAutoPipInfo(*web_contents())};
 
   ForAllPlayers(base::BindRepeating(
-      [](std::string_view auto_picture_in_picture_info,
+      [](const media::PictureInPictureEventsInfo::AutoPipInfo&
+             auto_picture_in_picture_info,
          const PlayerIdentifier& player) {
         player.observer->OnAutoPictureInPictureInfoChanged(
             player.player_id, auto_picture_in_picture_info);
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
index 4c91609..1ae9b89a 100644
--- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc
+++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -2,23 +2,23 @@
 // 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"
-#include "content/browser/media/session/media_session_impl.h"
-
 #include <map>
 #include <memory>
 #include <string>
 
+#include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "content/browser/media/session/media_session_impl.h"
 #include "content/browser/media/session/media_session_player_observer.h"
 #include "content/browser/media/session/mock_media_session_service_impl.h"
 #include "content/public/test/test_media_session_client.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
 #include "media/base/media_content_type.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "services/media_session/public/cpp/media_metadata.h"
 #include "services/media_session/public/cpp/test/mock_media_session.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
@@ -82,7 +82,9 @@
               (override));
   MOCK_METHOD(void,
               OnAutoPictureInPictureInfoChanged,
-              (int player_id, std::string_view auto_picture_in_picture_info),
+              (int player_id,
+               const media::PictureInPictureEventsInfo::AutoPipInfo&
+                   auto_picture_in_picture_info),
               (override));
 
   std::optional<media_session::MediaPosition> GetPosition(
diff --git a/content/browser/media/session/media_session_player_observer.h b/content/browser/media/session/media_session_player_observer.h
index 153bc33..a97da0b0 100644
--- a/content/browser/media/session/media_session_player_observer.h
+++ b/content/browser/media/session/media_session_player_observer.h
@@ -9,6 +9,7 @@
 
 #include "base/functional/callback.h"
 #include "base/time/time.h"
+#include "media/base/picture_in_picture_events_info.h"
 
 namespace media {
 enum class MediaContentType;
@@ -106,7 +107,8 @@
   // Called when the auto picture in picture information has changed.
   virtual void OnAutoPictureInPictureInfoChanged(
       int player_id,
-      std::string_view auto_picture_in_picture_info) = 0;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) = 0;
 
   // Returns the RenderFrameHost this player observer belongs to. Returns
   // nullptr if unavailable.
diff --git a/content/browser/media/session/media_session_service_impl_browsertest.cc b/content/browser/media/session/media_session_service_impl_browsertest.cc
index 30a0728f..9aa20b3 100644
--- a/content/browser/media/session/media_session_service_impl_browsertest.cc
+++ b/content/browser/media/session/media_session_service_impl_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "media/base/media_content_type.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "services/media_session/public/cpp/test/mock_media_session.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -66,7 +67,8 @@
       RequestVisibilityCallback request_visibility_callback) override {}
   void OnAutoPictureInPictureInfoChanged(
       int player_id,
-      std::string_view auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
   std::optional<media_session::MediaPosition> GetPosition(
       int player_id) const override {
diff --git a/content/browser/media/session/mock_media_session_player_observer.cc b/content/browser/media/session/mock_media_session_player_observer.cc
index 4c20210..cf8da9e 100644
--- a/content/browser/media/session/mock_media_session_player_observer.cc
+++ b/content/browser/media/session/mock_media_session_player_observer.cc
@@ -270,7 +270,8 @@
 
 void MockMediaSessionPlayerObserver::OnAutoPictureInPictureInfoChanged(
     int player_id,
-    std::string_view auto_picture_in_picture_info) {
+    const media::PictureInPictureEventsInfo::AutoPipInfo&
+        auto_picture_in_picture_info) {
   EXPECT_GE(player_id, 0);
   EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
 
diff --git a/content/browser/media/session/mock_media_session_player_observer.h b/content/browser/media/session/mock_media_session_player_observer.h
index e77074d..590d64e 100644
--- a/content/browser/media/session/mock_media_session_player_observer.h
+++ b/content/browser/media/session/mock_media_session_player_observer.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_MEDIA_SESSION_MOCK_MEDIA_SESSION_PLAYER_OBSERVER_H_
 
 #include <stddef.h>
+
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
@@ -13,6 +14,7 @@
 #include "content/browser/media/session/media_session_player_observer.h"
 #include "content/public/browser/global_routing_id.h"
 #include "media/audio/audio_device_description.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "services/media_session/public/cpp/media_position.h"
 
 namespace content {
@@ -55,7 +57,8 @@
   media::MediaContentType GetMediaContentType() const override;
   void OnAutoPictureInPictureInfoChanged(
       int player_id,
-      std::string_view auto_picture_in_picture_info) override;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override;
 
   void SetMediaContentType(media::MediaContentType media_content_type);
 
@@ -114,7 +117,8 @@
         media::AudioDeviceDescription::kDefaultDeviceId;
     bool supports_device_switching_ = true;
     bool has_sufficiently_visible_video_ = false;
-    std::string auto_picture_in_picture_info_;
+    media::PictureInPictureEventsInfo::AutoPipInfo
+        auto_picture_in_picture_info_;
     bool is_picture_in_picture_available_ = false;
   };
 
diff --git a/content/browser/media/session/pepper_player_delegate.h b/content/browser/media/session/pepper_player_delegate.h
index 91b251dd..9e5220e8 100644
--- a/content/browser/media/session/pepper_player_delegate.h
+++ b/content/browser/media/session/pepper_player_delegate.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "content/browser/media/session/media_session_player_observer.h"
+#include "media/base/picture_in_picture_events_info.h"
 
 namespace content {
 
@@ -57,7 +58,8 @@
   media::MediaContentType GetMediaContentType() const override;
   void OnAutoPictureInPictureInfoChanged(
       int player_id,
-      std::string_view auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
  private:
   void SetVolume(int player_id, double volume);
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index 029d20c6..9b372cd 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -5307,7 +5307,7 @@
       main_frame->child_at(0)->current_frame_host();
   RenderFrameHostImpl* grandchild_frame =
       child_frame->child_at(0)->current_frame_host();
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
   } else {
     EXPECT_EQ(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
@@ -5357,7 +5357,7 @@
       main_frame->child_at(0)->current_frame_host();
   RenderFrameHostImpl* grandchild_frame =
       child_frame->child_at(0)->current_frame_host();
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
   } else {
     EXPECT_EQ(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
@@ -5401,7 +5401,7 @@
       shell()->web_contents()->GetPrimaryMainFrame());
   RenderFrameHostImpl* child_frame =
       main_frame->child_at(0)->current_frame_host();
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
   } else {
     EXPECT_EQ(main_frame->GetSiteInstance(), child_frame->GetSiteInstance());
@@ -7892,7 +7892,7 @@
   // Now, the site should be set before we send the CommitNavigation IPC.
   EXPECT_TRUE(site_instance->HasSite());
 
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     // When we get into this situation with strict site isolation, the site URL
     // currently used is "about:". This may be changed in the future (e.g., to
     // an opaque ID).
diff --git a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
index 6d46524..62da0691 100644
--- a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/test/test_render_frame_host.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "media/mojo/mojom/media_player.mojom.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
@@ -146,7 +147,8 @@
   void RequestVisibility(
       RequestVisibilityCallback request_visibility_callback) override {}
   void RecordAutoPictureInPictureInfo(
-      const std::string& auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
  private:
   mojo::AssociatedReceiver<media::mojom::MediaPlayer> receiver_{this};
diff --git a/content/browser/private_aggregation/private_aggregation_host_unittest.cc b/content/browser/private_aggregation/private_aggregation_host_unittest.cc
index 83dadf4..0215ecf6 100644
--- a/content/browser/private_aggregation/private_aggregation_host_unittest.cc
+++ b/content/browser/private_aggregation/private_aggregation_host_unittest.cc
@@ -62,48 +62,6 @@
 using testing::Invoke;
 using testing::Property;
 
-AggregatableReportRequest GenerateReportRequest(
-    PrivateAggregationHost::ReportRequestGenerator generator,
-    PrivateAggregationPendingContributions::Wrapper contributions) {
-  if (!base::FeatureList::IsEnabled(
-          blink::features::kPrivateAggregationApiErrorReporting)) {
-    return std::move(generator).Run(
-        std::move(contributions.GetContributionsVector()));
-  }
-
-  EXPECT_TRUE(
-      contributions.GetPendingContributions().are_contributions_finalized());
-
-  // This function should only be used for flows that don't call
-  // `ContributeToHistogramOnEvent()`.
-  EXPECT_TRUE(contributions.GetPendingContributions()
-                  .GetConditionalContributionsForTesting()
-                  .empty());
-
-  std::vector<PrivateAggregationPendingContributions::BudgeterResult>
-      all_approved(
-          /*n=*/contributions.GetPendingContributions()
-              .unconditional_contributions()
-              .size(),
-          PrivateAggregationPendingContributions::BudgeterResult::kApproved);
-
-  const std::vector<blink::mojom::AggregatableReportHistogramContribution>&
-      final_unmerged_contributions =
-          contributions.GetPendingContributions()
-              .CompileFinalUnmergedContributions(
-                  /*test_budgeter_results=*/all_approved,
-                  PrivateAggregationPendingContributions::
-                      PendingReportLimitResult::kNotAtLimit,
-                  PrivateAggregationPendingContributions::NullReportBehavior::
-                      kSendNullReport);
-
-  all_approved.resize(final_unmerged_contributions.size());
-
-  return std::move(generator).Run(
-      std::move(contributions.GetPendingContributions())
-          .TakeFinalContributions(all_approved));
-}
-
 auto GenerateAndSaveReportRequest(
     std::optional<AggregatableReportRequest>* out) {
   return [out](PrivateAggregationHost::ReportRequestGenerator generator,
diff --git a/content/browser/private_aggregation/private_aggregation_test_utils.cc b/content/browser/private_aggregation/private_aggregation_test_utils.cc
index 8da182b..ef799da 100644
--- a/content/browser/private_aggregation/private_aggregation_test_utils.cc
+++ b/content/browser/private_aggregation/private_aggregation_test_utils.cc
@@ -6,10 +6,17 @@
 
 #include <memory>
 #include <tuple>
+#include <utility>
+#include <vector>
 
+#include "base/feature_list.h"
+#include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
 #include "content/browser/private_aggregation/private_aggregation_budget_key.h"
+#include "content/browser/private_aggregation/private_aggregation_host.h"
+#include "content/browser/private_aggregation/private_aggregation_pending_contributions.h"
 #include "content/browser/storage_partition_impl.h"
+#include "third_party/blink/public/common/features_generated.h"
 
 namespace content {
 
@@ -47,4 +54,46 @@
   return tie(a) == tie(b);
 }
 
+AggregatableReportRequest GenerateReportRequest(
+    PrivateAggregationHost::ReportRequestGenerator generator,
+    PrivateAggregationPendingContributions::Wrapper contributions) {
+  if (!base::FeatureList::IsEnabled(
+          blink::features::kPrivateAggregationApiErrorReporting)) {
+    return std::move(generator).Run(
+        std::move(contributions.GetContributionsVector()));
+  }
+
+  EXPECT_TRUE(
+      contributions.GetPendingContributions().are_contributions_finalized());
+
+  // This function should only be used for flows that don't call
+  // `ContributeToHistogramOnEvent()`.
+  EXPECT_TRUE(contributions.GetPendingContributions()
+                  .GetConditionalContributionsForTesting()
+                  .empty());
+
+  std::vector<PrivateAggregationPendingContributions::BudgeterResult>
+      all_approved(
+          /*n=*/contributions.GetPendingContributions()
+              .unconditional_contributions()
+              .size(),
+          PrivateAggregationPendingContributions::BudgeterResult::kApproved);
+
+  const std::vector<blink::mojom::AggregatableReportHistogramContribution>&
+      final_unmerged_contributions =
+          contributions.GetPendingContributions()
+              .CompileFinalUnmergedContributions(
+                  /*test_budgeter_results=*/all_approved,
+                  PrivateAggregationPendingContributions::
+                      PendingReportLimitResult::kNotAtLimit,
+                  PrivateAggregationPendingContributions::NullReportBehavior::
+                      kSendNullReport);
+
+  all_approved.resize(final_unmerged_contributions.size());
+
+  return std::move(generator).Run(
+      std::move(contributions.GetPendingContributions())
+          .TakeFinalContributions(all_approved));
+}
+
 }  // namespace content
diff --git a/content/browser/private_aggregation/private_aggregation_test_utils.h b/content/browser/private_aggregation/private_aggregation_test_utils.h
index a40ad6c..fba1591 100644
--- a/content/browser/private_aggregation/private_aggregation_test_utils.h
+++ b/content/browser/private_aggregation/private_aggregation_test_utils.h
@@ -21,6 +21,7 @@
 #include "content/browser/private_aggregation/private_aggregation_caller_api.h"
 #include "content/browser/private_aggregation/private_aggregation_host.h"
 #include "content/browser/private_aggregation/private_aggregation_manager_impl.h"
+#include "content/browser/private_aggregation/private_aggregation_pending_contributions.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/test/test_content_browser_client.h"
@@ -200,6 +201,13 @@
 bool operator==(const PrivateAggregationBudgetKey&,
                 const PrivateAggregationBudgetKey&);
 
+// Helper that correctly invokes the pending contributions object (if
+// `kPrivateAggregationApiErrorReporting` is enabled), approving all
+// contributions.
+AggregatableReportRequest GenerateReportRequest(
+    PrivateAggregationHost::ReportRequestGenerator generator,
+    PrivateAggregationPendingContributions::Wrapper contributions);
+
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_TEST_UTILS_H_
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc
index 777ff25..3a617df 100644
--- a/content/browser/renderer_host/frame_tree_browsertest.cc
+++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -2073,7 +2073,7 @@
 
   // Make sure we did a process transfer back to "b.is".
   const std::string kExpectedSiteURL =
-      AreAllSitesIsolatedForTesting()
+      AreStrictSiteInstancesEnabled()
           ? "http://a.com/"
           : SiteInstanceImpl::GetDefaultSiteURL().spec();
   const std::string kExpectedSubframeSiteURL =
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index a4ed89e2..f9b27264 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -2479,7 +2479,7 @@
   EXPECT_EQ(1, our_controller.GetEntryCount());
   EXPECT_EQ(0, our_controller.GetLastCommittedEntryIndex());
   EXPECT_FALSE(our_controller.GetPendingEntry());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(
         url,
         our_controller.GetLastCommittedEntry()->site_instance()->GetSiteURL());
@@ -2554,7 +2554,7 @@
   EXPECT_EQ(1, our_controller.GetEntryCount());
   EXPECT_EQ(0, our_controller.GetLastCommittedEntryIndex());
   EXPECT_FALSE(our_controller.GetPendingEntry());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(
         url,
         our_controller.GetLastCommittedEntry()->site_instance()->GetSiteURL());
diff --git a/content/browser/renderer_host/navigator_unittest.cc b/content/browser/renderer_host/navigator_unittest.cc
index eabb48b..22fd5f7 100644
--- a/content/browser/renderer_host/navigator_unittest.cc
+++ b/content/browser/renderer_host/navigator_unittest.cc
@@ -131,7 +131,7 @@
   EXPECT_TRUE(main_test_rfh()->IsActive());
   EXPECT_EQ(main_test_rfh()->lifecycle_state(),
             RenderFrameHostImpl::LifecycleStateImpl::kActive);
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
               main_test_rfh()->GetSiteInstance()->GetSiteInfo());
   } else {
@@ -199,7 +199,7 @@
   // Commit the navigation.
   navigation->Commit();
   EXPECT_TRUE(main_test_rfh()->IsActive());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(CreateExpectedSiteInfo(kUrl2),
               main_test_rfh()->GetSiteInstance()->GetSiteInfo());
   } else {
@@ -727,7 +727,7 @@
   TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
   ASSERT_TRUE(speculative_rfh);
   auto site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(kUrl1SiteInfo, speculative_rfh->GetSiteInstance()->GetSiteInfo());
   } else {
     EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
@@ -751,7 +751,7 @@
   ASSERT_TRUE(speculative_rfh);
   auto site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
 
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(site_instance_id_1, site_instance_id_2);
   } else {
     EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
@@ -767,7 +767,7 @@
 
   // Confirm that the commit corresponds to the new request.
   ASSERT_TRUE(main_test_rfh());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(kUrl2SiteInfo, main_test_rfh()->GetSiteInstance()->GetSiteInfo());
   } else {
     EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
@@ -1070,7 +1070,7 @@
   auto site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
   ASSERT_TRUE(speculative_rfh);
   EXPECT_NE(speculative_rfh, main_test_rfh());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
               speculative_rfh->GetSiteInstance()->GetSiteInfo());
   } else {
@@ -1110,7 +1110,7 @@
   EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
   EXPECT_NE(speculative_rfh, main_test_rfh());
 
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
               speculative_rfh->GetSiteInstance()->GetSiteInfo());
   } else {
@@ -1148,7 +1148,7 @@
   // they should be associated with different BrowsingInstances.
   EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
 
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ(CreateExpectedSiteInfo(kUrlRedirect),
               speculative_rfh->GetSiteInstance()->GetSiteInfo());
     EXPECT_NE(site_instance_id, redirect_site_instance_id);
@@ -1296,7 +1296,7 @@
     EXPECT_NE(current_instance, related_instance.get());
     EXPECT_NE(unrelated_instance.get(), related_instance.get());
 
-    if (AreAllSitesIsolatedForTesting()) {
+    if (AreStrictSiteInstancesEnabled()) {
       EXPECT_EQ(SiteInfo::CreateForTesting(
                     current_instance->GetIsolationContext(), kUrlSameSiteAs2),
                 related_instance->GetSiteInfo());
@@ -1359,7 +1359,7 @@
     EXPECT_NE(related_instance.get(), converted_instance_1.get());
     EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
 
-    if (AreAllSitesIsolatedForTesting()) {
+    if (AreStrictSiteInstancesEnabled()) {
       EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs2),
                 converted_instance_1->GetSiteInfo());
     } else {
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index c007f669..8ba44847 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -838,6 +838,13 @@
 
     // There are two active views on google.com now.
     EXPECT_EQ(instance1->group()->active_frame_count(), 2U);
+  } else if (ShouldUseDefaultSiteInstanceGroup()) {
+    // If default SiteInstanceGroups are used, the SiteInstances should be
+    // different, but active frame count is per group, so the active frame count
+    // is the same as that of default SiteInstance.
+    EXPECT_EQ(instance1->group()->active_frame_count(), 3U);
+    EXPECT_EQ(instance1->group(), instance2->group());
+    EXPECT_NE(instance1, instance2);
   } else {
     EXPECT_TRUE(instance1->IsDefaultSiteInstance());
     EXPECT_EQ(instance1->group()->active_frame_count(), 3U);
@@ -1348,7 +1355,7 @@
   scoped_refptr<SiteInstanceImpl> site_instance1 = rfh1->GetSiteInstance();
   RenderFrameDeletedObserver rfh1_deleted_observer(rfh1);
   TestRenderViewHost* rvh1 = test_rvh();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create 2 new tabs and simulate them being the opener chain for the main
@@ -1422,7 +1429,7 @@
   contents()->NavigateAndCommit(kUrl1);
   TestRenderFrameHost* rfh1 = main_test_rfh();
   scoped_refptr<SiteInstanceImpl> site_instance1 = rfh1->GetSiteInstance();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create a new tab and simulate having it be the opener for the main tab.
@@ -1475,7 +1482,7 @@
   contents()->NavigateAndCommit(kUrl1);
   scoped_refptr<SiteInstanceImpl> site_instance1 =
       main_test_rfh()->GetSiteInstance();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create a new tab and simulate having it be the opener for the main tab.
@@ -1520,7 +1527,7 @@
   contents()->NavigateAndCommit(kUrl1);
   scoped_refptr<SiteInstanceImpl> site_instance1 =
       main_test_rfh()->GetSiteInstance();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create a new tab and simulate having it be the opener for the main tab.
@@ -1666,7 +1673,7 @@
   EXPECT_NE(host, initial_host);
   // This test may run without strict site isolation, e.g. on Android.  In
   // that case, the navigation will end up in a default SiteInstance.
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_EQ("http://google.com/",
               first_instance->GetSiteInfo().site_url().spec());
   } else {
@@ -1698,7 +1705,7 @@
 
   // The first RenderFrameHost will be reused only when there's no site
   // isolation between the two sites.
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(host, manager->current_frame_host());
     EXPECT_TRUE(manager->speculative_frame_host());
   } else {
@@ -1712,7 +1719,7 @@
   ASSERT_TRUE(host);
   EXPECT_TRUE(host->GetSiteInstance()->IsGuest());
 
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(host->GetSiteInstance(), first_instance);
     EXPECT_EQ("http://chromium.org/",
               host->GetSiteInstance()->GetSiteInfo().site_url().spec());
@@ -2543,7 +2550,7 @@
   contents()->NavigateAndCommit(kUrl1);
   TestRenderFrameHost* rfh1 = main_test_rfh();
   scoped_refptr<SiteInstanceImpl> site_instance1 = rfh1->GetSiteInstance();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create 2 new tabs and construct the opener chain as follows:
@@ -2613,7 +2620,7 @@
   contents()->NavigateAndCommit(kUrl1);
   TestRenderFrameHost* rfh1 = main_test_rfh();
   scoped_refptr<SiteInstanceImpl> site_instance1 = rfh1->GetSiteInstance();
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             site_instance1->IsDefaultSiteInstance());
 
   // Create an opener tab, and simulate that its opener points to itself.
@@ -3919,7 +3926,7 @@
       main_test_rfh()->GetSiteInstance();
   SiteInfo foo_site_info = SiteInfo::CreateForTesting(
       initial_instance->GetIsolationContext(), kFooUrl);
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_FALSE(initial_instance->IsDefaultSiteInstance());
     EXPECT_EQ(kFooUrl, initial_instance->original_url());
     EXPECT_EQ(foo_site_info, initial_instance->GetSiteInfo());
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc
index 67b595d..928c97a 100644
--- a/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -928,7 +928,7 @@
   site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting(
       browser_context(), kRedirectUrl2);
   EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(speculative_process_host_id,
               site_instance->GetProcess()->GetDeprecatedID());
   } else {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 749dbef..fe352434 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -231,6 +231,7 @@
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_ANDROID)
+#include "base/android/build_info.h"
 #include "base/check.h"
 #include "content/browser/android/java_interfaces_impl.h"
 #include "content/browser/android/nfc_host.h"
@@ -3657,6 +3658,13 @@
   prefs.payment_request_enabled =
       base::FeatureList::IsEnabled(features::kWebPayments);
 
+#if BUILDFLAG(IS_ANDROID)
+  if (base::FeatureList::IsEnabled(features::kWebauthnDisabledOnAuto) &&
+      base::android::BuildInfo::GetInstance()->is_automotive()) {
+    prefs.disable_webauthn = true;
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+
   GetContentClient()->browser()->OverrideWebPreferences(
       this, *main_frame->GetSiteInstance(), &prefs);
   return prefs;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 333ce74..87f8472 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -909,7 +909,7 @@
   main_test_rfh()->GetSiteInstance()->group()->IncrementActiveFrameCount();
 
   EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_TRUE(
         contents()->GetSiteInstance()->GetSiteURL().DomainIs("google.com"));
   } else {
@@ -1012,13 +1012,13 @@
 
   EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
   EXPECT_TRUE(orig_instance->HasSite());
-  EXPECT_EQ(!AreAllSitesIsolatedForTesting(),
+  EXPECT_EQ(!AreStrictSiteInstancesEnabled(),
             orig_instance->IsDefaultSiteInstance());
 
   // Navigate to another site and verify that a new SiteInstance was created.
   const GURL url("http://www.google.com");
   NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
-  if (AreAllSitesIsolatedForTesting()) {
+  if (AreStrictSiteInstancesEnabled()) {
     EXPECT_NE(orig_instance, contents()->GetSiteInstance());
   } else {
     // Verify this remains the default SiteInstance since |url| does
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index 2a8d2443..30f529e 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -2471,11 +2471,10 @@
   // should enforce this check before all requests but users typically won't
   // have time to disable the FedCM API in other types of requests.
   // Note that for the active flow is not affected by the permission status.
-  if (GetApiPermissionStatus() != FederatedApiPermissionStatus::GRANTED &&
-      rp_mode_ != RpMode::kActive) {
+  if (!CanBypassPermissionStatusCheck(rp_mode_, mediation_requirement_) &&
+      GetApiPermissionStatus() != FederatedApiPermissionStatus::GRANTED) {
     CompleteRequestWithError(FederatedAuthRequestResult::kDisabledInSettings,
                              TokenStatus::kDisabledInSettings,
-
                              /*should_delay_callback=*/true);
     return;
   }
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index f78e6732..cadb96f 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -28,6 +28,7 @@
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/threading/platform_thread.h"
+#include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "base/timer/hi_res_timer_manager.h"
 #include "base/trace_event/trace_event.h"
@@ -44,6 +45,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/result_codes.h"
+#include "content/public/common/zygote/zygote_buildflags.h"
 #include "content/public/gpu/content_gpu_client.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/config/gpu_driver_bug_list.h"
@@ -59,6 +61,7 @@
 #include "media/gpu/buildflags.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
 #include "services/tracing/public/cpp/trace_startup.h"
 #include "services/tracing/public/cpp/trace_startup_config.h"
 #include "third_party/angle/src/gpu_info_util/SystemInfo.h"
@@ -196,11 +199,8 @@
 
 // Main function for starting the Gpu process.
 int GpuMain(MainFunctionParams parameters) {
-  if (tracing::TraceStartupConfig::GetInstance().IsEnabled()) {
-    gl::StartupTrace::Startup();
-  }
+  TRACE_EVENT("gpu,startup", "GpuMain");
 
-  TRACE_EVENT0("gpu", "GpuMain");
   base::CurrentProcess::GetInstance().SetProcessType(
       base::CurrentProcessType::PROCESS_GPU);
 
@@ -310,7 +310,6 @@
             base::MessagePumpType::DEFAULT);
 #endif
   }
-  gl::StartupTrace::GetInstance()->BindToCurrentThread();
 
   base::PlatformThread::SetName("CrGpuMain");
   mojo::InterfaceEndpointClient::SetThreadNameSuffixForMetrics("GpuMain");
@@ -436,7 +435,6 @@
   }
 
   DCHECK(tracing::IsTracingInitialized());
-  gl::StartupTrace::StarupDone();
 
   {
     TRACE_EVENT0("gpu", "Run Message Loop");
@@ -460,6 +458,14 @@
     sandbox::policy::SandboxLinux::GetInstance()->StopThread(watchdog_thread);
   }
 
+  base::Thread* trace_thread =
+      tracing::IsTracingInitialized()
+          ? tracing::PerfettoTracedProcess::GetTraceThread()
+          : nullptr;
+  if (trace_thread) {
+    sandbox::policy::SandboxLinux::GetInstance()->StopThread(trace_thread);
+  }
+
   // SandboxLinux::InitializeSandbox() must always be called
   // with only one thread.
   sandbox::policy::SandboxLinux::Options sandbox_options;
@@ -509,6 +515,10 @@
     watchdog_thread->Start();
   }
 
+  if (trace_thread) {
+    tracing::PerfettoTracedProcess::Get().RestartThreadInSandbox();
+  }
+
   return res;
 }
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java
index dc16c97..88782c45 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java
@@ -28,6 +28,7 @@
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.BaseSwitches;
+import org.chromium.base.FeatureOverrides;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LibraryProcessType;
@@ -39,6 +40,7 @@
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content_public.browser.ChildProcessImportance;
+import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner;
 import org.chromium.content_shell_apk.ChildProcessLauncherTestHelperService;
 import org.chromium.content_shell_apk.ChildProcessLauncherTestUtils;
@@ -431,6 +433,11 @@
         if (!ChildProcessConnection.supportNotPerceptibleBinding()) {
             return;
         }
+        FeatureOverrides.overrideParam(
+                ContentFeatureList.sSpareRendererAddNotPerceptibleBinding.getFeatureName(),
+                ContentFeatureList.sSpareRendererAddNotPerceptibleBinding.getName(),
+                true);
+
         ChildProcessLauncherHelperImpl.setSkipDelayForReducePriorityOnBackgroundForTesting();
 
         final ContentShellActivity activity =
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
index bc861ba..c1c4f55 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -215,13 +215,15 @@
     @Test
     @SmallTest
     public void test_addHiddenAttributeSubtree() {
-        performTest("add-hidden-attribute-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "add-hidden-attribute-subtree.html",
+                "add-hidden-attribute-subtree-expected-android.txt");
     }
 
     @Test
     @SmallTest
     public void test_addSubtree() {
-        performTest("add-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest("add-subtree.html", "add-subtree-expected-android.txt");
     }
 
     @Test
@@ -666,7 +668,7 @@
     @Test
     @SmallTest
     public void test_deleteSubtree() {
-        performTest("delete-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest("delete-subtree.html", "delete-subtree-expected-android.txt");
     }
 
     @Test
@@ -686,7 +688,9 @@
     @Test
     @SmallTest
     public void test_descriptionChangedSubtree() {
-        performTest("description-changed-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "description-changed-subtree.html",
+                "description-changed-subtree-expected-android.txt");
     }
 
     @Test
@@ -1036,13 +1040,15 @@
     @Test
     @SmallTest
     public void test_removeHiddenAttributeSubtree() {
-        performTest("remove-hidden-attribute-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "remove-hidden-attribute-subtree.html",
+                "remove-hidden-attribute-subtree-expected-android.txt");
     }
 
     @Test
     @SmallTest
     public void test_removeSubtree() {
-        performTest("remove-subtree.html", EMPTY_EXPECTATIONS_FILE);
+        performTest("remove-subtree.html", "remove-subtree-expected-android.txt");
     }
 
     @Test
@@ -1101,19 +1107,25 @@
     @Test
     @SmallTest
     public void test_subtreeReparentedIgnoredChanged() {
-        performTest("subtree-reparented-ignored-changed.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "subtree-reparented-ignored-changed.html",
+                "subtree-reparented-ignored-changed-expected-android.txt");
     }
 
     @Test
     @SmallTest
     public void test_subtreeReparentedViaAppendChild() {
-        performTest("subtree-reparented-via-append-child.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "subtree-reparented-via-append-child.html",
+                "subtree-reparented-via-append-child-expected-android.txt");
     }
 
     @Test
     @SmallTest
     public void test_subtreeReparentedViaAriaOwns() {
-        performTest("subtree-reparented-via-aria-owns.html", EMPTY_EXPECTATIONS_FILE);
+        performTest(
+                "subtree-reparented-via-aria-owns.html",
+                "subtree-reparented-via-aria-owns-expected-android.txt");
     }
 
     @Test
diff --git a/content/public/browser/url_data_source.cc b/content/public/browser/url_data_source.cc
index 577a8e7..44ed1d0b 100644
--- a/content/public/browser/url_data_source.cc
+++ b/content/public/browser/url_data_source.cc
@@ -101,6 +101,7 @@
     case network::mojom::CSPDirectiveName::Sandbox:
     case network::mojom::CSPDirectiveName::ScriptSrcAttr:
     case network::mojom::CSPDirectiveName::ScriptSrcElem:
+    case network::mojom::CSPDirectiveName::ScriptSrcV2:
     case network::mojom::CSPDirectiveName::StyleSrc:
     case network::mojom::CSPDirectiveName::StyleSrcAttr:
     case network::mojom::CSPDirectiveName::StyleSrcElem:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 958164f..688b749 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -980,12 +980,14 @@
     "ServiceWorkerStaticRouterRaceNetworkRequestPerformanceImprovement",
     base::FEATURE_DISABLED_BY_DEFAULT);
 
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 // Run video capture service in the Browser process as opposed to a dedicated
 // utility process.
 BASE_FEATURE(kRunVideoCaptureServiceInBrowserProcess,
              "RunVideoCaptureServiceInBrowserProcess",
              base::FEATURE_DISABLED_BY_DEFAULT
 );
+#endif
 
 // Update scheduler settings using resourced on ChromeOS.
 BASE_FEATURE(kSchedQoSOnResourcedForChrome,
@@ -1441,6 +1443,14 @@
 
 #endif  // BUILDFLAG(IS_MAC)
 
+#if BUILDFLAG(IS_ANDROID)
+// Disables WebAuthn on Android Auto. Default enabled in M137, remove in or
+// after M140.
+BASE_FEATURE(kWebauthnDisabledOnAuto,
+             "WebAuthenticationDisabledOnAuto",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 // Default amount of days after which the global navigation capturing IPH
 // guardrails are cleared from storage.
 const base::FeatureParam<int> kNavigationCapturingIPHGuardrailStorageDuration{
@@ -1474,7 +1484,7 @@
 };
 
 VideoCaptureServiceConfiguration GetVideoCaptureServiceConfiguration() {
-#if BUILDFLAG(IS_ANDROID)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
   return VideoCaptureServiceConfiguration::kEnabledForBrowserProcess;
 #else
   return base::FeatureList::IsEnabled(
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 0f5338b..0edbbe2 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -222,7 +222,9 @@
     kProcessPerSiteMainFrameSiteScalingFactor;
 CONTENT_EXPORT extern const base::FeatureParam<double>
     kProcessPerSiteMainFrameTotalMemoryLimit;
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kRunVideoCaptureServiceInBrowserProcess);
+#endif
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSchedQoSOnResourcedForChrome);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSecurePaymentConfirmation);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSecurePaymentConfirmationDebug);
@@ -320,6 +322,10 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kSonomaAccessibilityActivationRefinements);
 #endif  // BUILDFLAG(IS_MAC)
 
+#if BUILDFLAG(IS_ANDROID)
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebauthnDisabledOnAuto);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 // Number of days to "store" IPH guardrails for navigation captured app launches
 // till they are cleared.
 CONTENT_EXPORT extern const base::FeatureParam<int>
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/transit/HtmlElement.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/transit/HtmlElement.java
index ff7c969..7f31a34d 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/transit/HtmlElement.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/transit/HtmlElement.java
@@ -10,6 +10,7 @@
 import org.chromium.base.test.transit.Condition;
 import org.chromium.base.test.transit.ConditionWithResult;
 import org.chromium.base.test.transit.Element;
+import org.chromium.base.test.transit.Transition;
 import org.chromium.base.test.transit.TravelException;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.transit.HtmlConditions.DisplayedCondition;
@@ -42,22 +43,27 @@
         return new NotDisplayedCondition(mWebContentsSupplier, mHtmlElementSpec.getHtmlId());
     }
 
-    /** Click the HTML element to trigger a Transition. */
-    public void click() {
-        try {
-            DOMUtils.clickNode(mWebContentsSupplier.get(), mHtmlElementSpec.getHtmlId());
-        } catch (TimeoutException e) {
-            throw TravelException.newTravelException("Timed out trying to click DOM element", e);
-        }
+    /** Returns a trigger to click the HTML element to trigger a Transition. */
+    public Transition.Trigger getClickTrigger() {
+        return () -> {
+            try {
+                DOMUtils.clickNode(mWebContentsSupplier.get(), mHtmlElementSpec.getHtmlId());
+            } catch (TimeoutException e) {
+                throw TravelException.newTravelException(
+                        "Timed out trying to click DOM element", e);
+            }
+        };
     }
 
-    /** Long press the HTML element to trigger a Transition. */
-    public void longPress() {
-        try {
-            DOMUtils.longPressNode(mWebContentsSupplier.get(), mHtmlElementSpec.getHtmlId());
-        } catch (TimeoutException e) {
-            throw TravelException.newTravelException(
-                    "Timed out trying to long press DOM element", e);
-        }
+    /** Returns a trigger to long press the HTML element to trigger a Transition. */
+    public Transition.Trigger getLongPressTrigger() {
+        return () -> {
+            try {
+                DOMUtils.longPressNode(mWebContentsSupplier.get(), mHtmlElementSpec.getHtmlId());
+            } catch (TimeoutException e) {
+                throw TravelException.newTravelException(
+                        "Timed out trying to long press DOM element", e);
+            }
+        };
     }
 }
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist
index e38a8e6..7827fa50 100644
--- a/content/test/content_test_bundle_data.filelist
+++ b/content/test/content_test_bundle_data.filelist
@@ -2149,6 +2149,8 @@
 data/accessibility/css/reading-flow-pseudo-elements.html
 data/accessibility/css/reading-flow-shadow-dom-slot-expected-blink.txt
 data/accessibility/css/reading-flow-shadow-dom-slot.html
+data/accessibility/css/reading-flow-scroll-marker-expected-blink.txt
+data/accessibility/css/reading-flow-scroll-marker.html
 data/accessibility/css/reading-flow.html
 data/accessibility/css/table-cell-bad-parent-expected-blink.txt
 data/accessibility/css/table-cell-bad-parent.html
@@ -2256,10 +2258,12 @@
 data/accessibility/event/add-dialog.html
 data/accessibility/event/add-hidden-attribute-expected-auralinux.txt
 data/accessibility/event/add-hidden-attribute-expected-win.txt
+data/accessibility/event/add-hidden-attribute-subtree-expected-android.txt
 data/accessibility/event/add-hidden-attribute-subtree-expected-auralinux.txt
 data/accessibility/event/add-hidden-attribute-subtree-expected-win.txt
 data/accessibility/event/add-hidden-attribute-subtree.html
 data/accessibility/event/add-hidden-attribute.html
+data/accessibility/event/add-subtree-expected-android.txt
 data/accessibility/event/add-subtree-expected-auralinux.txt
 data/accessibility/event/add-subtree-expected-uia-win.txt
 data/accessibility/event/add-subtree-expected-win.txt
@@ -2536,6 +2540,7 @@
 data/accessibility/event/css-visibility-descendants.html
 data/accessibility/event/css-visibility-expected-win.txt
 data/accessibility/event/css-visibility.html
+data/accessibility/event/delete-subtree-expected-android.txt
 data/accessibility/event/delete-subtree-expected-auralinux.txt
 data/accessibility/event/delete-subtree.html
 data/accessibility/event/description-change-expected-auralinux.txt
@@ -2551,6 +2556,7 @@
 data/accessibility/event/description-change.html
 data/accessibility/event/description-changed-pane-title-expected-android.txt
 data/accessibility/event/description-changed-pane-title.html
+data/accessibility/event/description-changed-subtree-expected-android.txt
 data/accessibility/event/description-changed-subtree.html
 data/accessibility/event/disabled-state-changed-expected-auralinux.txt
 data/accessibility/event/disabled-state-changed-expected-win.txt
@@ -2755,10 +2761,12 @@
 data/accessibility/event/remove-child.html
 data/accessibility/event/remove-hidden-attribute-expected-auralinux.txt
 data/accessibility/event/remove-hidden-attribute-expected-win.txt
+data/accessibility/event/remove-hidden-attribute-subtree-expected-android.txt
 data/accessibility/event/remove-hidden-attribute-subtree-expected-auralinux.txt
 data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt
 data/accessibility/event/remove-hidden-attribute-subtree.html
 data/accessibility/event/remove-hidden-attribute.html
+data/accessibility/event/remove-subtree-expected-android.txt
 data/accessibility/event/remove-subtree-expected-win.txt
 data/accessibility/event/remove-subtree.html
 data/accessibility/event/reparent-element-with-active-descendant-expected-android.txt
@@ -2803,14 +2811,17 @@
 data/accessibility/event/style-changed-expected-uia-win.txt
 data/accessibility/event/style-changed-expected-win.txt
 data/accessibility/event/style-changed.html
+data/accessibility/event/subtree-reparented-ignored-changed-expected-android.txt
 data/accessibility/event/subtree-reparented-ignored-changed-expected-auralinux.txt
 data/accessibility/event/subtree-reparented-ignored-changed.html
+data/accessibility/event/subtree-reparented-via-append-child-expected-android.txt
 data/accessibility/event/subtree-reparented-via-append-child-expected-auralinux.txt
 data/accessibility/event/subtree-reparented-via-append-child-expected-mac.txt
 data/accessibility/event/subtree-reparented-via-append-child-expected-uia-win.txt
 data/accessibility/event/subtree-reparented-via-append-child-expected-win.txt
 data/accessibility/event/subtree-reparented-via-append-child.html
 data/accessibility/event/subtree-reparented-via-aria-owns-2.html
+data/accessibility/event/subtree-reparented-via-aria-owns-expected-android.txt
 data/accessibility/event/subtree-reparented-via-aria-owns-expected-auralinux-2.txt
 data/accessibility/event/subtree-reparented-via-aria-owns-expected-auralinux.txt
 data/accessibility/event/subtree-reparented-via-aria-owns-expected-mac.txt
diff --git a/content/test/data/accessibility/css/reading-flow-scroll-marker-expected-blink.txt b/content/test/data/accessibility/css/reading-flow-scroll-marker-expected-blink.txt
new file mode 100644
index 0000000..0552e39
--- /dev/null
+++ b/content/test/data/accessibility/css/reading-flow-scroll-marker-expected-blink.txt
@@ -0,0 +1,17 @@
+rootWebArea focusable
+++genericContainer ignored
+++++genericContainer ignored
+++++++genericContainer
+++++++++genericContainer focusable
+++++++++++staticText name='One'
+++++++++++++inlineTextBox name='One'
+++++++++genericContainer focusable
+++++++++++staticText name='Two'
+++++++++++++inlineTextBox name='Two'
+++++++++genericContainer focusable
+++++++++++staticText name='Three'
+++++++++++++inlineTextBox name='Three'
+++++++tabList horizontal setSize=3
+++++++++tab focusable name='Two' setSize=3 posInSet=1 selected=false
+++++++++tab focusable name='Three' setSize=3 posInSet=2 selected=false
+++++++++tab focusable name='One' setSize=3 posInSet=3 selected=true
diff --git a/content/test/data/accessibility/css/reading-flow-scroll-marker.html b/content/test/data/accessibility/css/reading-flow-scroll-marker.html
new file mode 100644
index 0000000..1e80113
--- /dev/null
+++ b/content/test/data/accessibility/css/reading-flow-scroll-marker.html
@@ -0,0 +1,80 @@
+<!--
+@BLINK-ALLOW:setSize*
+@BLINK-ALLOW:posInSet*
+@BLINK-ALLOW:focusable*
+-->
+<!doctype html>
+
+<style>
+.carousel {
+  overflow-x: auto;
+  columns: 1;
+  height: 200px;
+  width: 200px;
+
+  display: grid;
+  grid-auto-flow: column;
+  reading-flow: grid-order;
+
+  scroll-marker-group: after;
+
+  /* Scroll marker group is generated on the .carousel element */
+  &::scroll-marker-group {
+    height: 1rem;
+    width: 100%;
+  }
+
+  /* These are div items children within the carousel */
+  & > div {
+    height: 100%;
+    width: 300px;
+
+    /* Request a scroll marker for this element by setting non-none content */
+    &::scroll-marker {
+      display: inline-block;
+      width: 3rem;
+      border: 1px solid black;
+    }
+    /* The currently selected scroll marker should be blue */
+    &::scroll-marker:target-current {
+      background: blue;
+    }
+  }
+}
+
+#One {
+  order: 1;
+  &::scroll-marker {
+    content: 'One' / 'One';
+  }
+}
+#Two {
+  order: 2;
+  &::scroll-marker {
+    content: 'Two' /  'Two';
+  }
+}
+#Three {
+  order: 3;
+  &::scroll-marker {
+    content: 'Three' / 'Three';
+  }
+}
+</style>
+
+<!--- Test reading flow for grid items re-ordered using CSS property order.
+The reading flow container is a carousel scroller with scroll-markers.
+
+Expect order to be:
+One  -> Two  -> Three
+
+// TODO(crbug.com/413659838)
+Note that currently, ::scroll-marker recognize its parent as display: block and
+the CSS order property does not take into effect.
+-->
+
+<div class=carousel>
+ <div id="Two" tabindex="0">Two</div>
+ <div id="Three" tabindex="0">Three</div>
+ <div id="One" tabindex="0">One</div>
+</div>
diff --git a/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-android.txt b/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/add-hidden-attribute-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/add-subtree-expected-android.txt b/content/test/data/accessibility/event/add-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/add-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/delete-subtree-expected-android.txt b/content/test/data/accessibility/event/delete-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/delete-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/description-changed-subtree-expected-android.txt b/content/test/data/accessibility/event/description-changed-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/description-changed-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-android.txt b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/remove-subtree-expected-android.txt b/content/test/data/accessibility/event/remove-subtree-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/remove-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/subtree-reparented-ignored-changed-expected-android.txt b/content/test/data/accessibility/event/subtree-reparented-ignored-changed-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/subtree-reparented-ignored-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/subtree-reparented-via-append-child-expected-android.txt b/content/test/data/accessibility/event/subtree-reparented-via-append-child-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/subtree-reparented-via-append-child-expected-android.txt
diff --git a/content/test/data/accessibility/event/subtree-reparented-via-aria-owns-expected-android.txt b/content/test/data/accessibility/event/subtree-reparented-via-aria-owns-expected-android.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/accessibility/event/subtree-reparented-via-aria-owns-expected-android.txt
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index f12b1c25..358a806 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -585,6 +585,7 @@
 crbug.com/373852610 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ]
 crbug.com/407945675 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance2/wasm/texsubimage2d-16gb-wasm-memory.html [ Failure ]
 crbug.com/408364836 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/data/gles3/shaders/linkage.html [ RetryOnFailure ]
+crbug.com/373852610 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance2/wasm/getbuffersubdata-16gb-wasm-memory.html [ RetryOnFailure ]
 
 # Graphite
 crbug.com/332745399 [ win graphite-enabled ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
diff --git a/device/base/features.cc b/device/base/features.cc
index d10a101..2565670 100644
--- a/device/base/features.cc
+++ b/device/base/features.cc
@@ -44,5 +44,13 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+// Controls whether to override LocationRequest parameters in
+// LocationProviderGmsCore
+BASE_FEATURE(kGmsCoreLocationRequestParamOverride,
+             "GmsCoreLocationRequestParamOverride",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 }  // namespace features
 }  // namespace device
diff --git a/device/base/features.h b/device/base/features.h
index 65dcaba..2690a3b 100644
--- a/device/base/features.h
+++ b/device/base/features.h
@@ -34,6 +34,10 @@
 DEVICE_BASE_EXPORT BASE_DECLARE_FEATURE(kSerial);
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+DEVICE_BASE_EXPORT BASE_DECLARE_FEATURE(kGmsCoreLocationRequestParamOverride);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 }  // namespace features
 }  // namespace device
 
diff --git a/docs/rust.md b/docs/rust.md
index fd4d4236..8d77cf2 100644
--- a/docs/rust.md
+++ b/docs/rust.md
@@ -64,8 +64,8 @@
      `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
    * This will also apply any patches in `//third_party/rust/chromium_crates_io/patches`
      for the crates. If a patch can not apply, the crate's download will be cancelled and
-     an error will be printed. See [patching errors](#patching-errors) below for how to resolve
-     this.
+     an error will be printed. See
+     `//third_party/rust/chromium_crates_io/patches/README.md` for more details.
 1. (optional) If the crate is only to be used by tests and tooling, then
    specify the `"test"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`:
    ```
@@ -92,49 +92,6 @@
 bar = { version = "3", features = [ "spaceships" ] }
 ```
 
-### Patching third-party crates
-
-You may patch a crate in tree, but save any changes made into a diff file in
-a `//third_party/rust/chromium_crates_io/patches/` directory for the crate.
-The diff file should be generated by `git-format-patch` each new patch numbered
-consecutively so that they can be applied in order. For example, these files
-might exist if the "foo" crate was patched with a couple of changes:
-
-```
-//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Edit-the-Cargo-toml.diff
-//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
-```
-
-Patches are applied with `-p6 --directory
-third_party/rust/chromium_crates_io/vendor/<crate>-<version>`, effectively
-ignoring the version numbers in the patch files.
-
-The recommended procedure to create such patches is:
-
-1. Commit the plain new version of the crate to your local git branch
-2. Modify the crate as necessary
-3. Commit that modified version
-4. Use `git format-patch <unpatched version>` to generate the patch files
-5. Add the patch files in a new, third, commit
-6. Squash them, or rely on `git cl upload` doing so
-
-#### Patching errors
-
-If `gnrt vendor` fails to apply a patch for a crate, it will cancel the download of that
-crate rather than leave it in a broken state. To recreate patches, first get a pristine
-copy of the crate by using the `--no-patches` argument:
-
-1. Download the crate without applying patches:
-   * `vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>`
-2. Then recreate the patches as described in [Patching third-party crates](
-   #patching-third_party-crates).
-
-To verify the patches work, remove the vendored crate directory in
-`//third_party/rust/chromium_crates_io/vendor/`, named after the crate name
-and version. Then run the `vendor` action without `--no-patches` which will
-download the crate and apply the patches:
-   * `vpython3 ./tools/crates/run_gnrt.py vendor`
-
 ## Security
 
 If a shipping library needs security review (has any `unsafe`), and the review
@@ -198,7 +155,7 @@
                 foo-3.4.2  (crate sources downloaded from crates.io)
             patches/
                 foo/  (patches for the "foo" crate)
-                    0001-Edit-the-Cargo-toml.diff
+                    0001-Some-changes.diff
                     0002-Other-changes.diff
             Cargo.toml
             Cargo.lock
diff --git a/docs/speed/perf_lab_platforms.md b/docs/speed/perf_lab_platforms.md
index 24717ac..b39a068 100644
--- a/docs/speed/perf_lab_platforms.md
+++ b/docs/speed/perf_lab_platforms.md
@@ -36,6 +36,7 @@
  * [mac-m1_mini_2020-perf](https://ci.chromium.org/p/chrome/builders/ci/mac-m1_mini_2020-perf): Mac M1 Mini 2020.
  * [mac-m1_mini_2020-perf-pgo](https://ci.chromium.org/p/chrome/builders/ci/mac-m1_mini_2020-perf-pgo): Mac M1 Mini 2020.
  * [mac-m2-pro-perf](https://ci.chromium.org/p/chrome/builders/ci/mac-m2-pro-perf): Mac M2 PRO Baremetal ARM.
+ * [mac-m3-pro-perf](https://ci.chromium.org/p/chrome/builders/ci/mac-m3-pro-perf): Mac M3 PRO ARM.
 
 ### Win
 
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md
index 5a7a5cf..aeddb9e 100644
--- a/docs/threading_and_tasks.md
+++ b/docs/threading_and_tasks.md
@@ -54,8 +54,6 @@
 [4]: https://source.chromium.org/chromium/chromium/src/+/main:base/sequence_checker.h
 [5]: https://source.chromium.org/chromium/chromium/src/+/main:base/threading/sequence_bound.h
 
-### Nomenclature
-
 ## Core Concepts
  * **Task**: A unit of work to be processed. Effectively a function pointer with
    optionally associated state. In Chrome this is `base::OnceCallback` and
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 7e177e0..06bbe07 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -2473,6 +2473,7 @@
     bool needs_sort_ordinal,
     const syncer::StringOrdinal& suggested_page_ordinal,
     prefs::DictionaryValueUpdate* extension_dict) {
+  CHECK(extension_dict);
   // Reinitializes various preferences with empty dictionaries.
   if (!extension_dict->HasKey(pref_names::kPrefPreferences)) {
     extension_dict->Set(pref_names::kPrefPreferences,
@@ -2512,6 +2513,7 @@
   // are updated non-transactionally. This is probably not fixable without
   // nested transactional updates to pref dictionaries.
   if (needs_sort_ordinal) {
+    CHECK(app_sorting());
     app_sorting()->EnsureValidOrdinals(extension_id, suggested_page_ordinal);
   }
 
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
index 6850290..e6c5e2f7 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -336,10 +336,25 @@
   void EndReadAccess(gfx::GpuFenceHandle release_fence) final {
     return wrapped_->EndReadAccess(std::move(release_fence));
   }
-#if BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_ANDROID)
+  AHardwareBuffer* GetAHardwareBuffer() final {
+    return wrapped_->GetAHardwareBuffer();
+  }
+  std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
+  GetAHardwareBufferFenceSync() final {
+    return wrapped_->GetAHardwareBufferFenceSync();
+  }
+#elif BUILDFLAG(IS_WIN)
   std::optional<gl::DCLayerOverlayImage> GetDCLayerOverlayImage() final {
     return wrapped_->GetDCLayerOverlayImage();
   }
+#elif BUILDFLAG(IS_APPLE)
+  gfx::ScopedIOSurface GetIOSurface() const final {
+    return wrapped_->GetIOSurface();
+  }
+  bool IsInUseByWindowServer() const final {
+    return wrapped_->IsInUseByWindowServer();
+  }
 #endif
 
  private:
diff --git a/infra/config/generated/luci/luci-notify.cfg b/infra/config/generated/luci/luci-notify.cfg
index 3b2fecb..58eed10 100644
--- a/infra/config/generated/luci/luci-notify.cfg
+++ b/infra/config/generated/luci/luci-notify.cfg
@@ -3927,7 +3927,7 @@
     on_occurrence: FAILURE
     on_occurrence: INFRA_FAILURE
     email {
-      recipients: "chrome-browser-infra-team@google.com"
+      recipients: "chrome-dev-infra-auto+alerts@google.com"
     }
   }
   builders {
@@ -4110,7 +4110,7 @@
     on_occurrence: FAILURE
     on_occurrence: INFRA_FAILURE
     email {
-      recipients: "chrome-browser-infra-team@google.com"
+      recipients: "chrome-dev-infra-auto+alerts@google.com"
     }
   }
   builders {
diff --git a/infra/config/subprojects/chromium/ci/chromium.infra.star b/infra/config/subprojects/chromium/ci/chromium.infra.star
index caec048..962253a 100644
--- a/infra/config/subprojects/chromium/ci/chromium.infra.star
+++ b/infra/config/subprojects/chromium/ci/chromium.infra.star
@@ -371,7 +371,7 @@
     notifies = [
         luci.notifier(
             name = "rts-model-packager-notifier",
-            notify_emails = ["chrome-browser-infra-team@google.com"],
+            notify_emails = ["chrome-dev-infra-auto+alerts@google.com"],
             on_occurrence = ["FAILURE", "INFRA_FAILURE"],
         ),
     ],
diff --git a/infra/config/subprojects/infra.star b/infra/config/subprojects/infra.star
index b8b03b8..f428193 100644
--- a/infra/config/subprojects/infra.star
+++ b/infra/config/subprojects/infra.star
@@ -85,7 +85,7 @@
     notifies = [
         luci.notifier(
             name = "chromium-autosharder-notifier",
-            notify_emails = ["chrome-browser-infra-team@google.com"],
+            notify_emails = ["chrome-dev-infra-auto+alerts@google.com"],
             on_occurrence = ["FAILURE", "INFRA_FAILURE"],
         ),
     ],
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt
index 8b01db6..9069759 100644
--- a/infra/inclusive_language_presubmit_exempt_dirs.txt
+++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -123,7 +123,7 @@
 components/gcm_driver 1 1
 components/infobars/android/java/src/org/chromium/components/infobars 1 1
 components/input 2 1
-components/media_router/common/providers/cast/channel 1 1
+components/media_router/common/providers/cast/channel 3 2
 components/metrics 1 1
 components/metrics/debug 2 1
 components/omnibox/browser 1 1
@@ -275,7 +275,6 @@
 services/test/data/passage_embeddings 5 1
 services/tracing/perfetto 1 1
 services/tracing/public/mojom 1 1
-storage/browser/database 1 1
 styleguide 8 2
 styleguide/web 1 1
 testing 2 2
@@ -391,7 +390,7 @@
 third_party/blink/tools/blinkpy 1 1
 third_party/blink/tools/blinkpy/common 1 1
 third_party/blink/tools/blinkpy/common/checkout 1 1
-third_party/blink/tools/blinkpy/common/net 3 2
+third_party/blink/tools/blinkpy/common/net 4 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 20 7
@@ -670,7 +669,6 @@
 third_party/rust/chromium_crates_io/vendor/either-v1/.github/workflows 1 1
 third_party/rust/chromium_crates_io/vendor/equivalent-v1/.github/workflows 1 1
 third_party/rust/chromium_crates_io/vendor/flate2-v1 1 1
-third_party/rust/chromium_crates_io/vendor/getrandom-v0_2 5 1
 third_party/rust/chromium_crates_io/vendor/hashbrown-v0_15 1 1
 third_party/rust/chromium_crates_io/vendor/hashbrown-v0_15/src 1 1
 third_party/rust/chromium_crates_io/vendor/hex-v0_4 1 1
@@ -682,7 +680,6 @@
 third_party/rust/chromium_crates_io/vendor/itoa-v1 2 1
 third_party/rust/chromium_crates_io/vendor/itoa-v1/.github/workflows 2 1
 third_party/rust/chromium_crates_io/vendor/itoa-v1/src 1 1
-third_party/rust/chromium_crates_io/vendor/libm-v0_2 1 1
 third_party/rust/chromium_crates_io/vendor/llguidance-v0_7 1 1
 third_party/rust/chromium_crates_io/vendor/log-v0_4 1 1
 third_party/rust/chromium_crates_io/vendor/log-v0_4/.github/workflows 8 1
@@ -697,13 +694,10 @@
 third_party/rust/chromium_crates_io/vendor/qr_code-v2 1 1
 third_party/rust/chromium_crates_io/vendor/quote-v1 1 1
 third_party/rust/chromium_crates_io/vendor/quote-v1/.github/workflows 2 1
-third_party/rust/chromium_crates_io/vendor/rand_chacha-v0_3 4 1
 third_party/rust/chromium_crates_io/vendor/rand_core-v0_6 4 1
 third_party/rust/chromium_crates_io/vendor/rand_core-v0_6/src 3 1
 third_party/rust/chromium_crates_io/vendor/rand_core-v0_9 4 1
 third_party/rust/chromium_crates_io/vendor/rand_core-v0_9/src 3 1
-third_party/rust/chromium_crates_io/vendor/rand_pcg-v0_3 4 1
-third_party/rust/chromium_crates_io/vendor/rand-v0_8 9 2
 third_party/rust/chromium_crates_io/vendor/read-fonts-v0_27/src/tables 3 2
 third_party/rust/chromium_crates_io/vendor/regex-automata-v0_4 2 2
 third_party/rust/chromium_crates_io/vendor/regex-automata-v0_4/src/util 1 1
@@ -750,8 +744,6 @@
 third_party/rust/chromium_crates_io/vendor/windows-sys-v0_52 1 1
 third_party/rust/chromium_crates_io/vendor/windows-sys-v0_52/src/Windows/Wdk/System/SystemServices 1 1
 third_party/rust/chromium_crates_io/vendor/windows-sys-v0_52/src/Windows/Win32/Networking/Clustering 2 1
-third_party/rust/chromium_crates_io/vendor/zerocopy-v0_8 1 1
-third_party/rust/chromium_crates_io/vendor/zerocopy-v0_8/src 1 1
 third_party/screen-ai 2 1
 third_party/sentencepiece/src 2 2
 third_party/sentencepiece/src/doc 3 1
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 99d5b6cc..03b2fd5a 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1149,6 +1149,15 @@
       <message name="IDS_IOS_CLOSE_TABS" desc="Label for the option in settings to close open tabs. In titlecase. [Length: 20em] [iOS only]">
         Tabs
       </message>
+      <message name="IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON" desc="The label of collaboration group infobar when a group update occurs (e.g., member removed, sharing stopped, group deleted). [iOS only]">
+        Got it
+      </message>
+      <message name="IDS_IOS_COLLABORATION_GROUP_MEMBER_ADDED_PRIMARY_TOOLBAR_BUTTON" desc="The label of collaboration group infobar when a member is added to the group. [iOS only]">
+        Manage
+      </message>
+      <message name="IDS_IOS_COLLABORATION_GROUP_TAB_REOPEN_PRIMARY_TOOLBAR_BUTTON" desc="The label of collaboration group infobar to reopen the updated or closed tab. [iOS only]">
+        Reopen
+      </message>
       <message name="IDS_IOS_COLLAPSED_PRIMARY_TOOLBAR_BUTTON" desc="The accessibility label for the collapsed toolbar button in primary toolbar. [iOS only].">
         Collapsed primary toolbar button
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON.png.sha1
new file mode 100644
index 0000000..a21957f0c
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON.png.sha1
@@ -0,0 +1 @@
+b9a977cb86912c3573db6c12fab6f2bc82d18ce1
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_MEMBER_ADDED_PRIMARY_TOOLBAR_BUTTON.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_MEMBER_ADDED_PRIMARY_TOOLBAR_BUTTON.png.sha1
new file mode 100644
index 0000000..582d82c
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_MEMBER_ADDED_PRIMARY_TOOLBAR_BUTTON.png.sha1
@@ -0,0 +1 @@
+7d28a827ac55ce20c76fee3fe207687f7e65ecef
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_TAB_REOPEN_PRIMARY_TOOLBAR_BUTTON.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_TAB_REOPEN_PRIMARY_TOOLBAR_BUTTON.png.sha1
new file mode 100644
index 0000000..486b6b5
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COLLABORATION_GROUP_TAB_REOPEN_PRIMARY_TOOLBAR_BUTTON.png.sha1
@@ -0,0 +1 @@
+95f61e8f83db4a93555e712a616d0581b3e9ef30
\ No newline at end of file
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
index cb60582..0f2a4e5 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
@@ -817,11 +817,7 @@
 #pragma mark AuthenticationFlowPerformerDelegate
 
 - (void)didSignOutForAccountSwitch {
-  [self continueFlow];
-}
-
-- (void)didClearData {
-  [self continueFlow];
+  NOTREACHED();
 }
 
 - (void)didFetchUnsyncedDataWithUnsyncedDataTypes:
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile.mm
index 6e72106..f56efda 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile.mm
@@ -430,18 +430,14 @@
   [self continueFlow];
 }
 
-- (void)didClearData {
-  // TODO(crbug.com/403183877): Split `AuthenticationFlowPerformer` into 2
-  // classes to avoid having all those NOTREACHED methods.
-  NOTREACHED();
-}
-
 - (void)didFetchUnsyncedDataWithUnsyncedDataTypes:
     (syncer::DataTypeSet)unsyncedDataTypes {
   // Unsynced data is checked by AuthenticationFlow before calling
   // `AuthenticationFlowInProfile`.
   // So unsynced data is checked when leaving a profile (for profile switching),
   // or before sign-out (for account switching).
+  // TODO(crbug.com/403183877): Split `AuthenticationFlowPerformer` into 2
+  // classes to avoid having all those NOTREACHED methods.
   NOTREACHED();
 }
 
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer_delegate.h b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer_delegate.h
index 8416b4c5e..0fd8626 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer_delegate.h
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer_delegate.h
@@ -23,9 +23,6 @@
 // `signOutForAccountSwitchWithProfile`.
 - (void)didSignOutForAccountSwitch;
 
-// Indicates that browsing data finished clearing.
-- (void)didClearData;
-
 // Called after `-[AuthenticationFlowPerformer
 // fetchUnsyncedDataWithSyncService:]`, to return the list of data types
 // unsynced in the current profile.
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/BUILD.gn
index a61050b..4a39e4b 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/BUILD.gn
@@ -11,9 +11,11 @@
   ]
   deps = [
     "//base",
+    "//components/feature_engagement/public",
     "//components/signin/public/identity_manager/objc",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/authentication/ui_bundled/signin_promo",
+    "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/infobars/ui_bundled/banners",
     "//ios/chrome/browser/infobars/ui_bundled/coordinators",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
@@ -36,7 +38,11 @@
     ":coordinator",
     "//base",
     "//base/test:test_support",
+    "//components/feature_engagement/public",
+    "//components/feature_engagement/test:test_support",
     "//components/signin/public/identity_manager/objc",
+    "//ios/chrome/browser/authentication/ui_bundled/signin_promo",
+    "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/shared/model/application_context:application_context",
     "//ios/chrome/browser/shared/model/profile/test:test",
     "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/DEPS b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/DEPS
index f3d58f8..518100dd 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/DEPS
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+ios/chrome/browser/feature_engagement/model/tracker_factory.h",
   "+ios/chrome/browser/infobars/ui_bundled",
 ]
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_coordinator.mm
index 6723b44..87fb134 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_coordinator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_coordinator.mm
@@ -5,8 +5,10 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_coordinator.h"
 
 #import "base/notreached.h"
+#import "components/feature_engagement/public/tracker.h"
 #import "ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h"
 #import "ios/chrome/browser/authentication/ui_bundled/signin_promo/signin_promo_types.h"
+#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
 #import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_delegate.h"
 #import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_view_controller.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
@@ -38,6 +40,7 @@
   NonModalSignInPromoMediator* _mediator;
   // The type of promo to be displayed.
   SignInPromoType _promoType;
+  raw_ptr<feature_engagement::Tracker> _tracker;
 }
 
 // Synthesize because readonly property from superclass is changed to readwrite.
@@ -54,6 +57,7 @@
     self.browser = browser;
     self.shouldUseDefaultDismissal = NO;
     _promoType = promoType;
+    _tracker = feature_engagement::TrackerFactory::GetForProfile(self.profile);
   }
   return self;
 }
@@ -69,7 +73,9 @@
 
   _mediator = [[NonModalSignInPromoMediator alloc]
       initWithAuthenticationService:authService
-                    identityManager:identityManager];
+                    identityManager:identityManager
+           featureEngagementTracker:_tracker
+                          promoType:_promoType];
 
   _mediator.delegate = self;
 
@@ -87,6 +93,17 @@
 #pragma mark - Private Methods
 
 - (void)sendPromoDismissalNotification {
+  switch (_promoType) {
+    case SignInPromoType::kPassword:
+      _tracker->Dismissed(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature);
+      break;
+    case SignInPromoType::kBookmark:
+      _tracker->Dismissed(
+          feature_engagement::kIPHiOSPromoNonModalSigninBookmarkFeature);
+      break;
+  }
+
   [_mediator stopTimeOutTimers];
 
   id<NonModalSignInPromoCommands> nonModalSignInPromoHandler =
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h
index 1fa79b1..1a667fc 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h
@@ -11,6 +11,11 @@
 class IdentityManager;
 }
 class AuthenticationService;
+namespace feature_engagement {
+class Tracker;
+}
+
+enum class SignInPromoType;
 
 @class NonModalSignInPromoMediator;
 
@@ -27,10 +32,13 @@
 // Mediator that handles the business logic for the non-modal sign-in promo.
 @interface NonModalSignInPromoMediator : NSObject
 
-// Init Mediator with auth service and identity manager.
+// Init Mediator with auth service, identity manager, feature engagement tracker
+// and promo type.
 - (instancetype)
     initWithAuthenticationService:(AuthenticationService*)authService
                   identityManager:(signin::IdentityManager*)identityManager
+         featureEngagementTracker:(feature_engagement::Tracker*)tracker
+                        promoType:(SignInPromoType)promoType
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.mm
index e6a0dc07e..6f72f4e 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.mm
@@ -4,7 +4,11 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator.h"
 
 #import "base/timer/timer.h"
+#import "components/feature_engagement/public/event_constants.h"
+#import "components/feature_engagement/public/tracker.h"
 #import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
+#import "ios/chrome/browser/authentication/ui_bundled/signin_promo/signin_promo_types.h"
+#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 
 namespace {
@@ -31,14 +35,24 @@
 
   // The AuthenticationService used by the mediator to monitor sign-in status.
   raw_ptr<AuthenticationService> _authService;
+
+  // Feature engagement tracker for determining if the promo can be shown.
+  raw_ptr<feature_engagement::Tracker> _tracker;
+
+  // The type of promo (password or bookmark) being shown.
+  SignInPromoType _promoType;
 }
 
 - (instancetype)
     initWithAuthenticationService:(AuthenticationService*)authService
-                  identityManager:(signin::IdentityManager*)identityManager {
+                  identityManager:(signin::IdentityManager*)identityManager
+         featureEngagementTracker:(feature_engagement::Tracker*)tracker
+                        promoType:(SignInPromoType)promoType {
   self = [super init];
   if (self) {
     _authService = authService;
+    _tracker = tracker;
+    _promoType = promoType;
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(identityManager,
                                                                 self);
@@ -57,7 +71,21 @@
     return;
   }
 
-  // TODO(crbug.com/405135960): query tracker.
+  // Check with the feature engagement tracker if promo should be shown.
+  bool wouldShowPromo = false;
+
+  if (_promoType == SignInPromoType::kPassword) {
+    wouldShowPromo = _tracker->WouldTriggerHelpUI(
+        feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature);
+  } else if (_promoType == SignInPromoType::kBookmark) {
+    wouldShowPromo = _tracker->WouldTriggerHelpUI(
+        feature_engagement::kIPHiOSPromoNonModalSigninBookmarkFeature);
+  }
+
+  if (!wouldShowPromo) {
+    [self.delegate nonModalSignInPromoMediatorShouldDismiss:self];
+    return;
+  }
 
   __weak __typeof(self) weakSelf = self;
   _displayTimer = std::make_unique<base::OneShotTimer>();
@@ -73,6 +101,7 @@
 - (void)disconnect {
   _identityManagerObserver.reset();
   _authService = nil;
+  _tracker = nil;
 }
 
 #pragma mark - Private
@@ -92,6 +121,23 @@
 // Called when the display timer fires.
 - (void)displayTimerFired {
   _displayTimer = nullptr;
+
+  bool shouldShowPromo = false;
+
+  if (_promoType == SignInPromoType::kPassword) {
+    shouldShowPromo = _tracker->ShouldTriggerHelpUI(
+        feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature);
+  } else if (_promoType == SignInPromoType::kBookmark) {
+    shouldShowPromo = _tracker->ShouldTriggerHelpUI(
+        feature_engagement::kIPHiOSPromoNonModalSigninBookmarkFeature);
+  }
+
+  if (!shouldShowPromo) {
+    // Inform coordinator to dismiss UI and clean up.
+    [self.delegate nonModalSignInPromoMediatorShouldDismiss:self];
+    return;
+  }
+
   // Call the delegate to show the promo.
   [self.delegate nonModalSignInPromoMediatorTimerExpired:self];
 
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator_unittest.mm
index 4834fa1..88f83d1 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo/coordinator/non_modal_signin_promo_mediator_unittest.mm
@@ -7,7 +7,11 @@
 #import "base/memory/raw_ptr.h"
 #import "base/run_loop.h"
 #import "base/test/task_environment.h"
+#import "components/feature_engagement/public/feature_constants.h"
+#import "components/feature_engagement/test/mock_tracker.h"
 #import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
+#import "ios/chrome/browser/authentication/ui_bundled/signin_promo/signin_promo_types.h"
+#import "ios/chrome/browser/feature_engagement/model/tracker_factory.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/commands/non_modal_signin_promo_commands.h"
@@ -91,6 +95,13 @@
 
 @end
 
+namespace {
+std::unique_ptr<KeyedService> BuildFeatureEngagementMockTracker(
+    web::BrowserState* context) {
+  return std::make_unique<feature_engagement::test::MockTracker>();
+}
+}  // namespace
+
 class NonModalSignInPromoMediatorTest : public PlatformTest {
  protected:
   void SetUp() override {
@@ -103,12 +114,16 @@
             GetApplicationContext()->GetSystemIdentityManager());
     system_identity_manager->AddIdentity(identity_);
 
-    // Setup profile with fake authentication service
+    // Setup profile with fake authentication service and mock tracker factory
     TestProfileIOS::Builder builder;
     builder.AddTestingFactory(
         AuthenticationServiceFactory::GetInstance(),
         AuthenticationServiceFactory::GetFactoryWithDelegate(
             std::make_unique<FakeAuthenticationServiceDelegate>()));
+
+    builder.AddTestingFactory(
+        feature_engagement::TrackerFactory::GetInstance(),
+        base::BindRepeating(&BuildFeatureEngagementMockTracker));
     profile_ = std::move(builder).Build();
     authentication_service_ =
         AuthenticationServiceFactory::GetForProfile(profile_.get());
@@ -116,13 +131,20 @@
     auto* identity_manager =
         IdentityManagerFactory::GetForProfile(profile_.get());
 
+    // Get the mock tracker from the profile
+    mock_tracker_ = static_cast<feature_engagement::test::MockTracker*>(
+        feature_engagement::TrackerFactory::GetForProfile(profile_.get()));
+
     // Create fake delegate and command handler
     fake_delegate_ = [[FakeNonModalSignInPromoMediatorDelegate alloc] init];
     fake_command_handler_ = [[FakeNonModalSignInPromoHandler alloc] init];
 
+    // Create mediator with password promo type by default
     mediator_ = [[NonModalSignInPromoMediator alloc]
         initWithAuthenticationService:authentication_service_
-                      identityManager:identity_manager];
+                      identityManager:identity_manager
+             featureEngagementTracker:mock_tracker_
+                            promoType:SignInPromoType::kPassword];
 
     mediator_.delegate = fake_delegate_;
   }
@@ -161,6 +183,7 @@
   std::unique_ptr<TestProfileIOS> profile_;
   FakeSystemIdentity* identity_ = nullptr;
   raw_ptr<AuthenticationService> authentication_service_ = nullptr;
+  raw_ptr<feature_engagement::test::MockTracker> mock_tracker_;
 
   FakeNonModalSignInPromoMediatorDelegate* fake_delegate_ = nil;
   FakeNonModalSignInPromoHandler* fake_command_handler_ = nil;
@@ -170,6 +193,17 @@
 
 // Tests that the display timer fires after the delay and calls the delegate
 TEST_F(NonModalSignInPromoMediatorTest, DisplayTimerFiresAndCallsDelegate) {
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+
+  EXPECT_CALL(
+      *mock_tracker_,
+      ShouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
   // Start the display timer
   [mediator_ startPromoDisplayTimer];
 
@@ -185,6 +219,16 @@
 // method
 TEST_F(NonModalSignInPromoMediatorTest,
        TimeoutTimerCallsDelegateShouldDismiss) {
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(
+      *mock_tracker_,
+      ShouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
   // Start the display timer
   [mediator_ startPromoDisplayTimer];
 
@@ -201,6 +245,16 @@
 
 // Tests that the promo is dismissed when the user signs in
 TEST_F(NonModalSignInPromoMediatorTest, DismissWhenUserSignsIn) {
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(
+      *mock_tracker_,
+      ShouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
   // Start the display timer
   [mediator_ startPromoDisplayTimer];
 
@@ -218,6 +272,17 @@
 
 // Tests that stopTimeOutTimers correctly resets the timeout timer
 TEST_F(NonModalSignInPromoMediatorTest, StopTimeOutTimersResetsTimer) {
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(
+      *mock_tracker_,
+      ShouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   // Start the display timer
   [mediator_ startPromoDisplayTimer];
 
@@ -233,3 +298,57 @@
   // Verify shouldDismiss wasn't called because we stopped the timer
   EXPECT_EQ(0, fake_delegate_.shouldDismissCount);
 }
+
+// Tests that the promo is not displayed when the feature engagement tracker
+// indicates it should not be shown
+TEST_F(NonModalSignInPromoMediatorTest,
+       DoNotShowPromoWhenTrackerDisallowsAtWouldStage) {
+  // Set up the mock tracker to disallow the password promo
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(false));
+
+  // Start the display timer
+  [mediator_ startPromoDisplayTimer];
+
+  // The mediator should immediately dismiss instead of waiting for the timer
+  EXPECT_EQ(1, fake_delegate_.shouldDismissCount);
+  EXPECT_EQ(0, fake_delegate_.timerExpiredCount);
+
+  // Verify that NotifyEvent was never called
+  EXPECT_CALL(*mock_tracker_, NotifyEvent(testing::_)).Times(0);
+}
+
+// Tests that the promo is not displayed when the feature engagement tracker
+// allows at WouldTriggerHelpUI but disallows at ShouldTriggerHelpUI
+TEST_F(NonModalSignInPromoMediatorTest,
+       DoNotShowPromoWhenTrackerDisallowsAtShouldStage) {
+  // Set up the mock tracker to allow at WouldTriggerHelpUI
+  EXPECT_CALL(
+      *mock_tracker_,
+      WouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(true));
+
+  // But disallow at ShouldTriggerHelpUI
+  EXPECT_CALL(
+      *mock_tracker_,
+      ShouldTriggerHelpUI(testing::Ref(
+          feature_engagement::kIPHiOSPromoNonModalSigninPasswordFeature)))
+      .WillRepeatedly(testing::Return(false));
+
+  // Start the display timer
+  [mediator_ startPromoDisplayTimer];
+
+  // Fast-forward time to trigger the timer
+  FireDisplayTimer();
+
+  // The mediator should dismiss after timer fires without showing the promo
+  EXPECT_EQ(1, fake_delegate_.shouldDismissCount);
+  EXPECT_EQ(0, fake_delegate_.timerExpiredCount);
+
+  // Verify that NotifyEvent was never called
+  EXPECT_CALL(*mock_tracker_, NotifyEvent(testing::_)).Times(0);
+}
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h
index f4889a8f..fbb9eb61 100644
--- a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h
+++ b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h
@@ -5,6 +5,9 @@
 #ifndef IOS_CHROME_BROWSER_AUTOFILL_MODEL_BOTTOM_SHEET_SAVE_CARD_BOTTOM_SHEET_MODEL_H_
 #define IOS_CHROME_BROWSER_AUTOFILL_MODEL_BOTTOM_SHEET_SAVE_CARD_BOTTOM_SHEET_MODEL_H_
 
+#import <base/observer_list.h>
+#import <base/observer_list_types.h>
+
 #import <memory>
 #import <string>
 
@@ -12,6 +15,7 @@
 #import "components/autofill/core/browser/payments/autofill_save_card_delegate.h"
 #import "components/autofill/core/browser/payments/autofill_save_card_ui_info.h"
 #import "components/autofill/core/browser/payments/legal_message_line.h"
+#import "components/autofill/core/browser/payments/payments_autofill_client.h"
 
 namespace autofill {
 
@@ -21,6 +25,27 @@
 // the bottomsheet).
 class SaveCardBottomSheetModel {
  public:
+  // Save card flow states.
+  enum class SaveCardState {
+    // Save card is offered to the user.
+    kOffered,
+    // User accepted the bottomsheet and save card is in progress.
+    kSaveInProgress,
+    // Save card has succeeded.
+    kSaved,
+    // Save card has failed.
+    kFailed,
+    kMaxValue = kFailed,
+  };
+
+  // Interface for observer of this model.
+  class Observer : public base::CheckedObserver {
+   public:
+    ~Observer() override;
+    // Called when card upload request is completed.
+    virtual void OnCreditCardUploadCompleted(bool card_saved) = 0;
+  };
+
   SaveCardBottomSheetModel(
       AutofillSaveCardUiInfo ui_info,
       std::unique_ptr<AutofillSaveCardDelegate> save_card_delegate);
@@ -35,6 +60,19 @@
   // Calls `AutofillSaveCardDelegate` to handle the dismiss event.
   virtual void OnCanceled();
 
+  // Updates observer with save card result and sets the callback to be run
+  // after bottomsheet is closed upon showing the success confirmation.
+  virtual void CreditCardUploadCompleted(
+      bool card_saved,
+      autofill::payments::PaymentsAutofillClient::OnConfirmationClosedCallback
+          on_confirmation_closed_callback);
+
+  void AddObserver(Observer* observer) { observer_list_.AddObserver(observer); }
+
+  void RemoveObserver(Observer* observer) {
+    observer_list_.RemoveObserver(observer);
+  }
+
   // Logo to be displayed above the title in the bottomsheet.
   inline int logo_icon_id() const { return ui_info_.logo_icon_id; }
 
@@ -92,6 +130,8 @@
     return ui_info_.legal_message_lines;
   }
 
+  inline SaveCardState save_card_state() const { return save_card_state_; }
+
   base::WeakPtr<SaveCardBottomSheetModel> GetWeakPtr() {
     return weak_ptr_factory_.GetWeakPtr();
   }
@@ -107,6 +147,17 @@
   // Provides callbacks to handle user interactions with the UI.
   std::unique_ptr<AutofillSaveCardDelegate> save_card_delegate_;
 
+  // Callback to be called after credit card upload is complete and bottomsheet
+  // has been closed.
+  payments::PaymentsAutofillClient::OnConfirmationClosedCallback
+      on_confirmation_closed_callback_;
+
+  // TODO(crbug.com/412631591): Use SaveCardState to log result metrics for the
+  // bottomsheet's state.
+  SaveCardState save_card_state_{SaveCardState::kOffered};
+
+  base::ObserverList<Observer> observer_list_;
+
   base::WeakPtrFactory<SaveCardBottomSheetModel> weak_ptr_factory_{this};
 };
 
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.mm b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.mm
index b92f1b3..a242651 100644
--- a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.mm
+++ b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.mm
@@ -6,22 +6,51 @@
 
 #import <utility>
 
+#import "base/check.h"
+#import "components/autofill/core/browser/payments/payments_autofill_client.h"
+
 namespace autofill {
 
+SaveCardBottomSheetModel::Observer::~Observer() = default;
+
 SaveCardBottomSheetModel::SaveCardBottomSheetModel(
     AutofillSaveCardUiInfo ui_info,
     std::unique_ptr<AutofillSaveCardDelegate> save_card_delegate)
     : ui_info_(std::move(ui_info)),
       save_card_delegate_(std::move(save_card_delegate)) {}
 
-SaveCardBottomSheetModel::~SaveCardBottomSheetModel() = default;
+SaveCardBottomSheetModel::~SaveCardBottomSheetModel() {
+  // Model is destroyed on bottomsheet's dismissal. Presence of
+  // `on_confirmation_closed_callback_` indicates that the bottomsheet has been
+  // dismissed after getting save card confirmation. Thus the callback should be
+  // executed upon dismissing the bottomsheet.
+  if (on_confirmation_closed_callback_) {
+    std::move(on_confirmation_closed_callback_).Run();
+  }
+}
 
 void SaveCardBottomSheetModel::OnAccepted() {
+  save_card_state_ = SaveCardState::kSaveInProgress;
   save_card_delegate()->OnUiAccepted();
 }
 
 void SaveCardBottomSheetModel::OnCanceled() {
+  // This method is called when bottomsheet is dismissed using the `No thanks`
+  // button which is enabled only when save card is offered. Once bottomsheet
+  // has been accepted, the button is disabled while showing loading or
+  // confirmation.
+  CHECK(save_card_state_ == SaveCardState::kOffered);
   save_card_delegate()->OnUiCanceled();
 }
 
+void SaveCardBottomSheetModel::CreditCardUploadCompleted(
+    bool card_saved,
+    autofill::payments::PaymentsAutofillClient::OnConfirmationClosedCallback
+        on_confirmation_closed_callback) {
+  save_card_state_ =
+      card_saved ? SaveCardState::kSaved : SaveCardState::kFailed;
+  on_confirmation_closed_callback_ = std::move(on_confirmation_closed_callback);
+  observer_list_.Notify(&Observer::OnCreditCardUploadCompleted, card_saved);
+}
+
 }  // namespace autofill
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model_unittest.mm b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model_unittest.mm
index 012fce1..2ab8a8c 100644
--- a/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model_unittest.mm
+++ b/ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model_unittest.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h"
 
+#import "base/functional/callback_helpers.h"
 #import "base/strings/utf_string_conversions.h"
 #import "components/autofill/core/browser/payments/autofill_save_card_ui_info.h"
 #import "components/autofill/core/browser/payments/test_legal_message_line.h"
@@ -84,6 +85,12 @@
   MOCK_METHOD(void, OnUiCanceled, (), (override));
 };
 
+class MockSaveCardBottomSheetModelObserver
+    : public SaveCardBottomSheetModel::Observer {
+ public:
+  MOCK_METHOD(void, OnCreditCardUploadCompleted, (bool card_saved), (override));
+};
+
 class SaveCardBottomSheetModelTest : public PlatformTest {
  public:
   SaveCardBottomSheetModelTest() {
@@ -94,9 +101,14 @@
         AutofillSaveCardUiInfo(), std::move(delegate));
   }
 
+  void OnConfirmationClosedCallbackFn() {
+    ran_on_confirmation_closed_callback_ = true;
+  }
+
  protected:
   raw_ptr<MockAutofillSaveCardDelegate> save_card_delegate_ = nil;
   std::unique_ptr<SaveCardBottomSheetModel> save_card_bottom_sheet_model_;
+  bool ran_on_confirmation_closed_callback_ = false;
 };
 
 TEST_F(SaveCardBottomSheetModelTest, OnAccepted) {
@@ -109,4 +121,49 @@
   save_card_bottom_sheet_model_->OnCanceled();
 }
 
+// Test that on successful credit card upload completion, observer is updated
+// with the result and save card state is set to kSaved.
+TEST_F(SaveCardBottomSheetModelTest, OnCreditCardUploadCompleted_Success) {
+  MockSaveCardBottomSheetModelObserver observer;
+  save_card_bottom_sheet_model_->AddObserver(&observer);
+
+  EXPECT_CALL(observer, OnCreditCardUploadCompleted(true));
+  save_card_bottom_sheet_model_->CreditCardUploadCompleted(
+      /*card_saved=*/true,
+      /*on_confirmation_closed_callback=*/base::DoNothing());
+  EXPECT_EQ(save_card_bottom_sheet_model_->save_card_state(),
+            SaveCardBottomSheetModel::SaveCardState::kSaved);
+  save_card_bottom_sheet_model_->RemoveObserver(&observer);
+}
+
+// Test that on unsuccessful credit card upload completion, observer is updated
+// with the result and save card state is set to kFailed.
+TEST_F(SaveCardBottomSheetModelTest, OnCreditCardUploadCompleted_Failed) {
+  MockSaveCardBottomSheetModelObserver observer;
+  save_card_bottom_sheet_model_->AddObserver(&observer);
+
+  EXPECT_CALL(observer, OnCreditCardUploadCompleted(false));
+  save_card_bottom_sheet_model_->CreditCardUploadCompleted(
+      /*card_saved=*/false,
+      /*on_confirmation_closed_callback=*/base::DoNothing());
+  EXPECT_EQ(save_card_bottom_sheet_model_->save_card_state(),
+            SaveCardBottomSheetModel::SaveCardState::kFailed);
+  save_card_bottom_sheet_model_->RemoveObserver(&observer);
+}
+
+// Test that `on_confirmation_closed_callback` callback is executed when present
+// on model's reset.
+TEST_F(SaveCardBottomSheetModelTest, OnConfirmationDismissed) {
+  save_card_bottom_sheet_model_->CreditCardUploadCompleted(
+      /*card_saved=*/true, /*on_confirmation_closed_callback=*/
+      base::BindOnce(
+          &SaveCardBottomSheetModelTest::OnConfirmationClosedCallbackFn,
+          base::Unretained(this)));
+  EXPECT_EQ(save_card_bottom_sheet_model_->save_card_state(),
+            SaveCardBottomSheetModel::SaveCardState::kSaved);
+
+  save_card_bottom_sheet_model_.reset();
+  EXPECT_TRUE(ran_on_confirmation_closed_callback_);
+}
+
 }  // namespace autofill
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/BUILD.gn b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/BUILD.gn
index 7a5e49e..5ac5dc5 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/BUILD.gn
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/BUILD.gn
@@ -27,6 +27,7 @@
     "bottom_sheet_constants.h",
     "bottom_sheet_constants.mm",
   ]
+  deps = [ "//base" ]
 }
 
 source_set("bottom_sheet") {
@@ -185,6 +186,7 @@
     "save_card_bottom_sheet_coordinator.mm",
   ]
   deps = [
+    ":save_card_bottom_sheet_delegate",
     ":save_card_bottom_sheet_mediator",
     ":save_card_bottom_sheet_view_controller",
     "//base",
@@ -240,6 +242,7 @@
     ":save_card_bottom_sheet_delegate",
     ":save_card_bottom_sheet_mutator",
     "//build:branding_buildflags",
+    "//components/strings:components_strings_grit",
     "//ios/chrome/browser/autofill/model/message",
     "//ios/chrome/browser/autofill/ui_bundled:util",
     "//ios/chrome/browser/autofill/ui_bundled/bottom_sheet:constants",
@@ -249,6 +252,7 @@
     "//ios/chrome/browser/shared/ui/table_view/cells",
     "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/confirmation_alert",
+    "//ui/base",
   ]
   frameworks = [ "UIKit.framework" ]
 }
@@ -258,9 +262,11 @@
   sources = [ "save_card_bottom_sheet_view_controller_unittest.mm" ]
   deps = [
     ":save_card_bottom_sheet_view_controller",
+    "//components/strings:components_strings_grit",
     "//ios/chrome/common/ui/confirmation_alert",
     "//testing/gtest",
     "//third_party/ocmock",
+    "//ui/base",
   ]
 }
 
@@ -275,6 +281,7 @@
     "save_card_bottom_sheet_mediator.mm",
   ]
   deps = [
+    ":constants",
     ":save_card_bottom_sheet_consumer",
     ":save_card_bottom_sheet_mutator",
     "//base",
@@ -290,9 +297,11 @@
   testonly = true
   sources = [ "save_card_bottom_sheet_mediator_unittest.mm" ]
   deps = [
+    ":constants",
     ":save_card_bottom_sheet_consumer",
     ":save_card_bottom_sheet_mediator",
     "//base",
+    "//base/test:test_support",
     "//components/autofill/core/browser",
     "//components/autofill/core/browser:test_support",
     "//components/resources:components_scaled_resources_grit",
@@ -300,6 +309,7 @@
     "//ios/chrome/browser/autofill/model/bottom_sheet:save_card_bottom_sheet_model",
     "//ios/chrome/browser/autofill/model/message",
     "//ios/chrome/browser/shared/public/commands",
+    "//ios/web/public/test",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/ocmock",
@@ -362,6 +372,7 @@
     "virtual_card_enrollment_bottom_sheet_mediator.mm",
   ]
   deps = [
+    ":constants",
     ":virtual_card_enrollment_bottom_sheet_consumer",
     ":virtual_card_enrollment_bottom_sheet_data",
     ":virtual_card_enrollment_bottom_sheet_mutator",
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h
index cb4a6386..eedec332 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h
@@ -7,6 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
+#import "base/time/time.h"
+
 // Accessibility identifier of the Edit Address Cancel Button.
 extern NSString* const kEditProfileBottomSheetCancelButton;
 
@@ -17,4 +19,8 @@
 // Sheet.
 extern NSString* const kDetailIconCellIdentifier;
 
+// Time duration to wait before auto dismissing the Save Card or Virtual Card
+// Enrollment Bottom Sheet in success confirmation state.
+extern base::TimeDelta const kConfirmationDismissDelay;
+
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_BOTTOM_SHEET_BOTTOM_SHEET_CONSTANTS_H_
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.mm
index 12c622bc..606dd38 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h"
 
+#import "base/time/time.h"
+
 NSString* const kEditProfileBottomSheetCancelButton =
     @"EditProfileBottomSheetCancelButton";
 
@@ -11,3 +13,5 @@
     @"EditProfileBottomSheetViewIdentfier";
 
 NSString* const kDetailIconCellIdentifier = @"DetailIconCell";
+
+base::TimeDelta const kConfirmationDismissDelay = base::Seconds(1.5);
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_consumer.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_consumer.h
index 019fb6f..ae57884 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_consumer.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_consumer.h
@@ -49,6 +49,9 @@
 // label for the accept button to indicate loading.
 - (void)showLoadingStateWithAccessibilityLabel:(NSString*)accessibilityLabel;
 
+// Updates bottomsheet to show card upload is successful.
+- (void)showConfirmationState;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_BOTTOM_SHEET_SAVE_CARD_BOTTOM_SHEET_CONSUMER_H_
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator.mm
index 6173c7d5..81bac64 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator.mm
@@ -82,6 +82,12 @@
       openURLInNewTab:[OpenNewTabCommand commandWithURLFromChrome:URL.gurl]];
 }
 
+- (void)onViewDisappeared {
+  id<AutofillCommands> autofillHandler = HandlerForProtocol(
+      self.browser->GetCommandDispatcher(), AutofillCommands);
+  [autofillHandler dismissSaveCardBottomSheet];
+}
+
 #pragma mark - Private
 
 - (void)setInitialVoiceOverFocus {
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator_unittest.mm
index 751afe1..71c7c4a 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_coordinator_unittest.mm
@@ -111,3 +111,13 @@
 
   [coordinator_ stop];
 }
+
+TEST_F(SaveCardBottomSheetCoordinatorTest, OnViewDisappeared) {
+  [coordinator_ start];
+
+  OCMExpect([autofill_commands_handler_ dismissSaveCardBottomSheet]);
+
+  [coordinator_ onViewDisappeared];
+
+  [coordinator_ stop];
+}
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_delegate.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_delegate.h
index 7a025c90..352b9cc6 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_delegate.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_delegate.h
@@ -16,6 +16,12 @@
 // Handles user tapping on a link in the legal message.
 - (void)didTapLinkURL:(CrURL*)URL;
 
+// Handles bottomsheet's dismissal. Bottomsheet could be dismissed if user
+// swipes away the bottomsheet, in that case the coordinator's owner may not
+// stop the coordinator immediately. This ensures coordinator is stopped and
+// resources owned by it are freed as soon as possible.
+- (void)onViewDisappeared;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_BOTTOM_SHEET_SAVE_CARD_BOTTOM_SHEET_DELEGATE_H_
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
index 06b5a6b..7ac7e300 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
@@ -28,6 +28,10 @@
 
 - (void)disconnect;
 
+#pragma mark - SaveCardBottomSheetModel Observer methods
+
+- (void)onCreditCardUploadCompleted:(BOOL)cardSaved;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_BOTTOM_SHEET_SAVE_CARD_BOTTOM_SHEET_MEDIATOR_H_
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
index 9d2eb59..974f9fb1 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
@@ -5,21 +5,70 @@
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h"
 
 #import <memory>
+#import <optional>
 #import <utility>
 
+#import "base/scoped_observation.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/time/time.h"
+#import "base/timer/timer.h"
+#import "ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h"
 #import "ios/chrome/browser/autofill/model/message/save_card_message_with_links.h"
+#import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h"
 #import "ios/chrome/browser/shared/public/commands/autofill_commands.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 
+namespace {
+
+// Bridges the C++ Observer interface to the Objective-C mediator. Scoped
+// observation adds and removes this bridge as the observer of the
+// SaveCardBottomSheetModel.
+class ModelObserverBridge
+    : public autofill::SaveCardBottomSheetModel::Observer {
+ public:
+  ModelObserverBridge(autofill::SaveCardBottomSheetModel* model,
+                      __weak SaveCardBottomSheetMediator* mediator)
+      : mediator_(mediator) {
+    scoped_model_observation_.Observe(model);
+  }
+  ~ModelObserverBridge() override = default;
+  void OnCreditCardUploadCompleted(bool card_saved) override {
+    [mediator_ onCreditCardUploadCompleted:card_saved];
+  }
+
+ private:
+  __weak SaveCardBottomSheetMediator* mediator_;
+  base::ScopedObservation<autofill::SaveCardBottomSheetModel,
+                          ModelObserverBridge>
+      scoped_model_observation_{this};
+};
+
+// Time duration to wait before auto dismissing the bottomsheet in success
+// confirmation state when VoiceOver is running. This is slightly greater than
+// `kConfirmationStateDuration` to give VoiceOver enough time to read the
+// required content.
+// TODO(crbug.com/413009143): When VO is running do not use this and listen for
+// VO announcement to finish before auto dismissing the bottomsheet in
+// confirmation state.
+static constexpr base::TimeDelta kConfirmationDismissDelayIfVoiceOverRunning =
+    base::Seconds(5);
+
+}  // namespace
+
 // TODO(crbug.com/402511942): Implement SaveCardBottomSheetMediator.
 @implementation SaveCardBottomSheetMediator {
+  // `_modelObserverBridge` holds a scoped observation of the model for the
+  // mediator and must be destroyed before the `_saveCardBottomSheetModel`
+
   // The model layer component providing resources and callbacks for
   // saving the card or rejecting the card upload.
-  // TODO:(crbug.com/402511942): Start observing the model for card upload
-  // updates.
   std::unique_ptr<autofill::SaveCardBottomSheetModel> _saveCardBottomSheetModel;
   __weak id<AutofillCommands> _autofillCommandsHandler;
+  std::optional<ModelObserverBridge> _modelObserverBridge;
+
+  // Timer that controls auto dismissal of bottomsheet after success
+  // confirmation is shown.
+  base::OneShotTimer _autoDismissConfirmationTimer;
 }
 
 - (instancetype)initWithUIModel:
@@ -29,16 +78,23 @@
   if (self) {
     _saveCardBottomSheetModel = std::move(model);
     _autofillCommandsHandler = autofillCommandsHandler;
+    _modelObserverBridge.emplace(_saveCardBottomSheetModel.get(), self);
   }
   return self;
 }
 
 - (void)disconnect {
-  // TODO:(crbug.com/402511942): Stop observing the model
+  _modelObserverBridge.reset();
+  _saveCardBottomSheetModel.reset();
 }
 
 - (void)setConsumer:(id<SaveCardBottomSheetConsumer>)consumer {
   _consumer = consumer;
+
+  if (!_consumer) {
+    return;
+  }
+
   [self.consumer
       setAboveTitleImage:NativeImage(
                              _saveCardBottomSheetModel->logo_icon_id())];
@@ -90,4 +146,35 @@
   [_autofillCommandsHandler dismissSaveCardBottomSheet];
 }
 
+#pragma mark - SaveCardBottomSheetModel Observer
+
+- (void)onCreditCardUploadCompleted:(BOOL)cardSaved {
+  if (cardSaved) {
+    [_consumer showConfirmationState];
+    // Auto dismiss bottomsheet after showing successful save card confirmation.
+    __weak __typeof(self) weakSelf = self;
+    _autoDismissConfirmationTimer.Start(
+        FROM_HERE,
+        UIAccessibilityIsVoiceOverRunning()
+            ? kConfirmationDismissDelayIfVoiceOverRunning
+            : kConfirmationDismissDelay,
+        base::BindOnce(
+            [](__weak __typeof(self) weakSelf) {
+              if (weakSelf) {
+                [weakSelf dimissConfirmationStateOnTimeout];
+              }
+            },
+            weakSelf));
+  } else {
+    [_autofillCommandsHandler dismissSaveCardBottomSheet];
+  }
+}
+
+#pragma mark - Private
+
+- (void)dimissConfirmationStateOnTimeout {
+  _autoDismissConfirmationTimer.Stop();
+  [_autofillCommandsHandler dismissSaveCardBottomSheet];
+}
+
 @end
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
index f446034..78a5f9b 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
@@ -11,6 +11,7 @@
 #import "base/strings/strcat.h"
 #import "base/strings/string_number_conversions.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/test/task_environment.h"
 #import "components/autofill/core/browser/payments/autofill_save_card_ui_info.h"
 #import "components/autofill/core/browser/payments/payments_autofill_client.h"
 #import "components/autofill/core/browser/payments/test_legal_message_line.h"
@@ -19,8 +20,10 @@
 #import "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/autofill/model/bottom_sheet/save_card_bottom_sheet_model.h"
 #import "ios/chrome/browser/autofill/model/message/save_card_message_with_links.h"
+#import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h"
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_consumer.h"
 #import "ios/chrome/browser/shared/public/commands/autofill_commands.h"
+#import "ios/web/public/test/web_task_environment.h"
 #import "testing/gmock/include/gmock/gmock.h"
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
@@ -90,6 +93,9 @@
 - (void)showLoadingStateWithAccessibilityLabel:(NSString*)accessibilityLabel {
 }
 
+- (void)showConfirmationState {
+}
+
 @end
 
 class MockSaveCardBottomSheetModel : public autofill::SaveCardBottomSheetModel {
@@ -111,6 +117,8 @@
 class SaveCardBottomSheetMediatorTest : public PlatformTest {
  public:
   SaveCardBottomSheetMediatorTest() {
+    task_environment_ = std::make_unique<web::WebTaskEnvironment>(
+        base::test::TaskEnvironment::TimeSource::MOCK_TIME);
     mock_autofill_commands_handler_ =
         OCMProtocolMock(@protocol(AutofillCommands));
     std::unique_ptr<MockSaveCardBottomSheetModel> model =
@@ -122,7 +130,14 @@
         autofillCommandsHandler:mock_autofill_commands_handler_];
   }
 
+  ~SaveCardBottomSheetMediatorTest() override { [mediator_ disconnect]; }
+
+  web::WebTaskEnvironment* task_environment() {
+    return task_environment_.get();
+  }
+
  protected:
+  std::unique_ptr<web::WebTaskEnvironment> task_environment_;
   id<AutofillCommands> mock_autofill_commands_handler_;
   raw_ptr<MockSaveCardBottomSheetModel> model_ = nil;
   SaveCardBottomSheetMediator* mediator_ = nil;
@@ -186,6 +201,65 @@
   EXPECT_OCMOCK_VERIFY((id)mock_consumer);
 }
 
+// Test that successful credit card upload completion calls the consumer to show
+// the confirmation state.
+TEST_F(SaveCardBottomSheetMediatorTest, OnSuccessShowConfirmationState) {
+  id<SaveCardBottomSheetConsumer> mock_consumer =
+      OCMProtocolMock(@protocol(SaveCardBottomSheetConsumer));
+  mediator_.consumer = mock_consumer;
+
+  OCMExpect([mock_consumer showConfirmationState]);
+  [mediator_ onCreditCardUploadCompleted:YES];
+
+  EXPECT_OCMOCK_VERIFY((id)mock_consumer);
+}
+
+// Test that unsuccessful credit card upload completion dismisses the
+// bottomsheet.
+TEST_F(SaveCardBottomSheetMediatorTest, OnFailureDismissBottomSheet) {
+  id<SaveCardBottomSheetConsumer> mock_consumer =
+      OCMProtocolMock(@protocol(SaveCardBottomSheetConsumer));
+  mediator_.consumer = mock_consumer;
+
+  OCMReject([mock_consumer showConfirmationState]);
+  OCMExpect([mock_autofill_commands_handler_ dismissSaveCardBottomSheet]);
+  [mediator_ onCreditCardUploadCompleted:NO];
+
+  EXPECT_OCMOCK_VERIFY((id)mock_consumer);
+}
+
+// Tests that bottomsheet is auto-dismissed when the timer for confirmation
+// state times out.
+TEST_F(SaveCardBottomSheetMediatorTest, ConfirmationAutoDismissed_OnTimeOut) {
+  id<SaveCardBottomSheetConsumer> mock_consumer =
+      OCMProtocolMock(@protocol(SaveCardBottomSheetConsumer));
+  mediator_.consumer = mock_consumer;
+
+  OCMExpect([mock_consumer showConfirmationState]);
+  [mediator_ onCreditCardUploadCompleted:YES];
+
+  OCMExpect([mock_autofill_commands_handler_ dismissSaveCardBottomSheet]);
+  task_environment()->FastForwardBy(kConfirmationDismissDelay);
+}
+
+// Tests that bottomsheet is not auto-dismissed before the timer for
+// confirmation state times out.
+TEST_F(SaveCardBottomSheetMediatorTest,
+       ConfirmationNotAutoDismissed_BeforeTimeout) {
+  id<SaveCardBottomSheetConsumer> mock_consumer =
+      OCMProtocolMock(@protocol(SaveCardBottomSheetConsumer));
+  mediator_.consumer = mock_consumer;
+
+  OCMExpect([mock_consumer showConfirmationState]);
+  [mediator_ onCreditCardUploadCompleted:YES];
+
+  OCMReject([mock_autofill_commands_handler_ dismissSaveCardBottomSheet]);
+
+  // Advance timer slightly less than the actual timeout duration i.e
+  // `kConfirmationDismissDelay`.
+  task_environment()->FastForwardBy(kConfirmationDismissDelay * 0.99);
+}
+
 // Test that `OnCanceled` is called on the model and bottomsheet is dismissed
 // when cancel button is pressed.
 TEST_F(SaveCardBottomSheetMediatorTest, OnCancel) {
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h
index 4fd5f193..959d30e1 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h
@@ -18,7 +18,7 @@
 @property(nonatomic, weak) id<SaveCardBottomSheetMutator> mutator;
 
 // Delegate to handle navigational events (e.g tap on legal message link opens
-// url in a new tab).
+// url in a new tab, bottomsheet gets swiped or a new tab is opened).
 @property(nonatomic, weak) id<SaveCardBottomSheetDelegate> delegate;
 
 @end
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
index 769fa5f1..b4a1c8a 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h"
 
 #import "build/branding_buildflags.h"
+#import "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/autofill/model/message/save_card_message_with_links.h"
 #import "ios/chrome/browser/autofill/ui_bundled/autofill_credit_card_util.h"
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h"
@@ -14,6 +15,7 @@
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_icon_item.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
+#import "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -66,6 +68,11 @@
   [super viewDidLoad];
 }
 
+- (void)viewDidDisappear:(BOOL)animated {
+  [super viewDidDisappear:animated];
+  [self.delegate onViewDisappeared];
+}
+
 #pragma mark - SaveCardBottomSheetConsumer
 
 - (void)setAboveTitleImage:(UIImage*)logoImage {
@@ -116,6 +123,21 @@
   self.isConfirmed = NO;
 }
 
+- (void)showConfirmationState {
+  self.isLoading = NO;
+  self.isConfirmed = YES;
+  self.primaryActionButton.accessibilityLabel = l10n_util::GetNSString(
+      IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_ACCESSIBLE_NAME);
+  // Accessibility announcement needs to posted here since VoiceOver wouldn't
+  // announce button's accessibility label as button's state does not change.
+  // For confirmation state, the button's state is already disabled from
+  // previously showing loading state.
+  UIAccessibilityPostNotification(
+      UIAccessibilityAnnouncementNotification,
+      l10n_util::GetNSString(
+          IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_ACCESSIBLE_NAME));
+}
+
 #pragma mark - UITableViewDataSource
 
 - (NSInteger)tableView:(UITableView*)tableView
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller_unittest.mm
index aa4b23d..28e62e12 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller_unittest.mm
@@ -4,10 +4,12 @@
 
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.h"
 
+#import "components/strings/grit/components_strings.h"
 #import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#import "ui/base/l10n/l10n_util.h"
 
 class SaveCardBottomSheetViewControllerTest : public PlatformTest {
  public:
@@ -42,3 +44,17 @@
   EXPECT_NSEQ(view_controller_.primaryActionButton.accessibilityLabel,
               @"A11y label");
 }
+
+TEST_F(SaveCardBottomSheetViewControllerTest, ShowConfirmation) {
+  // Presence of primary action string lets view controller create a primary
+  // action button.
+  view_controller_.primaryActionString = @"Save";
+
+  EXPECT_TRUE(view_controller_.view);
+  [view_controller_ showConfirmationState];
+  EXPECT_FALSE(view_controller_.isLoading);
+  EXPECT_TRUE(view_controller_.isConfirmed);
+  EXPECT_NSEQ(view_controller_.primaryActionButton.accessibilityLabel,
+              l10n_util::GetNSString(
+                  IDS_AUTOFILL_SAVE_CARD_CONFIRMATION_SUCCESS_ACCESSIBLE_NAME));
+}
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/virtual_card_enrollment_bottom_sheet_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/virtual_card_enrollment_bottom_sheet_mediator.mm
index 1e155fdf..a2aa94d 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/virtual_card_enrollment_bottom_sheet_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/virtual_card_enrollment_bottom_sheet_mediator.mm
@@ -12,6 +12,7 @@
 #import "components/autofill/core/browser/payments/virtual_card_enroll_metrics_logger.h"
 #import "components/autofill/core/browser/ui/payments/virtual_card_enroll_ui_model.h"
 #import "ios/chrome/browser/autofill/model/credit_card/credit_card_data.h"
+#import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/bottom_sheet_constants.h"
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/virtual_card_enrollment_bottom_sheet_data.h"
 #import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h"
 #import "ui/base/l10n/l10n_util.h"
@@ -45,10 +46,6 @@
       scoped_model_observation_{this};
 };
 
-// The delay between showing the confirmation and dismissing the virtual card
-// enrollment prompt.
-const base::TimeDelta kConfirmationDismissDelay = base::Seconds(1.5);
-
 }  // namespace
 
 @interface VirtualCardEnrollmentBottomSheetMediator () {
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.mm
index 22ca3bf..41cc192b 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_view_controller.mm
@@ -578,6 +578,7 @@
       case FillingProduct::kCompose:
       case FillingProduct::kAutofillAi:
       case FillingProduct::kLoyaltyCard:
+      case FillingProduct::kIdentityCredential:
       case FillingProduct::kNone:
         // `kMerchantPromoCode` and `kCompose` cases are currently not available
         // on iOS. Also, there shouldn't be suggestions of type `kNone`.
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_view.mm b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_view.mm
index 997e738..f743012 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_view.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_suggestion_view.mm
@@ -75,6 +75,7 @@
     case FillingProduct::kCompose:
     case FillingProduct::kAutofillAi:
     case FillingProduct::kMerchantPromoCode:
+    case FillingProduct::kIdentityCredential:
       // These cases are currently not available on iOS.
       NOTREACHED();
   }
diff --git a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.h b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.h
index 04c8ab8..c5a69c7 100644
--- a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.h
+++ b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.h
@@ -188,6 +188,10 @@
   std::unique_ptr<payments::MandatoryReauthManager> payments_reauth_manager_;
 
   base::WeakPtr<SaveCardBottomSheetModel> save_card_bottom_sheet_model_;
+
+  // Indicates whether the save card bottom sheet should be presented instead of
+  // the infobar.
+  bool show_save_card_bottom_sheet_;
 };
 
 }  // namespace payments
diff --git a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.mm b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.mm
index 4c987294..80b82cf9 100644
--- a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client.mm
@@ -8,6 +8,7 @@
 
 #import "base/check_deref.h"
 #import "base/functional/callback.h"
+#import "base/functional/callback_helpers.h"
 #import "base/memory/ptr_util.h"
 #import "base/memory/raw_ref.h"
 #import "base/memory/weak_ptr.h"
@@ -125,8 +126,8 @@
   // Delegate providing callbacks for the save card UI.
   std::unique_ptr<AutofillSaveCardDelegate> common_delegate =
       std::make_unique<AutofillSaveCardDelegate>(std::move(callback), options);
-
-  if (ShowSaveCardBottomSheet(options)) {
+  show_save_card_bottom_sheet_ = ShowSaveCardBottomSheet(options);
+  if (show_save_card_bottom_sheet_) {
     AutofillBottomSheetTabHelper* bottom_sheet_tab_helper =
         AutofillBottomSheetTabHelper::FromWebState(web_state_);
     std::unique_ptr<SaveCardBottomSheetModel> model =
@@ -142,23 +143,37 @@
           std::move(ui_info), std::move(common_delegate))));
 }
 
+// TODO(crbug.com/413418918): Remove optional from
+// `on_confirmation_closed_callback`.
 void IOSChromePaymentsAutofillClient::CreditCardUploadCompleted(
     PaymentsRpcResult result,
     std::optional<OnConfirmationClosedCallback>
         on_confirmation_closed_callback) {
-  // TODO(crbug.com/402134138): Use `save_card_bottom_sheet_model_` to update
-  // the SaveCardBottomSheetModel on credit card upload completion for it to be
-  // observed by the mediator.
   const bool card_saved = result == PaymentsRpcResult::kSuccess;
+  OnConfirmationClosedCallback callback =
+      on_confirmation_closed_callback
+          ? *std::exchange(on_confirmation_closed_callback, std::nullopt)
+          : base::DoNothing();
   if (client_->GetAutofillSaveCardInfoBarDelegateIOS()) {
     client_->GetAutofillSaveCardInfoBarDelegateIOS()->CreditCardUploadCompleted(
-        card_saved, std::move(on_confirmation_closed_callback));
+        card_saved, std::move(callback));
+  } else if (save_card_bottom_sheet_model_) {
+    save_card_bottom_sheet_model_->CreditCardUploadCompleted(
+        card_saved, std::move(callback));
+  } else if (show_save_card_bottom_sheet_) {
+    // If a bottomsheet was showing before and was dismissed before getting the
+    // save card result, the weak ref to save card bottomsheet model would be
+    // invalid since model's lifecycle is same as the UI's and, the callback
+    // would never be executed. Ensure callback runs if it is still pending.
+    std::move(callback).Run();
   }
+
   if (!card_saved) {
-    // At this point, infobar would be dismissed but the omnibox icon could
-    // still be tapped to re-show the infobar. Since the card upload has
-    // failed, the save card infobar should not be re-shown, so the infobar is
-    // removed here to remove the associated omnibox icon.
+    // At this point, infobar would be dismissed (if showing earlier) but the
+    // omnibox icon could still be tapped to re-show the infobar. Since the card
+    // upload has failed, the save card infobar should not be re-shown, so the
+    // infobar is removed here to remove the associated omnibox icon. If a
+    // bottomsheet was showing before, there wouldn't be an omnibox icon at all.
     client_->RemoveAutofillSaveCardInfoBar();
 
     // Here, `PaymentsRpcResult::kClientSideTimeout` indicates that the card
diff --git a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm
index 6fc19a8..700df0c 100644
--- a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm
@@ -127,12 +127,14 @@
                                                        web_state,
                                                        infobar_manager,
                                                        autofill_agent) {
-    autofill::CreditCard credit_card(
-        base::Uuid::GenerateRandomV4().AsLowercaseString(),
-        "https://www.example.test/");
-    save_card_delegate_ = MockAutofillSaveCardInfoBarDelegateMobileFactory::
-        CreateMockAutofillSaveCardInfoBarDelegateMobileFactory(/*upload=*/true,
-                                                               credit_card);
+    if (!base::FeatureList::IsEnabled(features::kAutofillSaveCardBottomSheet)) {
+      autofill::CreditCard credit_card(
+          base::Uuid::GenerateRandomV4().AsLowercaseString(),
+          "https://www.example.test/");
+      save_card_delegate_ = MockAutofillSaveCardInfoBarDelegateMobileFactory::
+          CreateMockAutofillSaveCardInfoBarDelegateMobileFactory(
+              /*upload=*/true, credit_card);
+    }
   }
 
   MockAutofillSaveCardInfoBarDelegateMobile*
@@ -175,8 +177,9 @@
     // ChromeAutofillClient.
     autofill_commands_ = [[FakeAutofillCommands alloc] init];
     AutofillBottomSheetTabHelper::CreateForWebState(web_state_.get());
-    AutofillBottomSheetTabHelper::FromWebState(web_state_.get())
-        ->SetAutofillBottomSheetHandler(autofill_commands_);
+    bottomsheet_tab_helper_ =
+        AutofillBottomSheetTabHelper::FromWebState(web_state_.get());
+    bottomsheet_tab_helper_->SetAutofillBottomSheetHandler(autofill_commands_);
 
     autofill_client_->set_commands_handler(autofill_commands_);
   }
@@ -201,6 +204,7 @@
 
  protected:
   FakeAutofillCommands* autofill_commands_;
+  raw_ptr<AutofillBottomSheetTabHelper> bottomsheet_tab_helper_;
 
  private:
   web::WebTaskEnvironment task_environment_;
@@ -211,20 +215,6 @@
 };
 
 TEST_F(IOSChromePaymentsAutofillClientTest,
-       ShowSaveCardBottomSheet_FlagEnabled) {
-  base::test::ScopedFeatureList scoped_feature_list(
-      autofill::features::kAutofillSaveCardBottomSheet);
-
-  payments_client()->ShowSaveCreditCardToCloud(
-      CreditCard(), LegalMessageLines(),
-      payments::PaymentsAutofillClient::SaveCreditCardOptions()
-          .with_num_strikes(0)
-          .with_show_prompt(true),
-      base::DoNothing());
-  EXPECT_TRUE([autofill_commands() showSaveCardBottomSheetCalled]);
-}
-
-TEST_F(IOSChromePaymentsAutofillClientTest,
        DoNotShowSaveCardBottomSheet_FlagDisabled) {
   payments_client()->ShowSaveCreditCardToCloud(
       CreditCard(), LegalMessageLines(),
@@ -236,50 +226,6 @@
 }
 
 TEST_F(IOSChromePaymentsAutofillClientTest,
-       DoNoShowSaveCardBottomSheet_CardWithMoreThan0Strike) {
-  base::test::ScopedFeatureList scoped_feature_list(
-      autofill::features::kAutofillSaveCardBottomSheet);
-
-  payments_client()->ShowSaveCreditCardToCloud(
-      CreditCard(), LegalMessageLines(),
-      payments::PaymentsAutofillClient::SaveCreditCardOptions()
-          .with_num_strikes(1)
-          .with_show_prompt(true),
-      base::DoNothing());
-  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
-}
-
-TEST_F(IOSChromePaymentsAutofillClientTest,
-       DoNoShowSaveCardBottomSheet_ForRequestingCardHolderName) {
-  base::test::ScopedFeatureList scoped_feature_list(
-      autofill::features::kAutofillSaveCardBottomSheet);
-
-  payments_client()->ShowSaveCreditCardToCloud(
-      CreditCard(), LegalMessageLines(),
-      payments::PaymentsAutofillClient::SaveCreditCardOptions()
-          .with_should_request_name_from_user(true)
-          .with_num_strikes(0)
-          .with_show_prompt(true),
-      base::DoNothing());
-  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
-}
-
-TEST_F(IOSChromePaymentsAutofillClientTest,
-       DoNoShowSaveCardBottomSheet_ForRequestingExpiryDate) {
-  base::test::ScopedFeatureList scoped_feature_list(
-      autofill::features::kAutofillSaveCardBottomSheet);
-
-  payments_client()->ShowSaveCreditCardToCloud(
-      CreditCard(), LegalMessageLines(),
-      payments::PaymentsAutofillClient::SaveCreditCardOptions()
-          .with_should_request_expiration_date_from_user(true)
-          .with_num_strikes(0)
-          .with_show_prompt(true),
-      base::DoNothing());
-  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
-}
-
-TEST_F(IOSChromePaymentsAutofillClientTest,
        CreditCardUploadCompleted_CardSaved) {
   EXPECT_CALL(*(client()->GetAutofillSaveCardInfoBarDelegateIOS()),
               CreditCardUploadCompleted(/*card_saved=*/true, _));
@@ -398,6 +344,123 @@
   EXPECT_EQ([autofill_commands_ autofillErrorDialogContext], std::nullopt);
 }
 
+class IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest
+    : public IOSChromePaymentsAutofillClientTest {
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      autofill::features::kAutofillSaveCardBottomSheet};
+};
+
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       ShowSaveCardBottomSheet_FlagEnabled) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  EXPECT_TRUE([autofill_commands() showSaveCardBottomSheetCalled]);
+}
+
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       DoNoShowSaveCardBottomSheet_CardWithMoreThan0Strike) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_num_strikes(1)
+          .with_show_prompt(true),
+      base::DoNothing());
+  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
+}
+
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       DoNoShowSaveCardBottomSheet_ForRequestingCardHolderName) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_should_request_name_from_user(true)
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
+}
+
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       DoNoShowSaveCardBottomSheet_ForRequestingExpiryDate) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_should_request_expiration_date_from_user(true)
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  EXPECT_FALSE([autofill_commands() showSaveCardBottomSheetCalled]);
+}
+
+// Test that on save card success, the save card bottomsheet model's state is
+// set to kSaved.
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       CreditCardUploadCompleted_CardSaved) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  payments_client()->CreditCardUploadCompleted(
+      /*result=*/payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess,
+      /*on_confirmation_closed_callback=*/std::nullopt);
+  EXPECT_EQ((bottomsheet_tab_helper_->GetSaveCardBottomSheetModel())
+                ->save_card_state(),
+            autofill::SaveCardBottomSheetModel::SaveCardState::kSaved);
+}
+
+// Test that on save card failure, the save card bottomsheet model's state is
+// set to kFailed and the error dialog is shown.
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       CreditCardUploadCompleted_CardNotSaved) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  payments_client()->CreditCardUploadCompleted(
+      /*result=*/payments::PaymentsAutofillClient::PaymentsRpcResult::
+          kPermanentFailure,
+      /*on_confirmation_closed_callback=*/std::nullopt);
+  EXPECT_EQ((bottomsheet_tab_helper_->GetSaveCardBottomSheetModel())
+                ->save_card_state(),
+            autofill::SaveCardBottomSheetModel::SaveCardState::kFailed);
+  const std::optional<AutofillErrorDialogContext>& error_context =
+      [autofill_commands() autofillErrorDialogContext];
+  EXPECT_TRUE(error_context.has_value());
+  EXPECT_EQ(error_context.value().type,
+            AutofillErrorDialogType::kCreditCardUploadError);
+}
+
+// Test that on getting client-side timeout, the save card bottomsheet model's
+// state is set to kFailed and the error dialog is not shown.
+TEST_F(IOSChromePaymentsAutofillClientWithSaveCardBottomSheetTest,
+       CreditCardUploadCompleted_ClientSideTimeout_NoErrorConfirmation) {
+  payments_client()->ShowSaveCreditCardToCloud(
+      CreditCard(), LegalMessageLines(),
+      payments::PaymentsAutofillClient::SaveCreditCardOptions()
+          .with_num_strikes(0)
+          .with_show_prompt(true),
+      base::DoNothing());
+  payments_client()->CreditCardUploadCompleted(
+      /*result=*/payments::PaymentsAutofillClient::PaymentsRpcResult::
+          kClientSideTimeout,
+      /*on_confirmation_closed_callback=*/std::nullopt);
+  EXPECT_EQ((bottomsheet_tab_helper_->GetSaveCardBottomSheetModel())
+                ->save_card_state(),
+            autofill::SaveCardBottomSheetModel::SaveCardState::kFailed);
+  const std::optional<AutofillErrorDialogContext>& error_context =
+      [autofill_commands() autofillErrorDialogContext];
+  EXPECT_FALSE(error_context.has_value());
+}
+
 }  // namespace
 
 }  // namespace autofill
diff --git a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.mm b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.mm
index 9c4e175..e110771 100644
--- a/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.mm
@@ -122,6 +122,7 @@
     case autofill::FillingProduct::kAutofillAi:
     case autofill::FillingProduct::kMerchantPromoCode:
     case autofill::FillingProduct::kLoyaltyCard:
+    case autofill::FillingProduct::kIdentityCredential:
       // These cases are currently not available on iOS.
       NOTREACHED();
   }
diff --git a/ios/chrome/browser/autofill/ui_bundled/save_profile_egtest.mm b/ios/chrome/browser/autofill/ui_bundled/save_profile_egtest.mm
index db84124..ef852a3 100644
--- a/ios/chrome/browser/autofill/ui_bundled/save_profile_egtest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/save_profile_egtest.mm
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #import <memory>
+#import <string_view>
 
+#import "base/strings/strcat.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
@@ -21,6 +23,7 @@
 #import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h"
 #import "ios/chrome/browser/infobars/ui_bundled/infobar_earl_grey_ui_test_util.h"
 #import "ios/chrome/browser/infobars/ui_bundled/modals/infobar_address_profile_modal_constants.h"
+#import "ios/chrome/browser/metrics/model/metrics_app_interface.h"
 #import "ios/chrome/browser/signin/model/fake_system_identity.h"
 #import "ios/chrome/grit/ios_branded_strings.h"
 #import "ios/chrome/grit/ios_strings.h"
@@ -58,6 +61,9 @@
 struct FullAddressFormPageParams {
   // True if the submission should be default prevented.
   bool default_prevented = false;
+  // True if there should be redirection done after submitting with
+  // `default_prevented` enabled in the parameters.
+  bool redirect = false;
 };
 
 // Matcher for the banner button.
@@ -168,7 +174,16 @@
 
 @implementation SaveProfileEGTest
 
+- (void)setUp {
+  [super setUp];
+  chrome_test_util::GREYAssertErrorNil(
+      [MetricsAppInterface setupHistogramTester]);
+}
+
 - (void)tearDownHelper {
+  chrome_test_util::GREYAssertErrorNil(
+      [MetricsAppInterface releaseHistogramTester]);
+
   // Clear existing profile.
   [AutofillAppInterface clearProfilesStore];
 
@@ -220,6 +235,20 @@
         kAutofillAllowDefaultPreventedSubmission);
   }
 
+  if ([self isRunningTest:@selector(testSubmissionDetectionWithDeduping)]) {
+    config.features_enabled.push_back(kAutofillDedupeFormSubmission);
+    // Default must be prevented to allow triggering multiple submissions from
+    // the same form.
+    config.features_enabled.push_back(kAutofillAllowDefaultPreventedSubmission);
+  }
+
+  if ([self isRunningTest:@selector(testSubmissionDetectionWithoutDeduping)]) {
+    config.features_disabled.push_back(kAutofillDedupeFormSubmission);
+    // Default must be prevented to allow triggering multiple submissions from
+    // the same form.
+    config.features_enabled.push_back(kAutofillAllowDefaultPreventedSubmission);
+  }
+
   return config;
 }
 
@@ -294,11 +323,23 @@
   // Start server.
   GREYAssertTrue(self.testServer->Start(), @"Server did not start.");
 
+  auto makeQueryString = [](FullAddressFormPageParams params) -> std::string {
+    std::vector<std::string_view> queryParameters;
+    if (params.default_prevented) {
+      queryParameters.push_back("preventDefault");
+    }
+    if (params.redirect) {
+      queryParameters.push_back("redirectWhenDefaultPrevented");
+    }
+    return base::JoinString(queryParameters, "&");
+  };
+
   // Get the URL for the served test page with the query parameters for setting
   // it up.
   const GURL baseURL = self.testServer->GetURL(kFullAddressFormPage);
   GURL::Replacements replacements;
-  replacements.SetQueryStr(params.default_prevented ? "preventDefault" : "");
+  std::string query = makeQueryString(params).c_str();
+  replacements.SetQueryStr(query);
   const GURL fullURL = baseURL.ReplaceComponents(replacements);
 
   // Load the URL and wait for its content to be loaded.
@@ -787,7 +828,7 @@
   [SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
 
   // Submit the form with `defaultPrevented` not considered.
-  FullAddressFormPageParams params{.default_prevented = true};
+  FullAddressFormPageParams params{.default_prevented = true, .redirect = true};
   [self loadAndSubmitFullAddressFormWithParams:params];
 
   // Wait on the infobar to be displayed after submission.
@@ -819,7 +860,7 @@
   [SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
 
   // Submit the form with `defaultPrevented` considered.
-  FullAddressFormPageParams params{.default_prevented = true};
+  FullAddressFormPageParams params{.default_prevented = true, .redirect = true};
   [self loadAndSubmitFullAddressFormWithParams:params];
 
   // Make sure the infobar isn't displayed.
@@ -828,4 +869,64 @@
   [SigninEarlGrey signOut];
 }
 
+// Tests that multiple submissions on the same form are not deduped when
+// deduping is disabled where all submissions are sent over to the browser.
+- (void)testSubmissionDetectionWithoutDeduping {
+  // Submit the form with `defaultPrevented` not considered and without
+  // redirecting so the same form can be submitted multiple time.
+  FullAddressFormPageParams params{.default_prevented = true,
+                                   .redirect = false};
+  [self loadAndSubmitFullAddressFormWithParams:params];
+
+  // Wait on the infobar to be displayed after submission, meaning that
+  // submission was detected.
+  [InfobarEarlGreyUI waitUntilInfobarBannerVisibleOrTimeout:YES];
+
+  // Spam submissions.
+  for (int i = 0; i < 5; ++i) {
+    [ChromeEarlGrey tapWebStateElementWithID:@"submit-button"];
+  }
+
+  // Verify that all submissions were sent over to the browser and recorded.
+  GREYAssertTrue(
+      base::test::ios::WaitUntilConditionOrTimeout(
+          base::Milliseconds(200),
+          ^{
+            NSError* error = [MetricsAppInterface
+                expectTotalCount:6
+                    forHistogram:@"Autofill.iOS.FormSubmission.Outcome"];
+            return error == nil;
+          }),
+      @"Timed out waiting for all form submission events.");
+}
+
+// Tests that multiple submissions on the same form are deduped when deduping is
+// enabled where only one submission per form element is allowed when.
+- (void)testSubmissionDetectionWithDeduping {
+  // Submit the form with `defaultPrevented` not considered and without
+  // redirecting so the same form can be submitted multiple time.
+  FullAddressFormPageParams params{.default_prevented = true,
+                                   .redirect = false};
+  [self loadAndSubmitFullAddressFormWithParams:params];
+
+  // Wait on the infobar to be displayed after submission, meaning that
+  // submission was detected.
+  [InfobarEarlGreyUI waitUntilInfobarBannerVisibleOrTimeout:YES];
+
+  // Spam submissions.
+  for (int i = 0; i < 5; ++i) {
+    [ChromeEarlGrey tapWebStateElementWithID:@"submit-button"];
+  }
+
+  // Wait some time so the hypothetical form submission messages would have been
+  // sent over to the browser by then.
+  base::test::ios::SpinRunLoopWithMinDelay(base::Milliseconds(200));
+
+  // Verify that only one submission was actually recorded despite triggering
+  // multiple submissions on the same form.
+  chrome_test_util::GREYAssertErrorNil([MetricsAppInterface
+      expectTotalCount:1
+          forHistogram:@"Autofill.iOS.FormSubmission.Outcome"]);
+}
+
 @end
diff --git a/ios/chrome/browser/collaboration/model/messaging/BUILD.gn b/ios/chrome/browser/collaboration/model/messaging/BUILD.gn
index 181eaa6..e6b68bbb 100644
--- a/ios/chrome/browser/collaboration/model/messaging/BUILD.gn
+++ b/ios/chrome/browser/collaboration/model/messaging/BUILD.gn
@@ -18,11 +18,15 @@
     "//base",
     "//components/collaboration/internal:messaging_internal",
     "//components/collaboration/public",
+    "//components/collaboration/public:empty_messaging_backend_service",
+    "//components/collaboration/public:features",
     "//components/data_sharing/public:features",
-    "//components/saved_tab_groups/public:features",
+    "//components/keyed_service/core",
     "//ios/chrome/browser/collaboration/model",
     "//ios/chrome/browser/collaboration/model:features",
+    "//ios/chrome/browser/collaboration/model/messaging/infobar",
     "//ios/chrome/browser/data_sharing/model",
+    "//ios/chrome/browser/infobars/model",
     "//ios/chrome/browser/saved_tab_groups/model",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
diff --git a/ios/chrome/browser/collaboration/model/messaging/DEPS b/ios/chrome/browser/collaboration/model/messaging/DEPS
index 2b9de272..c2baffb 100644
--- a/ios/chrome/browser/collaboration/model/messaging/DEPS
+++ b/ios/chrome/browser/collaboration/model/messaging/DEPS
@@ -2,6 +2,7 @@
   "+components/collaboration/public",
   "+ios/chrome/browser/collaboration/model/features.h",
   "+ios/chrome/browser/data_sharing/model",
+  "+ios/chrome/browser/infobars/model",
 
   # Allows service construction.
   "+components/collaboration/internal/messaging/configuration.h",
diff --git a/ios/chrome/browser/collaboration/model/messaging/infobar/BUILD.gn b/ios/chrome/browser/collaboration/model/messaging/infobar/BUILD.gn
new file mode 100644
index 0000000..158d642
--- /dev/null
+++ b/ios/chrome/browser/collaboration/model/messaging/infobar/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("infobar") {
+  sources = [
+    "collaboration_group_infobar_delegate.h",
+    "collaboration_group_infobar_delegate.mm",
+  ]
+
+  deps = [
+    "//base",
+    "//components/collaboration/public",
+    "//components/infobars/core",
+    "//components/strings",
+    "//ios/chrome/app/strings",
+    "//ios/chrome/browser/infobars/model",
+    "//ios/chrome/browser/infobars/model:public",
+    "//ios/chrome/browser/shared/model/browser",
+    "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/web_state_list",
+    "//ui/base",
+  ]
+}
diff --git a/ios/chrome/browser/collaboration/model/messaging/infobar/DEPS b/ios/chrome/browser/collaboration/model/messaging/infobar/DEPS
new file mode 100644
index 0000000..75a4234
--- /dev/null
+++ b/ios/chrome/browser/collaboration/model/messaging/infobar/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ios/chrome/browser/infobars/model",
+]
diff --git a/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h
new file mode 100644
index 0000000..665c81e
--- /dev/null
+++ b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h
@@ -0,0 +1,57 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_COLLABORATION_MODEL_MESSAGING_INFOBAR_COLLABORATION_GROUP_INFOBAR_DELEGATE_H_
+#define IOS_CHROME_BROWSER_COLLABORATION_MODEL_MESSAGING_INFOBAR_COLLABORATION_GROUP_INFOBAR_DELEGATE_H_
+
+#import <UIKit/UIKit.h>
+
+#import <memory>
+#import <string>
+
+#import "base/memory/raw_ptr.h"
+#import "components/collaboration/public/messaging/message.h"
+#import "components/infobars/core/confirm_infobar_delegate.h"
+
+class ProfileIOS;
+
+// Shows a collaboration group update in an infobar.
+class CollaborationGroupInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  CollaborationGroupInfoBarDelegate(
+      ProfileIOS* profile,
+      collaboration::messaging::InstantMessage instant_message);
+
+  CollaborationGroupInfoBarDelegate(const CollaborationGroupInfoBarDelegate&) =
+      delete;
+  CollaborationGroupInfoBarDelegate& operator=(
+      const CollaborationGroupInfoBarDelegate&) = delete;
+
+  ~CollaborationGroupInfoBarDelegate() override;
+
+  // Creates a collaboration group infobar for the given `instant_message`.
+  // Returns true if the infobar creation was successful, false otherwise.
+  static bool Create(ProfileIOS* profile,
+                     collaboration::messaging::InstantMessage instant_message);
+
+  // InfoBarDelegate implementation.
+  InfoBarIdentifier GetIdentifier() const override;
+
+  // ConfirmInfoBarDelegate implementation.
+  std::u16string GetMessageText() const override;
+  std::u16string GetTitleText() const override;
+  int GetButtons() const override;
+  std::u16string GetButtonLabel(InfoBarButton button) const override;
+  bool Accept() override;
+  void InfoBarDismissed() override;
+
+  // Returns the avatar banner image to display. Could be `nil`.
+  UIImage* GetAvatarImage();
+
+ private:
+  raw_ptr<ProfileIOS> profile_;
+  collaboration::messaging::InstantMessage instant_message_;
+};
+
+#endif  // IOS_CHROME_BROWSER_COLLABORATION_MODEL_MESSAGING_INFOBAR_COLLABORATION_GROUP_INFOBAR_DELEGATE_H_
diff --git a/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm
new file mode 100644
index 0000000..38ff209
--- /dev/null
+++ b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm
@@ -0,0 +1,196 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h"
+
+#import "base/check.h"
+#import "base/memory/ptr_util.h"
+#import "base/strings/sys_string_conversions.h"
+#import "components/infobars/core/infobar.h"
+#import "components/infobars/core/infobar_delegate.h"
+#import "components/infobars/core/infobar_manager.h"
+#import "ios/chrome/browser/infobars/model/infobar_ios.h"
+#import "ios/chrome/browser/infobars/model/infobar_manager_impl.h"
+#import "ios/chrome/browser/infobars/model/infobar_type.h"
+#import "ios/chrome/browser/infobars/model/infobar_utils.h"
+#import "ios/chrome/browser/shared/model/browser/browser.h"
+#import "ios/chrome/browser/shared/model/browser/browser_list.h"
+#import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
+#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
+#import "ios/chrome/browser/shared/model/web_state_list/tab_group.h"
+#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
+#import "ios/chrome/grit/ios_strings.h"
+#import "ui/base/l10n/l10n_util.h"
+
+using collaboration::messaging::CollaborationEvent;
+
+namespace {
+
+// Returns the `local_group_id` attached to the given `instant_message` if any.
+std::optional<tab_groups::LocalTabGroupID> GetLocalTabGroupId(
+    collaboration::messaging::InstantMessage instant_message) {
+  if (instant_message.attributions.empty()) {
+    return std::nullopt;
+  }
+  // For an InstantMessage, even if it aggregates multiple underlying events,
+  // they should all be related to the same tab or tab group.
+  if (instant_message.attributions[0].tab_group_metadata.has_value()) {
+    return instant_message.attributions[0]
+        .tab_group_metadata->local_tab_group_id;
+  }
+  return std::nullopt;
+}
+
+// Returns the local tab group for the given `local_tab_group_id` and `browser`.
+const TabGroup* GetLocalTabGroup(
+    std::optional<tab_groups::LocalTabGroupID> local_tab_group_id,
+    Browser* browser) {
+  if (!local_tab_group_id.has_value()) {
+    return nullptr;
+  }
+
+  WebStateList* web_state_list = browser->GetWebStateList();
+  for (const TabGroup* group : web_state_list->GetGroups()) {
+    if (group->tab_group_id() == local_tab_group_id.value()) {
+      return group;
+    }
+  }
+  return nullptr;
+}
+
+// Returns the Browser on which to display the infobar for the given
+// `instant_message`.
+Browser* GetBrowserFromInstantMessage(
+    collaboration::messaging::InstantMessage instant_message,
+    BrowserList* browser_list) {
+  std::set<Browser*> browsers =
+      browser_list->BrowsersOfType(BrowserList::BrowserType::kRegular);
+  std::optional<tab_groups::LocalTabGroupID> local_tab_group_id =
+      GetLocalTabGroupId(instant_message);
+
+  bool use_first_available_browser = false;
+  switch (instant_message.collaboration_event) {
+    case CollaborationEvent::TAB_UPDATED:
+    case CollaborationEvent::TAB_REMOVED:
+    case CollaborationEvent::COLLABORATION_MEMBER_ADDED:
+    case CollaborationEvent::TAB_ADDED:
+    case CollaborationEvent::TAB_GROUP_ADDED:
+    case CollaborationEvent::TAB_GROUP_NAME_UPDATED:
+    case CollaborationEvent::TAB_GROUP_COLOR_UPDATED:
+    case CollaborationEvent::COLLABORATION_ADDED:
+    case CollaborationEvent::COLLABORATION_MEMBER_REMOVED:
+      break;
+    case CollaborationEvent::TAB_GROUP_REMOVED:
+    case CollaborationEvent::UNDEFINED:
+    case CollaborationEvent::COLLABORATION_REMOVED:
+      use_first_available_browser = true;
+      break;
+  }
+
+  // Retrieve the `source_browser`.
+  Browser* source_browser;
+  for (Browser* browser : browsers) {
+    // TODO(crbug.com/375595834): Handle cases where the `local_tab_group_id` is
+    // not set.
+    if (!local_tab_group_id.has_value() || use_first_available_browser) {
+      // If `local_tab_group_id` is empty, use the first available browser.
+      source_browser = browser;
+      break;
+    }
+    if (GetLocalTabGroup(local_tab_group_id, browser)) {
+      source_browser = browser;
+    }
+  }
+  return source_browser;
+}
+
+}  // namespace
+
+// static
+bool CollaborationGroupInfoBarDelegate::Create(
+    ProfileIOS* profile,
+    collaboration::messaging::InstantMessage instant_message) {
+  BrowserList* browser_list = BrowserListFactory::GetForProfile(profile);
+  Browser* source_browser =
+      GetBrowserFromInstantMessage(instant_message, browser_list);
+
+  web::WebState* active_web_state =
+      source_browser->GetWebStateList()->GetActiveWebState();
+  if (!active_web_state) {
+    return false;
+  }
+
+  infobars::InfoBarManager* infobar_manager =
+      InfoBarManagerImpl::FromWebState(active_web_state);
+
+  std::unique_ptr<CollaborationGroupInfoBarDelegate> delegate(
+      new CollaborationGroupInfoBarDelegate(profile, instant_message));
+  std::unique_ptr<InfoBarIOS> infobar = std::make_unique<InfoBarIOS>(
+      InfobarType::kInfobarTypeCollaborationGroup, std::move(delegate));
+  return !!infobar_manager->AddInfoBar(std::move(infobar));
+}
+
+CollaborationGroupInfoBarDelegate::CollaborationGroupInfoBarDelegate(
+    ProfileIOS* profile,
+    collaboration::messaging::InstantMessage instant_message)
+    : profile_(profile), instant_message_(instant_message) {
+  CHECK(!profile->IsOffTheRecord());
+}
+
+CollaborationGroupInfoBarDelegate::~CollaborationGroupInfoBarDelegate() {}
+
+infobars::InfoBarDelegate::InfoBarIdentifier
+CollaborationGroupInfoBarDelegate::GetIdentifier() const {
+  return TAB_SHARING_INFOBAR_DELEGATE;
+}
+
+std::u16string CollaborationGroupInfoBarDelegate::GetMessageText() const {
+  return u"";
+}
+
+std::u16string CollaborationGroupInfoBarDelegate::GetTitleText() const {
+  return instant_message_.localized_message;
+}
+
+int CollaborationGroupInfoBarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+std::u16string CollaborationGroupInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  switch (instant_message_.collaboration_event) {
+    case CollaborationEvent::TAB_UPDATED:
+    case CollaborationEvent::TAB_REMOVED:
+      return l10n_util::GetStringUTF16(
+          IDS_IOS_COLLABORATION_GROUP_TAB_REOPEN_PRIMARY_TOOLBAR_BUTTON);
+    case CollaborationEvent::COLLABORATION_MEMBER_ADDED:
+      return l10n_util::GetStringUTF16(
+          IDS_IOS_COLLABORATION_GROUP_MEMBER_ADDED_PRIMARY_TOOLBAR_BUTTON);
+    case CollaborationEvent::UNDEFINED:
+    case CollaborationEvent::TAB_ADDED:
+    case CollaborationEvent::TAB_GROUP_REMOVED:
+    case CollaborationEvent::TAB_GROUP_ADDED:
+    case CollaborationEvent::TAB_GROUP_NAME_UPDATED:
+    case CollaborationEvent::TAB_GROUP_COLOR_UPDATED:
+    case CollaborationEvent::COLLABORATION_ADDED:
+    case CollaborationEvent::COLLABORATION_REMOVED:
+    case CollaborationEvent::COLLABORATION_MEMBER_REMOVED:
+      return l10n_util::GetStringUTF16(
+          IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON);
+  }
+}
+
+bool CollaborationGroupInfoBarDelegate::Accept() {
+  // TODO(crbug.com/375595834): Implement this.
+  return true;
+}
+
+void CollaborationGroupInfoBarDelegate::InfoBarDismissed() {
+  ConfirmInfoBarDelegate::InfoBarDismissed();
+}
+
+UIImage* CollaborationGroupInfoBarDelegate::GetAvatarImage() {
+  // TODO(crbug.com/375595834): Update this to show avatars when needed.
+  return nil;
+}
diff --git a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.h b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.h
index e29acda..3590e7ac 100644
--- a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.h
+++ b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.h
@@ -5,9 +5,12 @@
 #ifndef IOS_CHROME_BROWSER_COLLABORATION_MODEL_MESSAGING_INSTANT_MESSAGING_SERVICE_H_
 #define IOS_CHROME_BROWSER_COLLABORATION_MODEL_MESSAGING_INSTANT_MESSAGING_SERVICE_H_
 
+#import "base/memory/raw_ptr.h"
 #import "components/collaboration/public/messaging/messaging_backend_service.h"
 #import "components/keyed_service/core/keyed_service.h"
 
+class ProfileIOS;
+
 namespace collaboration::messaging {
 
 using SuccessCallback = collaboration::messaging::MessagingBackendService::
@@ -18,7 +21,7 @@
       public collaboration::messaging::MessagingBackendService::
           InstantMessageDelegate {
  public:
-  InstantMessagingService();
+  InstantMessagingService(ProfileIOS* profile);
   InstantMessagingService(const InstantMessagingService&) = delete;
   InstantMessagingService& operator=(const InstantMessagingService&) = delete;
   ~InstantMessagingService() override;
@@ -28,6 +31,14 @@
       collaboration::messaging::InstantMessage message,
       MessagingBackendService::InstantMessageDelegate::SuccessCallback
           success_callback) override;
+
+ private:
+  // Shows a collaboration group infobar for the given `instant_message`.
+  // Returns `true` if the infobar has been displayed.
+  bool ShowCollaboraitonGroupInfobar(
+      collaboration::messaging::InstantMessage instant_message);
+
+  raw_ptr<ProfileIOS> profile_ = nullptr;
 };
 
 }  // namespace collaboration::messaging
diff --git a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.mm b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.mm
index 3bc072b..dac2c30 100644
--- a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.mm
+++ b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.mm
@@ -5,22 +5,42 @@
 #import "ios/chrome/browser/collaboration/model/messaging/instant_messaging_service.h"
 
 #import "base/functional/callback.h"
+#import "ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h"
+#import "ios/chrome/browser/infobars/model/infobar_ios.h"
+#import "ios/chrome/browser/infobars/model/infobar_manager_impl.h"
+#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 
 namespace collaboration::messaging {
 
-InstantMessagingService::InstantMessagingService() {}
+InstantMessagingService::InstantMessagingService(ProfileIOS* profile)
+    : profile_(profile) {
+  DCHECK(profile_);
+}
 InstantMessagingService::~InstantMessagingService() {}
 
 void InstantMessagingService::DisplayInstantaneousMessage(
-    collaboration::messaging::InstantMessage message,
+    collaboration::messaging::InstantMessage instant_message,
     MessagingBackendService::InstantMessageDelegate::SuccessCallback
         success_callback) {
-  // TODO(crbug.com/375595834): Send the message to the UI components.
+  bool message_displayed = false;
 
-  // Inform the backend that the message was displayed.
-  std::move(success_callback).Run(true);
-  // TODO(crbug.com/375595834): Call the callback with `false` when showing the
-  // message fails.
+  switch (instant_message.level) {
+    case InstantNotificationLevel::UNDEFINED:
+    case InstantNotificationLevel::SYSTEM:
+      break;
+    case InstantNotificationLevel::BROWSER:
+      message_displayed = ShowCollaboraitonGroupInfobar(instant_message);
+      break;
+  }
+
+  std::move(success_callback).Run(message_displayed);
+}
+
+bool InstantMessagingService::ShowCollaboraitonGroupInfobar(
+    collaboration::messaging::InstantMessage instant_message) {
+  bool infobar_displayed =
+      CollaborationGroupInfoBarDelegate::Create(profile_, instant_message);
+  return infobar_displayed;
 }
 
 }  // namespace collaboration::messaging
diff --git a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service_factory.mm b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service_factory.mm
index e747a39..5f2883f 100644
--- a/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service_factory.mm
+++ b/ios/chrome/browser/collaboration/model/messaging/instant_messaging_service_factory.mm
@@ -49,7 +49,7 @@
     return nullptr;
   }
 
-  return std::make_unique<InstantMessagingService>();
+  return std::make_unique<InstantMessagingService>(profile);
 }
 
 }  // namespace collaboration::messaging
diff --git a/ios/chrome/browser/context_menu/ui_bundled/BUILD.gn b/ios/chrome/browser/context_menu/ui_bundled/BUILD.gn
index b04f900..b6df456 100644
--- a/ios/chrome/browser/context_menu/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/context_menu/ui_bundled/BUILD.gn
@@ -51,6 +51,7 @@
     "//ios/public/provider/chrome/browser/context_menu:context_menu_api",
     "//ios/public/provider/chrome/browser/lens:lens_api",
     "//ios/web/common",
+    "//ios/web/public/js_image_transcoder",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/context_menu/ui_bundled/context_menu_configuration_provider.mm b/ios/chrome/browser/context_menu/ui_bundled/context_menu_configuration_provider.mm
index c61c814..b4e0d22 100644
--- a/ios/chrome/browser/context_menu/ui_bundled/context_menu_configuration_provider.mm
+++ b/ios/chrome/browser/context_menu/ui_bundled/context_menu_configuration_provider.mm
@@ -67,6 +67,7 @@
 #import "ios/public/provider/chrome/browser/lens/lens_api.h"
 #import "ios/web/common/features.h"
 #import "ios/web/common/url_scheme_util.h"
+#import "ios/web/public/js_image_transcoder/java_script_image_transcoder.h"
 #import "ios/web/public/ui/context_menu_params.h"
 #import "ios/web/public/web_state.h"
 #import "net/base/apple/url_conversions.h"
@@ -110,6 +111,9 @@
 
   // Whether the context menu is presented in the lens overlay.
   BOOL _isLensOverlay;
+
+  // Image transcoder to locally re-encode images to search.
+  std::unique_ptr<web::JavaScriptImageTranscoder> _imageTranscoder;
 }
 
 - (instancetype)initWithBrowser:(Browser*)browser
@@ -143,6 +147,7 @@
   _imageSaver = nil;
   [_imageCopier stop];
   _imageCopier = nil;
+  _imageTranscoder = nullptr;
   _baseWebState = nullptr;
 }
 
@@ -540,16 +545,40 @@
   ImageFetchTabHelper* imageFetcher =
       ImageFetchTabHelper::FromWebState(self.webState);
   DCHECK(imageFetcher);
+
   __weak ContextMenuConfigurationProvider* weakSelf = self;
-  imageFetcher->GetImageData(imageURL, referrer, ^(NSData* data) {
-    if (usingLens) {
-      [weakSelf searchImageUsingLensWithData:data];
-    } else {
-      [weakSelf searchByImageData:data imageURL:imageURL];
-    }
+  imageFetcher->GetImageData(imageURL, referrer, ^(NSData* rawData) {
+    // Arbitrary web image data requires sanitization before use.
+    [weakSelf sanitizeImageData:rawData
+                     completion:^(NSData* transcodedData) {
+                       if (usingLens) {
+                         [weakSelf searchImageUsingLensWithData:transcodedData];
+                       } else {
+                         [weakSelf searchByImageData:transcodedData
+                                            imageURL:imageURL];
+                       }
+                     }];
   });
 }
 
+// Sanitizes a web image data before use by passing it through the transcoder.
+- (void)sanitizeImageData:(NSData*)imageData
+               completion:(void (^)(NSData*))completion {
+  if (!_imageTranscoder) {
+    _imageTranscoder = std::make_unique<web::JavaScriptImageTranscoder>();
+  }
+  _imageTranscoder->TranscodeImage(
+      imageData, @"image/jpeg", nil, nil, nil,
+      base::BindOnce(^(NSData* result, NSError* error) {
+        if (error) {
+          completion(nil);
+          return;
+        }
+
+        completion(result);
+      }));
+}
+
 // Starts a reverse image search based on `imageData` and `imageURL` in a new
 // tab.
 - (void)searchByImageData:(NSData*)imageData imageURL:(const GURL&)URL {
diff --git a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.h b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.h
index c35e5ba6..7199e2c 100644
--- a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.h
+++ b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.h
@@ -20,17 +20,17 @@
 
   // web::JavaScriptDialogPresenter:
   void RunJavaScriptAlertDialog(web::WebState* web_state,
-                                const GURL& origin_url,
+                                const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback) override;
   void RunJavaScriptConfirmDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback) override;
   void RunJavaScriptPromptDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback) override;
diff --git a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.mm b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.mm
index 2de8f2b7..5b20cf2f 100644
--- a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.mm
+++ b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter.mm
@@ -135,7 +135,7 @@
 
 void OverlayJavaScriptDialogPresenter::RunJavaScriptAlertDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceClosure callback) {
   JavaScriptDialogBlockingState::CreateForWebState(web_state);
@@ -145,9 +145,9 @@
     return;
   }
 
+  const GURL origin_url = origin.GetURL();
   bool from_main_frame_origin =
-      origin_url.DeprecatedGetOriginAsURL() ==
-      web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
+      origin_url == web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
   std::unique_ptr<OverlayRequest> request =
       OverlayRequest::CreateWithConfig<JavaScriptAlertDialogRequest>(
           web_state, origin_url, from_main_frame_origin, message_text);
@@ -160,7 +160,7 @@
 
 void OverlayJavaScriptDialogPresenter::RunJavaScriptConfirmDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceCallback<void(bool success)> callback) {
   JavaScriptDialogBlockingState::CreateForWebState(web_state);
@@ -170,9 +170,9 @@
     return;
   }
 
+  const GURL origin_url = origin.GetURL();
   bool from_main_frame_origin =
-      origin_url.DeprecatedGetOriginAsURL() ==
-      web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
+      origin_url == web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
   std::unique_ptr<OverlayRequest> request =
       OverlayRequest::CreateWithConfig<JavaScriptConfirmDialogRequest>(
           web_state, origin_url, from_main_frame_origin, message_text);
@@ -185,7 +185,7 @@
 
 void OverlayJavaScriptDialogPresenter::RunJavaScriptPromptDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     NSString* default_prompt_text,
     base::OnceCallback<void(NSString* user_input)> callback) {
@@ -196,9 +196,9 @@
     return;
   }
 
+  const GURL origin_url = origin.GetURL();
   bool from_main_frame_origin =
-      origin_url.DeprecatedGetOriginAsURL() ==
-      web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
+      origin_url == web_state->GetLastCommittedURL().DeprecatedGetOriginAsURL();
   std::unique_ptr<OverlayRequest> request =
       OverlayRequest::CreateWithConfig<JavaScriptPromptDialogRequest>(
           web_state, origin_url, from_main_frame_origin, message_text,
diff --git a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter_unittest.mm b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter_unittest.mm
index 4cc2953..8db7eca 100644
--- a/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter_unittest.mm
+++ b/ios/chrome/browser/dialogs/ui_bundled/overlay_java_script_dialog_presenter_unittest.mm
@@ -19,11 +19,12 @@
 // Test fixture for OverlayJavaScriptDialogPresenter.
 class OverlayJavaScriptDialogPresenterTest : public PlatformTest {
  protected:
-  OverlayJavaScriptDialogPresenterTest() : url_("http://chromium.test") {
+  OverlayJavaScriptDialogPresenterTest()
+      : origin_(url::Origin::Create(GURL("http://chromium.test"))) {
     OverlayRequestQueue::CreateForWebState(&web_state_);
   }
 
-  const GURL url_;
+  const url::Origin origin_;
   web::FakeWebState web_state_;
   OverlayJavaScriptDialogPresenter presenter_;
 };
@@ -31,7 +32,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptAlertRequest.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunJavaScriptAlertDialog) {
-  presenter_.RunJavaScriptAlertDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptAlertDialog(&web_state_, origin_, @"",
                                       base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -45,7 +46,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptConfirmationOverlayRequestConfig.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunJavaScriptConfirmDialog) {
-  presenter_.RunJavaScriptConfirmDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptConfirmDialog(&web_state_, origin_, @"",
                                         base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -59,7 +60,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptPromptOverlayRequestConfig.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunJavaScriptPromptDialog) {
-  presenter_.RunJavaScriptPromptDialog(&web_state_, url_, @"", @"",
+  presenter_.RunJavaScriptPromptDialog(&web_state_, origin_, @"", @"",
                                        base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -73,7 +74,7 @@
 // Tests that the presenter removes all requests from the queue when
 // CancelDialogs() is called.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunJavaScriptDialogCancelDialogs) {
-  presenter_.RunJavaScriptAlertDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptAlertDialog(&web_state_, origin_, @"",
                                       base::DoNothing());
   OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
       &web_state_, OverlayModality::kWebContentArea);
@@ -87,7 +88,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptAlertRequest.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunAlert) {
-  presenter_.RunJavaScriptAlertDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptAlertDialog(&web_state_, origin_, @"",
                                       base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -103,7 +104,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptConfirmationOverlayRequestConfig.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunConfirmation) {
-  presenter_.RunJavaScriptConfirmDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptConfirmDialog(&web_state_, origin_, @"",
                                         base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -119,7 +120,7 @@
 // Tests that the presenter adds an OverlayRequest configured with a
 // JavaScriptPromptOverlayRequestConfig.
 TEST_F(OverlayJavaScriptDialogPresenterTest, RunPrompt) {
-  presenter_.RunJavaScriptPromptDialog(&web_state_, url_, @"", @"",
+  presenter_.RunJavaScriptPromptDialog(&web_state_, origin_, @"", @"",
                                        base::DoNothing());
 
   // Verify that an alert OverlayRequest is added to the queue.
@@ -135,7 +136,7 @@
 // Tests that the presenter removes all requests from the queue when
 // CancelDialogs() is called.
 TEST_F(OverlayJavaScriptDialogPresenterTest, CancelDialogs) {
-  presenter_.RunJavaScriptAlertDialog(&web_state_, url_, @"",
+  presenter_.RunJavaScriptAlertDialog(&web_state_, origin_, @"",
                                       base::DoNothing());
   OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
       &web_state_, OverlayModality::kWebContentArea);
diff --git a/ios/chrome/browser/download/coordinator/auto_deletion/auto_deletion_settings_mediator.mm b/ios/chrome/browser/download/coordinator/auto_deletion/auto_deletion_settings_mediator.mm
index 3afffc9..829bebf 100644
--- a/ios/chrome/browser/download/coordinator/auto_deletion/auto_deletion_settings_mediator.mm
+++ b/ios/chrome/browser/download/coordinator/auto_deletion/auto_deletion_settings_mediator.mm
@@ -46,6 +46,8 @@
 
 - (void)disconnect {
   _localState = nullptr;
+  [_autoDeletionEnabled stop];
+  [_autoDeletionEnabled setObserver:nil];
   _autoDeletionEnabled = nullptr;
 }
 
diff --git a/ios/chrome/browser/feature_engagement/model/BUILD.gn b/ios/chrome/browser/feature_engagement/model/BUILD.gn
index ca6c916..d60761c 100644
--- a/ios/chrome/browser/feature_engagement/model/BUILD.gn
+++ b/ios/chrome/browser/feature_engagement/model/BUILD.gn
@@ -76,6 +76,7 @@
     "//ios/chrome/browser/signin/model:fake_system_identity",
     "//ios/chrome/browser/signin/model:fake_system_identity_manager",
     "//ios/chrome/browser/signin/model:test_support",
+    "//ios/chrome/test:test_support",
     "//ios/web/public/test",
     "//testing/gtest",
   ]
diff --git a/ios/chrome/browser/feature_engagement/model/event_exporter_unittest.mm b/ios/chrome/browser/feature_engagement/model/event_exporter_unittest.mm
index 81cda3c..27f7192 100644
--- a/ios/chrome/browser/feature_engagement/model/event_exporter_unittest.mm
+++ b/ios/chrome/browser/feature_engagement/model/event_exporter_unittest.mm
@@ -23,6 +23,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/identity_manager_factory.h"
+#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
 #import "ios/web/public/test/web_task_environment.h"
 #import "testing/platform_test.h"
 
@@ -110,6 +111,7 @@
     }
   }
 
+  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
   web::WebTaskEnvironment task_environment_;
   base::RunLoop run_loop_;
   std::unique_ptr<feature_engagement::Tracker> tracker_;
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator.mm
index 552a350..e90fe4d9 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator.mm
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator.mm
@@ -153,7 +153,7 @@
 
 #pragma mark - UISheetPresentationControllerDelegate
 
-- (void)presentationControllerWillDismiss:
+- (void)presentationControllerDidDismiss:
     (UIPresentationController*)presentationController {
   [self dismissMenuPage];
   [self dismissBackgroundPickerActionSheet];
diff --git a/ios/chrome/browser/infobars/model/infobar_metrics_recorder.mm b/ios/chrome/browser/infobars/model/infobar_metrics_recorder.mm
index 1672155..f0380fbf 100644
--- a/ios/chrome/browser/infobars/model/infobar_metrics_recorder.mm
+++ b/ios/chrome/browser/infobars/model/infobar_metrics_recorder.mm
@@ -143,6 +143,16 @@
 const char kInfobarTypeSigninBadgeTappedHistogram[] =
     "Mobile.Messages.Badge.Tapped.InfobarTypeSignin";
 
+// Histogram names for collaboration group banner.
+const char kInfobarCollaborationGroupBannerEventHistogram[] =
+    "Mobile.Messages.Banner.Event.kInfobarCollaborationGroup";
+const char kInfobarCollaborationGroupBannerDismissTypeHistogram[] =
+    "Mobile.Messages.Banner.Dismiss.kInfobarCollaborationGroup";
+const char kInfobarCollaborationGroupModalEventHistogram[] =
+    "Mobile.Messages.Modal.Event.kInfobarCollaborationGroup";
+const char kInfobarCollaborationGroupBadgeTappedHistogram[] =
+    "Mobile.Messages.Badge.Tapped.kInfobarCollaborationGroup";
+
 }  // namespace
 
 @interface InfobarMetricsRecorder ()
@@ -203,6 +213,10 @@
     case InfobarType::kInfobarTypeSignin:
       UMA_HISTOGRAM_ENUMERATION(kInfobarTypeSigninBannerEventHistogram, event);
       break;
+    case InfobarType::kInfobarTypeCollaborationGroup:
+      UMA_HISTOGRAM_ENUMERATION(kInfobarCollaborationGroupBannerEventHistogram,
+                                event);
+      break;
   }
 }
 
@@ -253,6 +267,10 @@
       UMA_HISTOGRAM_ENUMERATION(kInfobarTypeSigninBannerDismissTypeHistogram,
                                 dismissType);
       break;
+    case InfobarType::kInfobarTypeCollaborationGroup:
+      UMA_HISTOGRAM_ENUMERATION(
+          kInfobarCollaborationGroupBannerDismissTypeHistogram, dismissType);
+      break;
   }
 }
 
@@ -301,6 +319,10 @@
     case InfobarType::kInfobarTypeSignin:
       UMA_HISTOGRAM_ENUMERATION(kInfobarTypeSigninModalEventHistogram, event);
       break;
+    case InfobarType::kInfobarTypeCollaborationGroup:
+      UMA_HISTOGRAM_ENUMERATION(kInfobarCollaborationGroupModalEventHistogram,
+                                event);
+      break;
   }
 }
 
@@ -344,6 +366,10 @@
     case InfobarType::kInfobarTypeSignin:
       UMA_HISTOGRAM_ENUMERATION(kInfobarTypeSigninBadgeTappedHistogram, state);
       break;
+    case InfobarType::kInfobarTypeCollaborationGroup:
+      UMA_HISTOGRAM_ENUMERATION(kInfobarCollaborationGroupBadgeTappedHistogram,
+                                state);
+      break;
   }
 }
 
diff --git a/ios/chrome/browser/infobars/model/infobar_type.h b/ios/chrome/browser/infobars/model/infobar_type.h
index f543b23..983ce46a 100644
--- a/ios/chrome/browser/infobars/model/infobar_type.h
+++ b/ios/chrome/browser/infobars/model/infobar_type.h
@@ -32,7 +32,9 @@
   // Message Infobar for Enhanced Safe Browsing.
   kInfobarTypeEnhancedSafeBrowsing = 12,
   // Message Infobar for non modal sign-in promo.
-  kInfobarTypeSignin = 13
+  kInfobarTypeSignin = 13,
+  // Message Infobar for collaboration group update.
+  kInfobarTypeCollaborationGroup = 14
 };
 
 // Message "Confirm Infobars" types, these are the generic kInfobarTypeConfirm
diff --git a/ios/chrome/browser/infobars/model/overlays/browser_agent/infobar_overlay_browser_agent_util.mm b/ios/chrome/browser/infobars/model/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
index 65d888e8..2015441 100644
--- a/ios/chrome/browser/infobars/model/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
+++ b/ios/chrome/browser/infobars/model/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
@@ -39,6 +39,9 @@
   browser_agent->AddDefaultInfobarInteractionHandlerForInfobarType(
       InfobarType::kInfobarTypeEnhancedSafeBrowsing);
 
+  browser_agent->AddDefaultInfobarInteractionHandlerForInfobarType(
+      InfobarType::kInfobarTypeCollaborationGroup);
+
   browser_agent->AddInfobarInteractionHandler(
       std::make_unique<InfobarInteractionHandler>(
           InfobarType::kInfobarTypeConfirm,
diff --git a/ios/chrome/browser/infobars/model/overlays/default_infobar_overlay_request_factory.mm b/ios/chrome/browser/infobars/model/overlays/default_infobar_overlay_request_factory.mm
index 14bb62bb..b28cc51 100644
--- a/ios/chrome/browser/infobars/model/overlays/default_infobar_overlay_request_factory.mm
+++ b/ios/chrome/browser/infobars/model/overlays/default_infobar_overlay_request_factory.mm
@@ -26,6 +26,7 @@
     case InfobarType::kInfobarTypeSyncError:
     case InfobarType::kInfobarTypeTranslate:
     case InfobarType::kInfobarTypeEnhancedSafeBrowsing:
+    case InfobarType::kInfobarTypeCollaborationGroup:
       return OverlayRequest::CreateWithConfig<
           DefaultInfobarOverlayRequestConfig>(infobar_ios, overlay_type);
 
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
index 81c4da99..355bfa2 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
@@ -871,7 +871,7 @@
     [handler showSettingsFromViewController:self.baseViewController];
   } else if (isSignedIn) {
     if (IsIdentityDiscAccountMenuEnabled()) {
-      [self showAccountMenu:identityDisc fromWeb:NO];
+      [self showAccountMenu:identityDisc];
     } else {
       [handler showSettingsFromViewController:self.baseViewController];
     }
@@ -1507,14 +1507,14 @@
 
 #pragma mark - Private
 
-- (void)showAccountMenu:(UIView*)identityDisc fromWeb:(BOOL)fromWeb {
+- (void)showAccountMenu:(UIView*)identityDisc {
   _accountMenuCoordinator = [SigninCoordinator
       accountMenuCoordinatorWithBaseViewController:self.NTPViewController
                                            browser:self.browser
                                       contextStyle:SigninContextStyle::kDefault
                                         anchorView:identityDisc
                                        accessPoint:AccountMenuAccessPoint::
-                                                       kWeb];
+                                                       kNewTabPage];
   __typeof(self) weakSelf = self;
   _accountMenuCoordinator.signinCompletion =
       ^(SigninCoordinatorResult, id<SystemIdentity>) {
diff --git a/ios/chrome/browser/omnibox/coordinator/omnibox_coordinator.mm b/ios/chrome/browser/omnibox/coordinator/omnibox_coordinator.mm
index f561a78..81f2f77 100644
--- a/ios/chrome/browser/omnibox/coordinator/omnibox_coordinator.mm
+++ b/ios/chrome/browser/omnibox/coordinator/omnibox_coordinator.mm
@@ -138,9 +138,9 @@
       LayoutGuideCenterForBrowser(self.browser);
   self.viewController.searchOnlyUI = self.searchOnlyUI;
 
-  BOOL isIncognito = self.profile->IsOffTheRecord();
+  BOOL incognito = self.profile->IsOffTheRecord();
   self.mediator = [[OmniboxMediator alloc]
-      initWithIncognito:isIncognito
+      initWithIncognito:incognito
                 tracker:feature_engagement::TrackerFactory::GetForProfile(
                             self.profile)
           isLensOverlay:_isLensOverlay];
@@ -227,7 +227,7 @@
                                     : nullptr];
   autocompleteResultWrapper.pedalAnnotator = annotator;
   autocompleteResultWrapper.templateURLService = templateURLService;
-  autocompleteResultWrapper.isIncognito = isIncognito;
+  autocompleteResultWrapper.incognito = incognito;
   autocompleteResultWrapper.delegate = _omniboxAutocompleteController;
 
   _omniboxAutocompleteController.autocompleteResultWrapper =
diff --git a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h
index e7eb5c9d..0b4eee2 100644
--- a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h
+++ b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h
@@ -33,7 +33,7 @@
 @property(nonatomic, strong) OmniboxPedalAnnotator* pedalAnnotator;
 
 /// Whether or not browser is in incognito mode.
-@property(nonatomic, assign) BOOL isIncognito;
+@property(nonatomic, assign) BOOL incognito;
 
 /// TemplateURLService to observe default search engine change.
 @property(nonatomic, assign) TemplateURLService* templateURLService;
diff --git a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
index d668922e..3ccbd3b9 100644
--- a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
@@ -118,7 +118,7 @@
   AutocompleteMatchFormatter* formatter =
       [AutocompleteMatchFormatter formatterWithMatch:match];
   formatter.starred = [self isStarredMatch:match];
-  formatter.incognito = self.isIncognito;
+  formatter.incognito = self.incognito;
   formatter.defaultSearchEngineIsGoogle = _defaultSearchEngineIsGoogle;
   formatter.pedalData = [self.pedalAnnotator pedalForMatch:match];
   formatter.isMultimodal = self.hasThumbnail;
diff --git a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
index 8d60009..bd5395ad 100644
--- a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
@@ -47,7 +47,7 @@
         /*view=*/nullptr, std::move(omnibox_client));
     wrapper_ = [[AutocompleteResultWrapper alloc]
         initWithOmniboxClient:omnibox_controller_->client()];
-    wrapper_.isIncognito = NO;
+    wrapper_.incognito = NO;
     wrapper_.templateURLService =
         search_engines_test_environment_.template_url_service();
     wrapper_.delegate = _fake_autocomplete_wrapper_delegate;
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/BUILD.gn b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/BUILD.gn
index 2bcdc5e..b5671d5d 100644
--- a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/BUILD.gn
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/BUILD.gn
@@ -25,6 +25,7 @@
     "//ios/chrome/browser/overlays/ui_bundled:coordinators",
     "//ios/chrome/browser/overlays/ui_bundled:util",
     "//ios/chrome/browser/overlays/ui_bundled/infobar_banner/autofill_address_profile",
+    "//ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group",
     "//ios/chrome/browser/overlays/ui_bundled/infobar_banner/confirm",
     "//ios/chrome/browser/overlays/ui_bundled/infobar_banner/passwords",
     "//ios/chrome/browser/overlays/ui_bundled/infobar_banner/permissions",
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/BUILD.gn b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/BUILD.gn
new file mode 100644
index 0000000..7065e2d
--- /dev/null
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("collaboration_group") {
+  sources = [
+    "collaboration_group_infobar_banner_overlay_mediator.h",
+    "collaboration_group_infobar_banner_overlay_mediator.mm",
+  ]
+
+  deps = [
+    "//base",
+    "//ios/chrome/browser/collaboration/model/messaging/infobar",
+    "//ios/chrome/browser/infobars/model",
+    "//ios/chrome/browser/infobars/ui_bundled/banners",
+    "//ios/chrome/browser/overlays/model",
+    "//ios/chrome/browser/overlays/model/public/default",
+    "//ios/chrome/browser/overlays/model/public/infobar_banner",
+    "//ios/chrome/browser/overlays/ui_bundled:coordinators",
+    "//ios/chrome/browser/overlays/ui_bundled/infobar_banner:mediators",
+    "//ios/chrome/browser/shared/ui/symbols",
+    "//ios/chrome/common/ui/colors",
+    "//ui/base",
+  ]
+}
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/DEPS b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/DEPS
new file mode 100644
index 0000000..288c21e
--- /dev/null
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ios/chrome/browser/collaboration/model/messaging/infobar",
+]
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.h b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.h
new file mode 100644
index 0000000..0a5c62e
--- /dev/null
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.h
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_OVERLAYS_UI_BUNDLED_INFOBAR_BANNER_COLLABORATION_GROUP_COLLABORATION_GROUP_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_OVERLAYS_UI_BUNDLED_INFOBAR_BANNER_COLLABORATION_GROUP_COLLABORATION_GROUP_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
+
+#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_mediator.h"
+
+// Mediator that configures an infobar banner for collaboration group.
+@interface CollaborationGroupInfobarBannerOverlayMediator
+    : InfobarBannerOverlayMediator
+@end
+
+#endif  // IOS_CHROME_BROWSER_OVERLAYS_UI_BUNDLED_INFOBAR_BANNER_COLLABORATION_GROUP_COLLABORATION_GROUP_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.mm
new file mode 100644
index 0000000..91aed87
--- /dev/null
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.mm
@@ -0,0 +1,95 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.h"
+
+#import "base/strings/sys_string_conversions.h"
+#import "ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.h"
+#import "ios/chrome/browser/infobars/model/infobar_ios.h"
+#import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_consumer.h"
+#import "ios/chrome/browser/overlays/model/public/default/default_infobar_overlay_request_config.h"
+#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h"
+#import "ios/chrome/browser/overlays/ui_bundled/overlay_request_mediator+subclassing.h"
+#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+
+@interface CollaborationGroupInfobarBannerOverlayMediator ()
+// The banner config from the request.
+@property(nonatomic, readonly) DefaultInfobarOverlayRequestConfig* config;
+// The delegate attached to the config.
+@property(nonatomic, readonly)
+    CollaborationGroupInfoBarDelegate* collaborationGroupDelegate;
+@end
+
+@implementation CollaborationGroupInfobarBannerOverlayMediator
+
+#pragma mark - Accessors
+
+- (DefaultInfobarOverlayRequestConfig*)config {
+  return self.request
+             ? self.request->GetConfig<DefaultInfobarOverlayRequestConfig>()
+             : nullptr;
+}
+
+- (CollaborationGroupInfoBarDelegate*)collaborationGroupDelegate {
+  return static_cast<CollaborationGroupInfoBarDelegate*>(
+      self.config->delegate());
+}
+
+#pragma mark - OverlayRequestMediator
+
++ (const OverlayRequestSupport*)requestSupport {
+  return DefaultInfobarOverlayRequestConfig::RequestSupport();
+}
+
+#pragma mark - InfobarOverlayRequestMediator
+
+- (void)bannerInfobarButtonWasPressed:(UIButton*)sender {
+  // This can happen if the user quickly navigates to another website while the
+  // banner is still appearing, causing the banner to be triggered before being
+  // removed.
+  if (!self.collaborationGroupDelegate) {
+    return;
+  }
+
+  self.collaborationGroupDelegate->Accept();
+  [self dismissOverlay];
+}
+
+@end
+
+@implementation CollaborationGroupInfobarBannerOverlayMediator (ConsumerSupport)
+
+// Configures consumer from the settings in `config`.
+- (void)configureConsumer {
+  id<InfobarBannerConsumer> consumer = self.consumer;
+  CollaborationGroupInfoBarDelegate* delegate = self.collaborationGroupDelegate;
+
+  [consumer setButtonText:base::SysUTF16ToNSString(delegate->GetButtonLabel(
+                              CollaborationGroupInfoBarDelegate::BUTTON_OK))];
+
+  UIImage* avatarImage = delegate->GetAvatarImage();
+  if (!avatarImage) {
+    // TODO(crbug.com/375595834): Update this once defined in the specs.
+    avatarImage = DefaultSymbolTemplateWithPointSize(kPersonFillSymbol,
+                                                     kInfobarSymbolPointSize);
+    [consumer setUseIconBackgroundTint:YES];
+    [consumer setIconBackgroundColor:[UIColor colorNamed:kBlueColor]];
+    [consumer
+        setIconImageTintColor:[UIColor colorNamed:kPrimaryBackgroundColor]];
+  }
+  [consumer setIconImage:avatarImage];
+
+  [consumer setPresentsModal:NO];
+  if (delegate->GetTitleText().empty()) {
+    [consumer
+        setTitleText:base::SysUTF16ToNSString(delegate->GetMessageText())];
+  } else {
+    [consumer setTitleText:base::SysUTF16ToNSString(delegate->GetTitleText())];
+    [consumer
+        setSubtitleText:base::SysUTF16ToNSString(delegate->GetMessageText())];
+  }
+}
+
+@end
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_coordinator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_coordinator.mm
index 15c96e9..7db2e3c 100644
--- a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_coordinator.mm
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_coordinator.mm
@@ -20,6 +20,7 @@
 #import "ios/chrome/browser/overlays/model/public/overlay_request_support.h"
 #import "ios/chrome/browser/overlays/model/public/overlay_response.h"
 #import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator.h"
+#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/collaboration_group/collaboration_group_infobar_banner_overlay_mediator.h"
 #import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.h"
 #import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/features.h"
 #import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_mediator.h"
@@ -248,6 +249,9 @@
     case InfobarType::kInfobarTypeEnhancedSafeBrowsing:
       mediatorClass = [EnhancedSafeBrowsingBannerOverlayMediator class];
       break;
+    case InfobarType::kInfobarTypeCollaborationGroup:
+      mediatorClass = [CollaborationGroupInfobarBannerOverlayMediator class];
+      break;
     default:
       NOTREACHED() << "Received unsupported infobarType.";
   }
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm
index 2e6c6aa..5370a45 100644
--- a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm
+++ b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm
@@ -33,7 +33,7 @@
 // confirmation state when VoiceOver is running. This is slightly greater than
 // `kConfirmationStateDuration` to give VoiceOver enough time to read the
 // required content.
-// TODO(crbug.com/339887700): When VO is running do not use this and listen for
+// TODO(crbug.com/413009143): When VO is running do not use this and listen for
 // VO announcement to finish before auto-closing the modal in confirmation
 // state.
 static constexpr base::TimeDelta kConfirmationStateDurationIfVoiceOverRunning =
diff --git a/ios/chrome/browser/passwords/model/password_controller_egtest.mm b/ios/chrome/browser/passwords/model/password_controller_egtest.mm
index fade3f7..7b321ca 100644
--- a/ios/chrome/browser/passwords/model/password_controller_egtest.mm
+++ b/ios/chrome/browser/passwords/model/password_controller_egtest.mm
@@ -173,7 +173,7 @@
 }
 
 - (void)setUp {
-  if ([self isRunningTest:@selector(testLoginEventReported)]) {
+  if ([self isRunningTest:@selector(FLAKY_testLoginEventReported)]) {
     // Start the servers before calling the superclass's `-setUp` so that their
     // addresses can be added to the app launch config. `GREYAssertTrue` can
     // only be used after calling the superclass's `-setUp`, so use `CHECK()`
@@ -226,7 +226,7 @@
   }
 
   // Set Enterprise features for testing password-related event reporting.
-  if ([self isRunningTest:@selector(testLoginEventReported)]) {
+  if ([self isRunningTest:@selector(FLAKY_testLoginEventReported)]) {
     CHECK(_policyServer);
     CHECK(_reportingServer);
     config.additional_args.push_back(
@@ -757,8 +757,9 @@
                                 password:passwordValue];
 }
 
+// TODO(crbug.com/413658473): Test fails with the app crashing.
 // Tests that log in events are reported to an enterprise connector.
-- (void)testLoginEventReported {
+- (void)FLAKY_testLoginEventReported {
   [self loadLoginPage];
 
   // Simulate login.
diff --git a/ios/chrome/browser/policy/model/BUILD.gn b/ios/chrome/browser/policy/model/BUILD.gn
index 880a335..ca4f2015 100644
--- a/ios/chrome/browser/policy/model/BUILD.gn
+++ b/ios/chrome/browser/policy/model/BUILD.gn
@@ -68,6 +68,7 @@
     "//components/autofill/core/browser",
     "//components/bookmarks/common",
     "//components/bookmarks/managed",
+    "//components/collaboration/public:prefs",
     "//components/commerce/core:pref_names",
     "//components/component_updater",
     "//components/enterprise",
diff --git a/ios/chrome/browser/policy/model/DEPS b/ios/chrome/browser/policy/model/DEPS
index 44994110..196470d 100644
--- a/ios/chrome/browser/policy/model/DEPS
+++ b/ios/chrome/browser/policy/model/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+ios/chrome/browser/policy_url_blocking/model",
   "+ios/chrome/browser/signin/model",
+  "+components/collaboration/public/pref_names.h",
   "+components/lens",
 ]
 
diff --git a/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm b/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm
index a7b6831c..26cd3f6 100644
--- a/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm
+++ b/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm
@@ -9,6 +9,7 @@
 #import "components/autofill/core/common/autofill_prefs.h"
 #import "components/bookmarks/common/bookmark_pref_names.h"
 #import "components/bookmarks/managed/managed_bookmarks_policy_handler.h"
+#import "components/collaboration/public/pref_names.h"
 #import "components/commerce/core/pref_names.h"
 #import "components/component_updater/pref_names.h"
 #import "components/content_settings/core/common/pref_names.h"
@@ -248,6 +249,12 @@
       std::make_unique<policy::GenAiDefaultSettingsPolicyHandler>(
           std::move(gen_ai_default_policies)));
 
+  handlers->AddHandler(std::make_unique<policy::CloudUserOnlyPolicyHandler>(
+      std::make_unique<SimplePolicyHandler>(
+          policy::key::kTabGroupSharingSettings,
+          collaboration::prefs::kSharedTabGroupsManagedAccountSetting,
+          base::Value::Type::INTEGER)));
+
   handlers->AddHandler(
       std::make_unique<
           enterprise_connectors::EnterpriseConnectorsPolicyHandler>(
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.h b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.h
index ad6dca1c..57eed75d 100644
--- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.h
+++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.h
@@ -95,7 +95,7 @@
 @property(nonatomic, assign) WebNavigationBrowserAgent* navigationAgent;
 
 // If the current session is off the record or not.
-@property(nonatomic, assign) bool isIncognito;
+@property(nonatomic, assign) bool incognito;
 
 // The Orderer to control the order of the overflow menu.
 @property(nonatomic, weak) OverflowMenuOrderer* menuOrderer;
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.mm
index 3e01318..2e66c3c 100644
--- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.mm
+++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator.mm
@@ -342,8 +342,8 @@
   [self updateModel];
 }
 
-- (void)setIsIncognito:(BOOL)isIncognito {
-  _isIncognito = isIncognito;
+- (void)setIncognito:(BOOL)incognito {
+  _incognito = incognito;
   [self updateModel];
 }
 
@@ -1884,7 +1884,7 @@
     case overflow_menu::Destination::Bookmarks:
       return self.bookmarksDestination;
     case overflow_menu::Destination::History:
-      return (self.isIncognito) ? nil : self.historyDestination;
+      return (self.incognito) ? nil : self.historyDestination;
     case overflow_menu::Destination::ReadingList:
       // Set badges if necessary.
       if (self.engagementTracker &&
@@ -1899,7 +1899,7 @@
     case overflow_menu::Destination::Downloads:
       return self.downloadsDestination;
     case overflow_menu::Destination::RecentTabs:
-      return self.isIncognito ? nil : self.recentTabsDestination;
+      return self.incognito ? nil : self.recentTabsDestination;
     case overflow_menu::Destination::SiteInfo:
       return ([self currentWebPageSupportsSiteInfo]) ? self.siteInfoDestination
                                                      : nil;
@@ -2056,7 +2056,7 @@
       return self.readLaterAction;
     case overflow_menu::ActionType::ClearBrowsingData:
       // Showing the Clear Browsing Data Action would be confusing in incognito.
-      return (self.isIncognito) ? nil : self.clearBrowsingDataAction;
+      return (self.incognito) ? nil : self.clearBrowsingDataAction;
     case overflow_menu::ActionType::Translate:
       return self.translateAction;
     case overflow_menu::ActionType::DesktopSite:
@@ -2422,8 +2422,8 @@
 - (void)openDownloads {
   [self dismissMenu];
   profile_metrics::BrowserProfileType type =
-      self.isIncognito ? profile_metrics::BrowserProfileType::kIncognito
-                       : profile_metrics::BrowserProfileType::kRegular;
+      self.incognito ? profile_metrics::BrowserProfileType::kIncognito
+                     : profile_metrics::BrowserProfileType::kRegular;
   UmaHistogramEnumeration("Download.OpenDownloadsFromMenu.PerProfileType",
                           type);
   [self.browserCoordinatorHandler showDownloadsFolder];
@@ -2463,8 +2463,8 @@
 
   [self dismissMenu];
   profile_metrics::BrowserProfileType type =
-      self.isIncognito ? profile_metrics::BrowserProfileType::kIncognito
-                       : profile_metrics::BrowserProfileType::kRegular;
+      self.incognito ? profile_metrics::BrowserProfileType::kIncognito
+                     : profile_metrics::BrowserProfileType::kRegular;
   UmaHistogramEnumeration("Settings.OpenSettingsFromMenu.PerProfileType", type);
   [self.applicationHandler
       showSettingsFromViewController:self.baseViewController
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator_unittest.mm b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator_unittest.mm
index afd0403..3f8aa4a3 100644
--- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator_unittest.mm
+++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_mediator_unittest.mm
@@ -243,12 +243,12 @@
   }
 
  protected:
-  OverflowMenuMediator* CreateMediator(BOOL is_incognito) {
-    orderer_ = [[OverflowMenuOrderer alloc] initWithIsIncognito:is_incognito];
+  OverflowMenuMediator* CreateMediator(BOOL incognito) {
+    orderer_ = [[OverflowMenuOrderer alloc] initWithIsIncognito:incognito];
     orderer_.model = model_;
 
     mediator_ = [[OverflowMenuMediator alloc] init];
-    mediator_.isIncognito = is_incognito;
+    mediator_.incognito = incognito;
     mediator_.menuOrderer = orderer_;
     mediator_.baseViewController = baseViewController_;
     mediator_.localStatePrefs = localStatePrefs_.get();
@@ -258,9 +258,9 @@
   }
 
   OverflowMenuMediator* CreateMediatorWithBrowserPolicyConnector(
-      BOOL is_incognito,
+      BOOL incognito,
       BrowserPolicyConnectorIOS* browser_policy_connector) {
-    CreateMediator(is_incognito);
+    CreateMediator(incognito);
     mediator_.browserPolicyConnector = browser_policy_connector;
     return mediator_;
   }
@@ -461,7 +461,7 @@
 // Tests that the feature engagement tracker get notified when the mediator is
 // disconnected and the tracker wants the notification badge displayed.
 TEST_F(OverflowMenuMediatorTest, TestFeatureEngagementDisconnect) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   EXPECT_CALL(tracker_, ShouldTriggerHelpUI(testing::_))
       .WillRepeatedly(Return(true));
   mediator_.engagementTracker = &tracker_;
@@ -476,7 +476,7 @@
 // Tests that the mediator is returning the right number of items and sections
 // for the Tools Menu type.
 TEST_F(OverflowMenuMediatorTest, TestMenuItemsCount) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   mediator_.model = model_;
 
   NSUInteger number_of_action_items = 6;
@@ -521,7 +521,7 @@
 // Tests that the items returned by the mediator are correctly enabled on a
 // WebPage.
 TEST_F(OverflowMenuMediatorTest, TestItemsStatusOnWebPage) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
   mediator_.webStateList = browser_->GetWebStateList();
 
@@ -538,7 +538,7 @@
 // Tests that the items returned by the mediator are correctly enabled on the
 // NTP.
 TEST_F(OverflowMenuMediatorTest, TestItemsStatusOnNTP) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
   mediator_.webStateList = browser_->GetWebStateList();
 
@@ -558,7 +558,7 @@
 TEST_F(OverflowMenuMediatorTest, TestReadLaterDisabled) {
   const GURL kUrl("https://chromium.test");
   web_state_->SetCurrentURL(kUrl);
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
   mediator_.webStateList = browser_->GetWebStateList();
   mediator_.webContentAreaOverlayPresenter = OverlayPresenter::FromBrowser(
@@ -587,7 +587,7 @@
 
 // Tests that the "Text Zoom..." button is disabled on non-HTML pages.
 TEST_F(OverflowMenuMediatorTest, TestTextZoomDisabled) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
   mediator_.webStateList = browser_->GetWebStateList();
 
@@ -613,7 +613,7 @@
 // Tests that the "Managed by..." item is hidden when none of the policies is
 // set.
 TEST_F(OverflowMenuMediatorTest, TestEnterpriseInfoHidden) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
 
   mediator_.webStateList = browser_->GetWebStateList();
@@ -641,7 +641,7 @@
   EXPECT_TRUE(authentication_service->HasPrimaryIdentityManaged(
       signin::ConsentLevel::kSignin));
 
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   // Set the objects needed to detect the signed in managed account.
   mediator_.authenticationService =
       AuthenticationServiceFactory::GetForProfile(profile_.get());
@@ -672,7 +672,7 @@
   enterprise_policy_helper->GetPolicyProvider()->UpdateChromePolicy(map);
 
   CreateMediatorWithBrowserPolicyConnector(
-      /*is_incognito=*/NO, connector);
+      /*incognito=*/NO, connector);
 
   SetUpActiveWebState();
 
@@ -689,7 +689,7 @@
   // Sign in unsupervised user.
   SignInPrimaryAccountWithSupervisionStatus(/*is_supervised=*/false);
 
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
 
   mediator_.webStateList = browser_->GetWebStateList();
@@ -705,7 +705,7 @@
   // Sign in supervised user.
   SignInPrimaryAccountWithSupervisionStatus(/*is_supervised=*/true);
 
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
 
   mediator_.webStateList = browser_->GetWebStateList();
@@ -727,7 +727,7 @@
   web_state_->SetCurrentURL(nonBookmarkedURL);
   SetUpActiveWebState();
 
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpBookmarks();
   bookmark_model_->AddURL(bookmark_model_->mobile_node(), 0,
                           base::SysNSStringToUTF16(@"Test bookmark"),
@@ -760,7 +760,7 @@
   web_state_->SetCurrentURL(url);
   SetUpActiveWebState();
 
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   mediator_.webStateList = browser_->GetWebStateList();
 
   // Force model update.
@@ -777,7 +777,7 @@
 TEST_F(OverflowMenuMediatorTest, TestWhatsNewEnabled) {
   const GURL kUrl("https://chromium.test");
   web_state_->SetCurrentURL(kUrl);
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   SetUpActiveWebState();
   mediator_.webStateList = browser_->GetWebStateList();
   mediator_.webContentAreaOverlayPresenter = OverlayPresenter::FromBrowser(
@@ -793,7 +793,7 @@
 // that bug was never reproduced, but it tests part of the issue.
 TEST_F(OverflowMenuMediatorTest, TestOpenWhatsNewDoesntCrashWithNoTracker) {
   // Create Mediator and DO NOT set the Tracker on it.
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   // Force model update.
   mediator_.model = model_;
@@ -817,7 +817,7 @@
 // positioned at at most kNewDestinationsInsertionIndex when there is an
 // eligible identity error that can be resolved from the Settings menu.
 TEST_F(OverflowMenuMediatorTest, TestEligibleIdentityErrorWhenSyncOff) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   syncer::MockSyncService syncService;
   // Inject eligible identity error in Sync Service.
@@ -839,7 +839,7 @@
 // Tests that there is no error badge displayed on the Settings destination when
 // there is no eligible identity error. Sync is OFF.
 TEST_F(OverflowMenuMediatorTest, TestNoEligibleIdentityErrorWhenSyncOff) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   syncer::MockSyncService syncService;
   ON_CALL(syncService, GetUserActionableError())
@@ -859,7 +859,7 @@
 // an account error that will be indicated in the Settings menu. The account is
 // signed.
 TEST_F(OverflowMenuMediatorTest, TestSyncError) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   syncer::MockSyncService syncService;
   // Inject Sync error in Sync Service.
@@ -881,7 +881,7 @@
 // Tests that there is no error cue (red dot) displayed on the Settings
 // destination when there is no identity error.
 TEST_F(OverflowMenuMediatorTest, TestNoIdentityError) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   syncer::MockSyncService syncService;
   ON_CALL(syncService, GetUserActionableError())
@@ -902,7 +902,7 @@
 TEST_F(OverflowMenuMediatorTest, TestIdentityErrorWithWhatsNewPromo) {
   const GURL kUrl("https://chromium.test");
   web_state_->SetCurrentURL(kUrl);
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   // Show the new label badge for What's New.
   ON_CALL(tracker_, ShouldTriggerHelpUI(testing::Ref(
                         feature_engagement::kIPHWhatsNewUpdatedFeature)))
@@ -934,7 +934,7 @@
 // Tests that there is blue dot displayed on the Settings destination when there
 // is no identity error.
 TEST_F(OverflowMenuMediatorTest, TestSettingsBlueDotBadge) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   syncer::MockSyncService syncService;
   ON_CALL(syncService, GetUserActionableError())
@@ -955,7 +955,7 @@
 // history ranking.
 TEST_F(OverflowMenuMediatorTest,
        TestPromotedDestinationsWhenNoHistoryUsageRanking) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
   // Show the new label badge for What's New.
   ON_CALL(tracker_, ShouldTriggerHelpUI(testing::Ref(
                         feature_engagement::kIPHWhatsNewUpdatedFeature)))
@@ -986,7 +986,7 @@
 
 // Tests that the actions have the correct longpress items set.
 TEST_F(OverflowMenuMediatorTest, ActionLongpressItems) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   mediator_.model = model_;
 
@@ -1008,7 +1008,7 @@
 
 // Tests that the destinations have the correct longpress items set.
 TEST_F(OverflowMenuMediatorTest, DestinationLongpressItems) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   mediator_.model = model_;
 
@@ -1030,7 +1030,7 @@
 // Tests that when a destination becomes hidden during customization, the
 // corresponding action gains a subtitle and a highlight.
 TEST_F(OverflowMenuMediatorTest, DestinationHideShowsActionSubtitle) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   mediator_.model = model_;
 
@@ -1068,7 +1068,7 @@
 // Tests that when the the right metric is recorder when the Password Manager
 // item is tapped.
 TEST_F(OverflowMenuMediatorTest, OpenPasswordsMetricLogged) {
-  CreateMediator(/*is_incognito=*/NO);
+  CreateMediator(/*incognito=*/NO);
 
   mediator_.model = model_;
 
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/popup_menu_coordinator.mm b/ios/chrome/browser/popup_menu/ui_bundled/popup_menu_coordinator.mm
index 6b6ecfc..c9368f6 100644
--- a/ios/chrome/browser/popup_menu/ui_bundled/popup_menu_coordinator.mm
+++ b/ios/chrome/browser/popup_menu/ui_bundled/popup_menu_coordinator.mm
@@ -264,10 +264,10 @@
     UIContentSizeCategory contentSizeCategory =
         self.baseViewController.traitCollection.preferredContentSizeCategory;
 
-    BOOL isIncognito = profile->IsOffTheRecord();
-    mediator.isIncognito = isIncognito;
+    BOOL incognito = profile->IsOffTheRecord();
+    mediator.incognito = incognito;
     _overflowMenuOrderer =
-        [[OverflowMenuOrderer alloc] initWithIsIncognito:isIncognito];
+        [[OverflowMenuOrderer alloc] initWithIsIncognito:incognito];
     _overflowMenuOrderer.visibleDestinationsCount = [OverflowMenuUIConfiguration
         numDestinationsVisibleWithoutHorizontalScrollingForScreenWidth:
             screenWidth
diff --git a/ios/chrome/browser/prerender/model/preload_controller.mm b/ios/chrome/browser/prerender/model/preload_controller.mm
index 259da0f0..8e96e851 100644
--- a/ios/chrome/browser/prerender/model/preload_controller.mm
+++ b/ios/chrome/browser/prerender/model/preload_controller.mm
@@ -127,7 +127,7 @@
 
   // web::JavaScriptDialogPresenter:
   void RunJavaScriptAlertDialog(web::WebState* web_state,
-                                const GURL& origin_url,
+                                const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback) override {
     std::move(callback).Run();
@@ -136,7 +136,7 @@
 
   void RunJavaScriptConfirmDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback) override {
     std::move(callback).Run(/*success=*/false);
@@ -145,7 +145,7 @@
 
   void RunJavaScriptPromptDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback) override {
diff --git a/ios/chrome/browser/reader_mode/coordinator/BUILD.gn b/ios/chrome/browser/reader_mode/coordinator/BUILD.gn
index fc04fd34..b60d74f5c 100644
--- a/ios/chrome/browser/reader_mode/coordinator/BUILD.gn
+++ b/ios/chrome/browser/reader_mode/coordinator/BUILD.gn
@@ -10,13 +10,32 @@
     "reader_mode_mediator.mm",
   ]
   deps = [
+    ":options",
     "//ios/chrome/browser/reader_mode/model",
     "//ios/chrome/browser/reader_mode/ui",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/web_state_list",
+    "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/tabs/model",
     "//ios/web/public",
   ]
 }
+
+source_set("options") {
+  visibility = [ ":coordinator" ]
+  sources = [
+    "reader_mode_options_coordinator.h",
+    "reader_mode_options_coordinator.mm",
+    "reader_mode_options_mediator.h",
+    "reader_mode_options_mediator.mm",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/reader_mode/ui:options",
+    "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
+    "//ios/chrome/browser/shared/model/browser",
+    "//ios/chrome/browser/shared/public/commands",
+  ]
+}
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm
index a042b6f4..9c6a5fa 100644
--- a/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm
+++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.mm
@@ -5,18 +5,24 @@
 #import "ios/chrome/browser/reader_mode/coordinator/reader_mode_coordinator.h"
 
 #import "ios/chrome/browser/reader_mode/coordinator/reader_mode_mediator.h"
+#import "ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.h"
 #import "ios/chrome/browser/reader_mode/ui/reader_mode_view_controller.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
+#import "ios/chrome/browser/shared/public/commands/reader_mode_options_commands.h"
 
-@interface ReaderModeCoordinator ()
+@interface ReaderModeCoordinator () <ReaderModeOptionsCommands>
 @end
 
 @implementation ReaderModeCoordinator {
   ReaderModeViewController* _viewController;
   ReaderModeMediator* _mediator;
+  ReaderModeOptionsCoordinator* _optionsCoordinator;
 }
 
+#pragma mark - ChromeCoordinator
+
 - (void)start {
   _viewController = [[ReaderModeViewController alloc] init];
   _mediator = [[ReaderModeMediator alloc]
@@ -24,14 +30,41 @@
   _mediator.consumer = _viewController;
   [self.baseViewController addChildViewController:_viewController];
   [_viewController didMoveToParentViewController:self.baseViewController];
+  // TODO(crbug.com/409941529): Only show options there if this is the first
+  // time Reader mode is triggered.
+  [self showReaderModeOptions];
+  // Start handling Reader mode options commands.
+  [self.browser->GetCommandDispatcher()
+      startDispatchingToTarget:self
+                   forProtocol:@protocol(ReaderModeOptionsCommands)];
 }
 
 - (void)stop {
+  // Stop handling Reader mode options commands.
+  [self.browser->GetCommandDispatcher() stopDispatchingToTarget:self];
+  // Ensure the options UI is dismissed.
+  [self hideReaderModeOptions];
+  // Disconnect mediator from model layer.
   [_mediator disconnect];
   _mediator = nil;
+  // Dismiss Reader mode UI.
   [_viewController willMoveToParentViewController:nil];
   [_viewController removeFromParentViewController];
   _viewController = nil;
 }
 
+#pragma mark - ReaderModeOptionsCommands
+
+- (void)showReaderModeOptions {
+  _optionsCoordinator = [[ReaderModeOptionsCoordinator alloc]
+      initWithBaseViewController:_viewController
+                         browser:self.browser];
+  [_optionsCoordinator start];
+}
+
+- (void)hideReaderModeOptions {
+  [_optionsCoordinator stop];
+  _optionsCoordinator = nil;
+}
+
 @end
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.h b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.h
new file mode 100644
index 0000000..32b3acd0
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.h
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_COORDINATOR_H_
+
+#import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h"
+
+// Coordinator for Reader mode options UI.
+@interface ReaderModeOptionsCoordinator : ChromeCoordinator
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_COORDINATOR_H_
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.mm b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.mm
new file mode 100644
index 0000000..d56d83f
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.mm
@@ -0,0 +1,54 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/reader_mode/coordinator/reader_mode_options_coordinator.h"
+
+#import "ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h"
+#import "ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h"
+#import "ios/chrome/browser/shared/model/browser/browser.h"
+#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
+#import "ios/chrome/browser/shared/public/commands/reader_mode_options_commands.h"
+
+@interface ReaderModeOptionsCoordinator () <
+    UIAdaptivePresentationControllerDelegate>
+
+@end
+
+@implementation ReaderModeOptionsCoordinator {
+  ReaderModeOptionsMediator* _mediator;
+  ReaderModeOptionsViewController* _viewController;
+}
+
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  _viewController = [[ReaderModeOptionsViewController alloc] init];
+  _viewController.presentationController.delegate = self;
+  _mediator = [[ReaderModeOptionsMediator alloc] init];
+  [self.baseViewController presentViewController:_viewController
+                                        animated:YES
+                                      completion:nil];
+}
+
+- (void)stop {
+  [_mediator disconnect];
+  _mediator = nil;
+  [_viewController.presentingViewController dismissViewControllerAnimated:YES
+                                                               completion:nil];
+  _viewController = nil;
+}
+
+#pragma mark - UIAdaptivePresentationControllerDelegate
+
+- (void)presentationControllerDidDismiss:
+    (UIPresentationController*)presentationController {
+  // If the navigation controller is not dismissed programmatically i.e. not
+  // dismissed using `dismissViewControllerAnimated:completion:`, then call
+  // `-hideReaderModeOptions`.
+  id<ReaderModeOptionsCommands> readerModeOptionsHandler = HandlerForProtocol(
+      self.browser->GetCommandDispatcher(), ReaderModeOptionsCommands);
+  [readerModeOptionsHandler hideReaderModeOptions];
+}
+
+@end
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h
new file mode 100644
index 0000000..fd5b2eb
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h
@@ -0,0 +1,18 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_MEDIATOR_H_
+
+#import <Foundation/Foundation.h>
+
+// Mediator for the reader mode options.
+@interface ReaderModeOptionsMediator : NSObject
+
+// Disconnects from the model layer.
+- (void)disconnect;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_READER_MODE_COORDINATOR_READER_MODE_OPTIONS_MEDIATOR_H_
diff --git a/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.mm b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.mm
new file mode 100644
index 0000000..d1bbee0
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.mm
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h"
+
+@implementation ReaderModeOptionsMediator
+
+#pragma mark - Public
+
+- (void)disconnect {
+  // TODO(crbug.com/409941529): Disconnect the mediator from the model layer.
+}
+
+@end
diff --git a/ios/chrome/browser/reader_mode/ui/BUILD.gn b/ios/chrome/browser/reader_mode/ui/BUILD.gn
index eab01f4..7159b89 100644
--- a/ios/chrome/browser/reader_mode/ui/BUILD.gn
+++ b/ios/chrome/browser/reader_mode/ui/BUILD.gn
@@ -13,3 +13,15 @@
     "//ios/chrome/common/ui/util",
   ]
 }
+
+source_set("options") {
+  sources = [
+    "reader_mode_options_view_controller.h",
+    "reader_mode_options_view_controller.mm",
+  ]
+  deps = [
+    "//ios/chrome/browser/shared/ui/util",
+    "//ios/chrome/common/ui/colors",
+    "//ios/chrome/common/ui/util",
+  ]
+}
diff --git a/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h b/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h
new file mode 100644
index 0000000..311d7cc2
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READER_MODE_UI_READER_MODE_OPTIONS_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_READER_MODE_UI_READER_MODE_OPTIONS_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+// View controller for the reader mode options.
+@interface ReaderModeOptionsViewController : UIViewController
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_READER_MODE_UI_READER_MODE_OPTIONS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.mm b/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.mm
new file mode 100644
index 0000000..0640b30
--- /dev/null
+++ b/ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.mm
@@ -0,0 +1,30 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h"
+
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+
+@implementation ReaderModeOptionsViewController
+
+#pragma mark - Initialization
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    self.sheetPresentationController.detents =
+        @[ [UISheetPresentationControllerDetent mediumDetent] ];
+    self.sheetPresentationController.largestUndimmedDetentIdentifier =
+        [UISheetPresentationControllerDetent mediumDetent].identifier;
+  }
+  return self;
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  self.view.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor];
+}
+
+@end
diff --git a/ios/chrome/browser/sessions/model/legacy_session_restoration_service_unittest.mm b/ios/chrome/browser/sessions/model/legacy_session_restoration_service_unittest.mm
index f1a5816..50964dd 100644
--- a/ios/chrome/browser/sessions/model/legacy_session_restoration_service_unittest.mm
+++ b/ios/chrome/browser/sessions/model/legacy_session_restoration_service_unittest.mm
@@ -22,7 +22,9 @@
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
 #import "base/time/time.h"
+#import "components/data_sharing/test_support/mock_data_sharing_service.h"
 #import "components/saved_tab_groups/test_support/fake_tab_group_sync_service.h"
+#import "ios/chrome/browser/data_sharing/model/data_sharing_service_factory.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/sessions/model/session_constants.h"
 #import "ios/chrome/browser/sessions/model/session_internal_util.h"
@@ -383,6 +385,12 @@
               // affects the list of created files.
               return std::make_unique<tab_groups::FakeTabGroupSyncService>();
             }));
+    builder.AddTestingFactory(
+        data_sharing::DataSharingServiceFactory::GetInstance(),
+        base::BindOnce(
+            [](web::BrowserState* context) -> std::unique_ptr<KeyedService> {
+              return std::make_unique<data_sharing::MockDataSharingService>();
+            }));
     profile_ = std::move(builder).Build();
     file_tracker_.Start(profile_->GetStatePath());
 
diff --git a/ios/chrome/browser/sessions/model/session_restoration_service_impl_unittest.mm b/ios/chrome/browser/sessions/model/session_restoration_service_impl_unittest.mm
index 6084f05..099affc 100644
--- a/ios/chrome/browser/sessions/model/session_restoration_service_impl_unittest.mm
+++ b/ios/chrome/browser/sessions/model/session_restoration_service_impl_unittest.mm
@@ -20,7 +20,9 @@
 #import "base/scoped_multi_source_observation.h"
 #import "base/test/metrics/histogram_tester.h"
 #import "base/time/time.h"
+#import "components/data_sharing/test_support/mock_data_sharing_service.h"
 #import "components/saved_tab_groups/test_support/fake_tab_group_sync_service.h"
+#import "ios/chrome/browser/data_sharing/model/data_sharing_service_factory.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/sessions/model/proto/storage.pb.h"
 #import "ios/chrome/browser/sessions/model/session_constants.h"
@@ -375,6 +377,12 @@
               // affects the list of created files.
               return std::make_unique<tab_groups::FakeTabGroupSyncService>();
             }));
+    builder.AddTestingFactory(
+        data_sharing::DataSharingServiceFactory::GetInstance(),
+        base::BindOnce(
+            [](web::BrowserState* context) -> std::unique_ptr<KeyedService> {
+              return std::make_unique<data_sharing::MockDataSharingService>();
+            }));
     profile_ = std::move(builder).Build();
     file_tracker_.Start(profile_->GetStatePath());
 
diff --git a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_coordinator.mm
index f4eb1cd..8346c92f 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_coordinator.mm
@@ -7,9 +7,7 @@
 #import <UIKit/UIKit.h>
 
 #import "base/check.h"
-#import "base/debug/dump_without_crashing.h"
 #import "base/metrics/histogram_functions.h"
-#import "base/not_fatal_until.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/settings/ui_bundled/password/password_manager_ui_features.h"
@@ -287,17 +285,6 @@
   UIViewController* presentedViewController =
       topViewController.presentedViewController;
 
-  // Add some crash keys with usefull information for debugging failures when
-  // pushing the reauth controller.
-  SCOPED_CRASH_KEY_STRING64(
-      "ReauthCoordinator", "topVC",
-      base::SysNSStringToUTF8(NSStringFromClass(topViewController.class)));
-  SCOPED_CRASH_KEY_STRING64("ReauthCoordinator", "presentedVC",
-                            presentedViewController
-                                ? base::SysNSStringToUTF8(NSStringFromClass(
-                                      presentedViewController.class))
-                                : "none");
-
   // Do not dismiss the Search Controller, otherwise pushViewController does not
   // add the new view controller to the top of the navigation stack.
   if (![presentedViewController isKindOfClass:[UISearchController class]] &&
@@ -318,11 +305,6 @@
 
   if (![_baseNavigationController.topViewController
           isEqual:_reauthViewController]) {
-    SCOPED_CRASH_KEY_NUMBER("ReauthCoordinator", "sceneActivation",
-                            self.browser->GetSceneState().activationLevel);
-    SCOPED_CRASH_KEY_BOOL("ReauthCoordinator", "hasWindow",
-                          _baseNavigationController.view.window != nil);
-    base::debug::DumpWithoutCrashing();
     _reauthViewController.delegate = nil;
     _reauthViewController = nil;
     return NO;
@@ -342,19 +324,6 @@
 
   if (_baseNavigationController.topViewController == _reauthViewController) {
     [_baseNavigationController popViewControllerAnimated:NO];
-  } else {
-    SCOPED_CRASH_KEY_STRING64(
-        "ReauthCoordinator", "topVC",
-        base::SysNSStringToUTF8(NSStringFromClass(
-            _baseNavigationController.topViewController.class)));
-    SCOPED_CRASH_KEY_BOOL("ReauthCoordinator", "reauthIsInStack",
-                          [_baseNavigationController.viewControllers
-                              containsObject:_reauthViewController]);
-    SCOPED_CRASH_KEY_NUMBER("ReauthCoordinator", "sceneActivation",
-                            self.browser->GetSceneState().activationLevel);
-    SCOPED_CRASH_KEY_BOOL("ReauthCoordinator", "hasWindow",
-                          _baseNavigationController.view.window != nil);
-    base::debug::DumpWithoutCrashing();
   }
 
   _reauthViewController.delegate = nil;
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index 94459b90..0ed9c94 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -2241,8 +2241,7 @@
                                           contextStyle:SigninContextStyle::
                                                            kDefault
                                             anchorView:nil
-                                           accessPoint:AccountMenuAccessPoint::
-                                                           kWeb];
+                                           accessPoint:accessPoint];
   self.signinCoordinator = accountMenuCoordinator;
   // TODO(crbug.com/336719423): Record signin metrics based on the
   // selected action from the account switcher.
diff --git a/ios/chrome/browser/shared/model/prefs/BUILD.gn b/ios/chrome/browser/shared/model/prefs/BUILD.gn
index fa41d04a8..6ecdb32 100644
--- a/ios/chrome/browser/shared/model/prefs/BUILD.gn
+++ b/ios/chrome/browser/shared/model/prefs/BUILD.gn
@@ -32,6 +32,7 @@
     "//components/breadcrumbs/core:status",
     "//components/browser_sync",
     "//components/browsing_data/core",
+    "//components/collaboration/public:prefs",
     "//components/commerce/core:pref_names",
     "//components/component_updater",
     "//components/component_updater/installer_policies",
diff --git a/ios/chrome/browser/shared/model/prefs/DEPS b/ios/chrome/browser/shared/model/prefs/DEPS
index f19708c..9e3f876 100644
--- a/ios/chrome/browser/shared/model/prefs/DEPS
+++ b/ios/chrome/browser/shared/model/prefs/DEPS
@@ -18,6 +18,7 @@
   "+ios/chrome/browser/drive/model/drive_policy.h",
   "+ios/chrome/browser/web/model/annotations/annotations_util.h",
   "+ios/chrome/browser/parcel_tracking",
+  "+components/collaboration/public/pref_names.h",
   "+components/webui/chrome_urls/pref_names.h",
   "+components/saved_tab_groups/public/pref_names.h",
   "+components/lens/lens_overlay_permission_utils.h",
diff --git a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
index f8dd4888..d919856ff 100644
--- a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
@@ -16,6 +16,7 @@
 #import "components/breadcrumbs/core/breadcrumbs_status.h"
 #import "components/browser_sync/sync_to_signin_migration.h"
 #import "components/browsing_data/core/pref_names.h"
+#import "components/collaboration/public/pref_names.h"
 #import "components/commerce/core/pref_names.h"
 #import "components/component_updater/component_updater_service.h"
 #import "components/component_updater/installer_policies/autofill_states_component_installer.h"
@@ -660,6 +661,7 @@
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
   autofill::prefs::RegisterProfilePrefs(registry);
+  collaboration::prefs::RegisterProfilePrefs(registry);
   commerce::RegisterPrefs(registry);
   dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry);
   enterprise::RegisterIdentifiersProfilePrefs(registry);
diff --git a/ios/chrome/browser/shared/public/commands/BUILD.gn b/ios/chrome/browser/shared/public/commands/BUILD.gn
index 41cc29d..661a4e5 100644
--- a/ios/chrome/browser/shared/public/commands/BUILD.gn
+++ b/ios/chrome/browser/shared/public/commands/BUILD.gn
@@ -59,6 +59,7 @@
     "qr_scanner_commands.h",
     "quick_delete_commands.h",
     "reader_mode_commands.h",
+    "reader_mode_options_commands.h",
     "reading_list_add_command.h",
     "reading_list_add_command.mm",
     "recent_activity_commands.h",
diff --git a/ios/chrome/browser/shared/public/commands/reader_mode_options_commands.h b/ios/chrome/browser/shared/public/commands/reader_mode_options_commands.h
new file mode 100644
index 0000000..2b13101
--- /dev/null
+++ b/ios/chrome/browser/shared/public/commands/reader_mode_options_commands.h
@@ -0,0 +1,19 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_READER_MODE_OPTIONS_COMMANDS_H_
+#define IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_READER_MODE_OPTIONS_COMMANDS_H_
+
+// Commands protocol to show/hide the Reader mode options UI.
+@protocol ReaderModeOptionsCommands <NSObject>
+
+// Shows the Reader mode options UI.
+- (void)showReaderModeOptions;
+
+// Hides the Reader mode options UI.
+- (void)hideReaderModeOptions;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_READER_MODE_OPTIONS_COMMANDS_H_
diff --git a/ios/chrome/browser/sync/model/prefs/BUILD.gn b/ios/chrome/browser/sync/model/prefs/BUILD.gn
index c6978b3b..ca3cafe 100644
--- a/ios/chrome/browser/sync/model/prefs/BUILD.gn
+++ b/ios/chrome/browser/sync/model/prefs/BUILD.gn
@@ -46,6 +46,7 @@
     ":prefs",
     ":test_data",
     "//base/test:test_support",
+    "//components/sync/base:features",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.cc b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.cc
index 12e84d5..cd938bd 100644
--- a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.cc
+++ b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.cc
@@ -116,4 +116,9 @@
       std::inserter(syncable_prefs, syncable_prefs.end()));
   return syncable_prefs;
 }
+
+bool IOSChromeSyncablePrefsDatabase::IsPreferenceAlwaysSyncing(
+    std::string_view pref_name) const {
+  return common_syncable_prefs_database_.IsPreferenceAlwaysSyncing(pref_name);
+}
 }  // namespace browser_sync
diff --git a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.h b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.h
index b75dfc0..84363e46 100644
--- a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.h
+++ b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database.h
@@ -24,6 +24,8 @@
   std::map<std::string_view, sync_preferences::SyncablePrefMetadata>
   GetAllSyncablePrefsForTest() const;
 
+  bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const override;
+
  private:
   // This defines the list of preferences that are syncable across all
   // platforms.
diff --git a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database_unittest.cc b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database_unittest.cc
index f7635057..1827a93 100644
--- a/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database_unittest.cc
+++ b/ios/chrome/browser/sync/model/prefs/ios_chrome_syncable_prefs_database_unittest.cc
@@ -7,6 +7,8 @@
 #include <string_view>
 
 #include "base/test/metrics/histogram_enum_reader.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/sync/base/features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -30,4 +32,23 @@
   }
 }
 
+TEST(IOSChromeSyncablePrefsDatabaseTest, IsPreferenceAlwaysSyncing) {
+  base::test::ScopedFeatureList scoped_feature_list(
+      syncer::kSyncSupportAlwaysSyncingPriorityPreferences);
+  browser_sync::IOSChromeSyncablePrefsDatabase db;
+  EXPECT_TRUE(db.IsPreferenceAlwaysSyncing(
+      sync_preferences::kSyncableAlwaysSyncingPriorityPrefForTesting));
+  EXPECT_FALSE(db.IsPreferenceAlwaysSyncing(
+      sync_preferences::kSyncablePriorityPrefForTesting));
+
+  // Currently, only priority preferences are allowed in the allowlist.
+  const std::map<std::string_view, sync_preferences::SyncablePrefMetadata>
+      syncable_prefs = db.GetAllSyncablePrefsForTest();
+  for (const auto& [pref_name, metadata] : syncable_prefs) {
+    if (db.IsPreferenceAlwaysSyncing(pref_name)) {
+      EXPECT_EQ(metadata.data_type(), syncer::PRIORITY_PREFERENCES);
+    }
+  }
+}
+
 }  // namespace
diff --git a/ios/chrome/browser/web/model/web_state_delegate_browser_agent_unittest.mm b/ios/chrome/browser/web/model/web_state_delegate_browser_agent_unittest.mm
index 213aced..2ae9e60 100644
--- a/ios/chrome/browser/web/model/web_state_delegate_browser_agent_unittest.mm
+++ b/ios/chrome/browser/web/model/web_state_delegate_browser_agent_unittest.mm
@@ -180,8 +180,8 @@
 
   // Present a JavaScript alert.
   GURL kOriginUrl("http://chromium.test");
-  presenter->RunJavaScriptAlertDialog(web_state, kOriginUrl, @"",
-                                      base::DoNothing());
+  presenter->RunJavaScriptAlertDialog(
+      web_state, url::Origin::Create(kOriginUrl), @"", base::DoNothing());
 
   // Verify that JavaScript alert OverlayRequest has been added to the
   // WebState's queue.
diff --git a/ios/chrome/test/data/policy/policy_test_bundle_data.filelist b/ios/chrome/test/data/policy/policy_test_bundle_data.filelist
index 964ad8bd..f7d7d302 100644
--- a/ios/chrome/test/data/policy/policy_test_bundle_data.filelist
+++ b/ios/chrome/test/data/policy/policy_test_bundle_data.filelist
@@ -78,6 +78,7 @@
 //ios/chrome/test/data/policy/pref_mapping/SyncDisabled.json
 //ios/chrome/test/data/policy/pref_mapping/SyncTypesListDisabled.json
 //ios/chrome/test/data/policy/pref_mapping/TabCompareSettings.json
+//ios/chrome/test/data/policy/pref_mapping/TabGroupSharingSettings.json
 //ios/chrome/test/data/policy/pref_mapping/TranslateEnabled.json
 //ios/chrome/test/data/policy/pref_mapping/URLAllowlist.json
 //ios/chrome/test/data/policy/pref_mapping/URLBlocklist.json
diff --git a/ios/chrome/test/data/policy/pref_mapping/TabGroupSharingSettings.json b/ios/chrome/test/data/policy/pref_mapping/TabGroupSharingSettings.json
new file mode 100644
index 0000000..4b79f91
--- /dev/null
+++ b/ios/chrome/test/data/policy/pref_mapping/TabGroupSharingSettings.json
@@ -0,0 +1,15 @@
+[
+  {
+    "os": [
+      "ios"
+    ],
+    "simple_policy_pref_mapping_test": {
+      "pref_name": "shared_tab_groups.managed_account_setting",
+      "pref_location": "user_profile",
+      "default_value": 0,
+      "values_to_test": [
+        0, 1
+      ]
+    }
+  }
+]
diff --git a/ios/testing/data/http_server_files/full_address_form.html b/ios/testing/data/http_server_files/full_address_form.html
index 60b40a4..bfedfb1 100644
--- a/ios/testing/data/http_server_files/full_address_form.html
+++ b/ios/testing/data/http_server_files/full_address_form.html
@@ -9,8 +9,10 @@
 
 The page can be adapted to different scenarios based on the following URL query
 parameters:
- * preventDefault: Will use the form submission variant that prevents default
-     for form submission. You only need to put the key, no value needed.
+ * preventDefault: When set, will use the form submission variant that prevents
+     default for form submission. You only need to put the key, no value needed.
+ * redirectWhenDefaultPrevented: When set, will redirect to another page when
+     the form submission is preventDefault()ed.
 -->
 
 <!DOCTYPE html>
@@ -56,9 +58,11 @@
         // Prevent default for other listeners so the the Autofill listener will
         // read the event with the defaultPrevented bit set to true.
         e.preventDefault();
-        // Emulate a post-submit navigation that happens slightly after
-        // propagating the "submit" event.
-        setTimeout(() => window.location = '/destination.html', 10);
+        if (queryParams.hasOwnProperty('redirectWhenDefaultPrevented')) {
+          // Emulate a post-submit navigation that happens slightly after
+          // propagating the "submit" event, when enabled.
+          setTimeout(() => window.location = '/destination.html', 10);
+        }
       });
     }
 
@@ -66,11 +70,11 @@
     function FillForm() {
       const form = document.forms[0];
       form['fullname'].value = 'Test User';
-      form['address-line1'].value  = '123 Test St';
-      form['city'].value  = 'TestCity';
-      form['state'].value  = 'CA';
+      form['address-line1'].value = '123 Test St';
+      form['city'].value = 'TestCity';
+      form['state'].value = 'CA';
       form['postal-code'].value = '12345';
-      form['country'].value  = 'TestCountry';
+      form['country'].value = 'TestCountry';
     }
 
   </script>
diff --git a/ios/web/public/test/fakes/fake_java_script_dialog_presenter.h b/ios/web/public/test/fakes/fake_java_script_dialog_presenter.h
index ee437aac..7ba46b2 100644
--- a/ios/web/public/test/fakes/fake_java_script_dialog_presenter.h
+++ b/ios/web/public/test/fakes/fake_java_script_dialog_presenter.h
@@ -18,7 +18,7 @@
   FakeJavaScriptAlertDialog();
   ~FakeJavaScriptAlertDialog();
   raw_ptr<WebState> web_state = nullptr;
-  GURL origin_url;
+  url::Origin origin;
   NSString* message_text;
   base::OnceClosure callback;
 };
@@ -27,7 +27,7 @@
   FakeJavaScriptConfirmDialog();
   ~FakeJavaScriptConfirmDialog();
   raw_ptr<WebState> web_state = nullptr;
-  GURL origin_url;
+  url::Origin origin;
   NSString* message_text;
   base::OnceCallback<void(bool success)> callback;
 };
@@ -36,7 +36,7 @@
   FakeJavaScriptPromptDialog();
   ~FakeJavaScriptPromptDialog();
   raw_ptr<WebState> web_state = nullptr;
-  GURL origin_url;
+  url::Origin origin;
   NSString* message_text;
   NSString* default_prompt_text;
   base::OnceCallback<void(NSString* user_input)> callback;
@@ -52,17 +52,17 @@
 
   // JavaScriptDialogPresenter overrides:
   void RunJavaScriptAlertDialog(WebState* web_state,
-                                const GURL& origin_url,
+                                const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback) override;
   void RunJavaScriptConfirmDialog(
       WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback) override;
   void RunJavaScriptPromptDialog(
       WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback) override;
diff --git a/ios/web/public/test/fakes/fake_java_script_dialog_presenter.mm b/ios/web/public/test/fakes/fake_java_script_dialog_presenter.mm
index 38a34e5a..2f266a0 100644
--- a/ios/web/public/test/fakes/fake_java_script_dialog_presenter.mm
+++ b/ios/web/public/test/fakes/fake_java_script_dialog_presenter.mm
@@ -30,12 +30,12 @@
 
 void FakeJavaScriptDialogPresenter::RunJavaScriptAlertDialog(
     WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceClosure callback) {
   auto dialog = std::make_unique<FakeJavaScriptAlertDialog>();
   dialog->web_state = web_state;
-  dialog->origin_url = origin_url;
+  dialog->origin = origin;
   dialog->message_text = [message_text copy];
   dialog->callback = std::move(callback);
 
@@ -48,12 +48,12 @@
 
 void FakeJavaScriptDialogPresenter::RunJavaScriptConfirmDialog(
     WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceCallback<void(bool success)> callback) {
   auto dialog = std::make_unique<FakeJavaScriptConfirmDialog>();
   dialog->web_state = web_state;
-  dialog->origin_url = origin_url;
+  dialog->origin = origin;
   dialog->message_text = [message_text copy];
   dialog->callback = std::move(callback);
 
@@ -65,13 +65,13 @@
 }
 void FakeJavaScriptDialogPresenter::RunJavaScriptPromptDialog(
     WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     NSString* default_prompt_text,
     base::OnceCallback<void(NSString* user_input)> callback) {
   auto dialog = std::make_unique<FakeJavaScriptPromptDialog>();
   dialog->web_state = web_state;
-  dialog->origin_url = origin_url;
+  dialog->origin = origin;
   dialog->message_text = [message_text copy];
   dialog->default_prompt_text = [default_prompt_text copy];
   dialog->callback = std::move(callback);
diff --git a/ios/web/public/ui/java_script_dialog_presenter.h b/ios/web/public/ui/java_script_dialog_presenter.h
index 331adcf..bf8023d 100644
--- a/ios/web/public/ui/java_script_dialog_presenter.h
+++ b/ios/web/public/ui/java_script_dialog_presenter.h
@@ -5,9 +5,8 @@
 #ifndef IOS_WEB_PUBLIC_UI_JAVA_SCRIPT_DIALOG_PRESENTER_H_
 #define IOS_WEB_PUBLIC_UI_JAVA_SCRIPT_DIALOG_PRESENTER_H_
 
-#import "base/functional/callback.h"
 #import "base/functional/callback_forward.h"
-#import "url/gurl.h"
+#import "url/origin.h"
 
 @class NSString;
 
@@ -21,7 +20,7 @@
 
   // Notifies the delegate that a JavaScript alert needs to be presented.
   virtual void RunJavaScriptAlertDialog(WebState* web_state,
-                                        const GURL& origin_url,
+                                        const url::Origin& origin,
                                         NSString* message_text,
                                         base::OnceClosure callback) = 0;
 
@@ -29,14 +28,14 @@
   // presented.
   virtual void RunJavaScriptConfirmDialog(
       WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback) = 0;
 
   // Notifies the delegate that a JavaScript prompt needs to be presented.
   virtual void RunJavaScriptPromptDialog(
       WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback) = 0;
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 3188a63..3fa2329 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -421,7 +421,7 @@
            !requested_confirm_dialogs().empty() ||
            !requested_prompt_dialogs().empty();
   }
-  const GURL& page_url() { return page_url_; }
+  const url::Origin page_origin() { return url::Origin::Create(page_url_); }
 
  private:
   FakeWebStateDelegate web_state_delegate_;
@@ -439,7 +439,7 @@
   ASSERT_TRUE(requested_prompt_dialogs().empty());
   auto& dialog = requested_alert_dialogs().front();
   EXPECT_EQ(web_state(), dialog->web_state);
-  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(page_origin(), dialog->origin);
   EXPECT_NSEQ(@"test", dialog->message_text);
 }
 
@@ -456,7 +456,7 @@
   ASSERT_TRUE(requested_prompt_dialogs().empty());
   auto& dialog = requested_confirm_dialogs().front();
   EXPECT_EQ(web_state(), dialog->web_state);
-  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(page_origin(), dialog->origin);
   EXPECT_NSEQ(@"test", dialog->message_text);
 }
 
@@ -471,7 +471,7 @@
   ASSERT_TRUE(requested_prompt_dialogs().empty());
   auto& dialog = requested_confirm_dialogs().front();
   EXPECT_EQ(web_state(), dialog->web_state);
-  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(page_origin(), dialog->origin);
   EXPECT_NSEQ(@"test", dialog->message_text);
 }
 
@@ -488,7 +488,7 @@
   ASSERT_EQ(1U, requested_prompt_dialogs().size());
   auto& dialog = requested_prompt_dialogs().front();
   EXPECT_EQ(web_state(), dialog->web_state);
-  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(page_origin(), dialog->origin);
   EXPECT_NSEQ(@"Yes?", dialog->message_text);
   EXPECT_NSEQ(@"No", dialog->default_prompt_text);
 }
@@ -507,7 +507,7 @@
   ASSERT_EQ(1U, requested_prompt_dialogs().size());
   auto& dialog = requested_prompt_dialogs().front();
   EXPECT_EQ(web_state(), dialog->web_state);
-  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(page_origin(), dialog->origin);
   EXPECT_NSEQ(@"", dialog->message_text);
   EXPECT_NSEQ(@"", dialog->default_prompt_text);
 }
@@ -520,7 +520,7 @@
   // Change visible URL.
   AddPendingItem(GURL("https://pending.test/"), ui::PAGE_TRANSITION_TYPED);
   web_controller().webStateImpl->SetIsLoading(true);
-  ASSERT_NE(page_url().DeprecatedGetOriginAsURL(),
+  ASSERT_NE(page_origin().GetURL(),
             web_state()->GetVisibleURL().DeprecatedGetOriginAsURL());
 
   ExecuteJavaScript(@"alert('test')");
diff --git a/ios/web/web_state/ui/crw_wk_ui_handler.mm b/ios/web/web_state/ui/crw_wk_ui_handler.mm
index 3f769d9..d2f7a5a 100644
--- a/ios/web/web_state/ui/crw_wk_ui_handler.mm
+++ b/ios/web/web_state/ui/crw_wk_ui_handler.mm
@@ -224,8 +224,9 @@
     return;
   }
 
+  url::Origin origin = web::OriginWithWKSecurityOrigin(frame.securityOrigin);
   self.webStateImpl->RunJavaScriptAlertDialog(
-      requestURL, message, base::BindOnce(completionHandler));
+      origin, message, base::BindOnce(completionHandler));
 }
 
 - (void)webView:(WKWebView*)webView
@@ -242,8 +243,9 @@
     return;
   }
 
+  url::Origin origin = web::OriginWithWKSecurityOrigin(frame.securityOrigin);
   self.webStateImpl->RunJavaScriptConfirmDialog(
-      requestURL, message, base::BindOnce(completionHandler));
+      origin, message, base::BindOnce(completionHandler));
 }
 
 - (void)webView:(WKWebView*)webView
@@ -252,8 +254,8 @@
                          initiatedByFrame:(WKFrameInfo*)frame
                         completionHandler:
                             (void (^)(NSString* result))completionHandler {
-  GURL origin(web::GURLOriginWithWKSecurityOrigin(frame.securityOrigin));
-  if (web::GetWebClient()->IsAppSpecificURL(origin)) {
+  GURL origin_url(web::GURLOriginWithWKSecurityOrigin(frame.securityOrigin));
+  if (web::GetWebClient()->IsAppSpecificURL(origin_url)) {
     std::string mojoResponse =
         self.mojoFacade->HandleMojoMessage(base::SysNSStringToUTF8(prompt));
     completionHandler(base::SysUTF8ToNSString(mojoResponse));
@@ -269,8 +271,9 @@
     return;
   }
 
+  url::Origin origin = web::OriginWithWKSecurityOrigin(frame.securityOrigin);
   self.webStateImpl->RunJavaScriptPromptDialog(
-      requestURL, prompt, defaultText, base::BindOnce(completionHandler));
+      origin, prompt, defaultText, base::BindOnce(completionHandler));
 }
 
 - (void)webView:(WKWebView*)webView
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index 5436eac..ba2cb11c 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -28,6 +28,7 @@
 #import "ios/web/public/web_state.h"
 #import "ios/web/public/web_state_delegate.h"
 #import "url/gurl.h"
+#import "url/origin.h"
 
 @class CRWSessionStorage;
 @class CRWWebController;
@@ -232,21 +233,21 @@
                                    base::OnceCallback<void(bool)> callback);
 
   // Notifies the delegate that a JavaScript alert dialog needs to be presented.
-  void RunJavaScriptAlertDialog(const GURL& origin_url,
+  void RunJavaScriptAlertDialog(const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback);
 
   // Notifies the delegate that a JavaScript confirmation dialog needs to be
   // presented.
   void RunJavaScriptConfirmDialog(
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback);
 
   // Notifies the delegate that a JavaScript prompt dialog needs to be
   // presented.
   void RunJavaScriptPromptDialog(
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback);
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index b36040ce..5e866d1 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -401,31 +401,31 @@
                                                std::move(callback));
 }
 
-void WebStateImpl::RunJavaScriptAlertDialog(const GURL& origin_url,
+void WebStateImpl::RunJavaScriptAlertDialog(const url::Origin& origin,
                                             NSString* message_text,
                                             base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RealizedState()->RunJavaScriptAlertDialog(origin_url, message_text,
+  RealizedState()->RunJavaScriptAlertDialog(origin, message_text,
                                             std::move(callback));
 }
 
 void WebStateImpl::RunJavaScriptConfirmDialog(
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceCallback<void(bool success)> callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RealizedState()->RunJavaScriptConfirmDialog(origin_url, message_text,
+  RealizedState()->RunJavaScriptConfirmDialog(origin, message_text,
                                               std::move(callback));
 }
 
 void WebStateImpl::RunJavaScriptPromptDialog(
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     NSString* default_prompt_text,
     base::OnceCallback<void(NSString* user_input)> callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   RealizedState()->RunJavaScriptPromptDialog(
-      origin_url, message_text, default_prompt_text, std::move(callback));
+      origin, message_text, default_prompt_text, std::move(callback));
 }
 
 bool WebStateImpl::IsJavaScriptDialogRunning() {
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.h b/ios/web/web_state/web_state_impl_realized_web_state.h
index da261b4..7a30449e 100644
--- a/ios/web/web_state/web_state_impl_realized_web_state.h
+++ b/ios/web/web_state/web_state_impl_realized_web_state.h
@@ -144,15 +144,15 @@
   void HandleContextMenu(const ContextMenuParams& params);
   void ShowRepostFormWarningDialog(FormWarningType warning_type,
                                    base::OnceCallback<void(bool)> callback);
-  void RunJavaScriptAlertDialog(const GURL& origin_url,
+  void RunJavaScriptAlertDialog(const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback);
   void RunJavaScriptConfirmDialog(
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback);
   void RunJavaScriptPromptDialog(
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback);
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.mm b/ios/web/web_state/web_state_impl_realized_web_state.mm
index 0b0b5cc..b3e98ba4 100644
--- a/ios/web/web_state/web_state_impl_realized_web_state.mm
+++ b/ios/web/web_state/web_state_impl_realized_web_state.mm
@@ -504,7 +504,7 @@
 }
 
 void WebStateImpl::RealizedWebState::RunJavaScriptAlertDialog(
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceClosure callback) {
   JavaScriptDialogPresenter* presenter =
@@ -516,12 +516,12 @@
 
   running_javascript_dialog_ = true;
   presenter->RunJavaScriptAlertDialog(
-      owner_, origin_url, message_text,
+      owner_, origin, message_text,
       WrapCallbackForJavaScriptDialog(std::move(callback)));
 }
 
 void WebStateImpl::RealizedWebState::RunJavaScriptConfirmDialog(
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceCallback<void(bool success)> callback) {
   JavaScriptDialogPresenter* presenter =
@@ -533,12 +533,12 @@
 
   running_javascript_dialog_ = true;
   presenter->RunJavaScriptConfirmDialog(
-      owner_, origin_url, message_text,
+      owner_, origin, message_text,
       WrapCallbackForJavaScriptDialog(std::move(callback)));
 }
 
 void WebStateImpl::RealizedWebState::RunJavaScriptPromptDialog(
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     NSString* default_prompt_text,
     base::OnceCallback<void(NSString* user_input)> callback) {
@@ -551,7 +551,7 @@
 
   running_javascript_dialog_ = true;
   presenter->RunJavaScriptPromptDialog(
-      owner_, origin_url, message_text, default_prompt_text,
+      owner_, origin, message_text, default_prompt_text,
       WrapCallbackForJavaScriptDialog(std::move(callback)));
 }
 
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm
index e9b8e74..74d6f92 100644
--- a/ios/web/web_state/web_state_impl_unittest.mm
+++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -54,6 +54,7 @@
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #import "url/gurl.h"
+#import "url/origin.h"
 
 using base::test::RunOnceCallback;
 using base::test::ios::kWaitForPageLoadTimeout;
@@ -406,7 +407,7 @@
   EXPECT_FALSE(presenter->cancel_dialogs_called());
 
   __block bool callback_called = false;
-  web_state.RunJavaScriptAlertDialog(GURL(), @"", base::BindOnce(^() {
+  web_state.RunJavaScriptAlertDialog(url::Origin(), @"", base::BindOnce(^() {
                                        callback_called = true;
                                      }));
 
@@ -924,7 +925,8 @@
   // presented.
   delegate.GetFakeJavaScriptDialogPresenter()->set_callback_execution_paused(
       true);
-  web_state.RunJavaScriptAlertDialog(GURL(), @"message", base::DoNothing());
+  web_state.RunJavaScriptAlertDialog(url::Origin(), @"message",
+                                     base::DoNothing());
 
   // Verify that CanTakeSnapshot() returns no while the dialog is presented.
   EXPECT_FALSE(web_state.CanTakeSnapshot());
@@ -950,7 +952,8 @@
   // presented.
   delegate.GetFakeJavaScriptDialogPresenter()->set_callback_execution_paused(
       true);
-  web_state.RunJavaScriptAlertDialog(GURL(), @"message", base::DoNothing());
+  web_state.RunJavaScriptAlertDialog(url::Origin(), @"message",
+                                     base::DoNothing());
 
   // Verify that IsJavaScriptDialogRunning() returns true while the dialog is
   // presented.
@@ -985,7 +988,8 @@
   // presented.
   delegate.GetFakeJavaScriptDialogPresenter()->set_callback_execution_paused(
       true);
-  web_state.RunJavaScriptAlertDialog(GURL(), @"message", base::DoNothing());
+  web_state.RunJavaScriptAlertDialog(url::Origin(), @"message",
+                                     base::DoNothing());
 
   // Attempt to create a PDF for this page and validate that it return nil.
   __block NSData* callback_data_when_dialog = nil;
diff --git a/ios/web_view/internal/web_view_java_script_dialog_presenter.h b/ios/web_view/internal/web_view_java_script_dialog_presenter.h
index a43fed9..caefd76 100644
--- a/ios/web_view/internal/web_view_java_script_dialog_presenter.h
+++ b/ios/web_view/internal/web_view_java_script_dialog_presenter.h
@@ -33,17 +33,17 @@
 
   // web::JavaScriptDialogPresenter overrides:
   void RunJavaScriptAlertDialog(web::WebState* web_state,
-                                const GURL& origin_url,
+                                const url::Origin& origin,
                                 NSString* message_text,
                                 base::OnceClosure callback) override;
   void RunJavaScriptConfirmDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       base::OnceCallback<void(bool success)> callback) override;
   void RunJavaScriptPromptDialog(
       web::WebState* web_state,
-      const GURL& origin_url,
+      const url::Origin& origin,
       NSString* message_text,
       NSString* default_prompt_text,
       base::OnceCallback<void(NSString* user_input)> callback) override;
diff --git a/ios/web_view/internal/web_view_java_script_dialog_presenter.mm b/ios/web_view/internal/web_view_java_script_dialog_presenter.mm
index 0b6960f..f6ae34a 100644
--- a/ios/web_view/internal/web_view_java_script_dialog_presenter.mm
+++ b/ios/web_view/internal/web_view_java_script_dialog_presenter.mm
@@ -7,6 +7,8 @@
 #import "base/functional/callback_helpers.h"
 #import "ios/web_view/public/cwv_ui_delegate.h"
 #import "net/base/apple/url_conversions.h"
+#import "url/gurl.h"
+#import "url/origin.h"
 
 namespace ios_web_view {
 
@@ -19,7 +21,7 @@
 
 void WebViewJavaScriptDialogPresenter::RunJavaScriptAlertDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceClosure callback) {
   SEL delegate_method = @selector(webView:
@@ -30,14 +32,14 @@
   }
   [ui_delegate_ webView:web_view_
       runJavaScriptAlertPanelWithMessage:message_text
-                                 pageURL:net::NSURLWithGURL(origin_url)
+                                 pageURL:net::NSURLWithGURL(origin.GetURL())
                        completionHandler:base::CallbackToBlock(
                                              std::move(callback))];
 }
 
 void WebViewJavaScriptDialogPresenter::RunJavaScriptConfirmDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     base::OnceCallback<void(bool success)> callback) {
   SEL delegate_method = @selector(webView:
@@ -48,14 +50,14 @@
   }
   [ui_delegate_ webView:web_view_
       runJavaScriptConfirmPanelWithMessage:message_text
-                                   pageURL:net::NSURLWithGURL(origin_url)
+                                   pageURL:net::NSURLWithGURL(origin.GetURL())
                          completionHandler:base::CallbackToBlock(
                                                std::move(callback))];
 }
 
 void WebViewJavaScriptDialogPresenter::RunJavaScriptPromptDialog(
     web::WebState* web_state,
-    const GURL& origin_url,
+    const url::Origin& origin,
     NSString* message_text,
     NSString* default_prompt_text,
     base::OnceCallback<void(NSString* user_input)> callback) {
@@ -69,7 +71,7 @@
   [ui_delegate_ webView:web_view_
       runJavaScriptTextInputPanelWithPrompt:message_text
                                 defaultText:default_prompt_text
-                                    pageURL:net::NSURLWithGURL(origin_url)
+                                    pageURL:net::NSURLWithGURL(origin.GetURL())
                           completionHandler:base::CallbackToBlock(
                                                 std::move(callback))];
 }
diff --git a/ios/web_view/test/ui_delegate_inttest.mm b/ios/web_view/test/ui_delegate_inttest.mm
index 0f07b1d..76e2c67 100644
--- a/ios/web_view/test/ui_delegate_inttest.mm
+++ b/ios/web_view/test/ui_delegate_inttest.mm
@@ -14,6 +14,7 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/gtest_support.h"
 #import "url/gurl.h"
+#import "url/origin.h"
 
 using base::test::ios::kWaitForUIElementTimeout;
 
@@ -31,6 +32,11 @@
     ASSERT_TRUE(test_server_->Start());
   }
 
+  NSURL* GetEchoOriginURL() {
+    return net::NSURLWithGURL(
+        test_server_->GetURL("/echo").DeprecatedGetOriginAsURL());
+  }
+
   NSURL* GetEchoURL() {
     return net::NSURLWithGURL(test_server_->GetURL("/echo"));
   }
@@ -71,7 +77,7 @@
 
   OCMExpect([mock_delegate_ webView:web_view_
       runJavaScriptAlertPanelWithMessage:@"message"
-                                 pageURL:GetEchoURL()
+                                 pageURL:GetEchoOriginURL()
                        completionHandler:mock_completion_handler]);
 
   ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL()));
@@ -93,7 +99,7 @@
 
   OCMExpect([mock_delegate_ webView:web_view_
       runJavaScriptConfirmPanelWithMessage:@"message"
-                                   pageURL:GetEchoURL()
+                                   pageURL:GetEchoOriginURL()
                          completionHandler:mock_completion_handler]);
 
   ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL()));
@@ -117,7 +123,7 @@
   OCMExpect([mock_delegate_ webView:web_view_
       runJavaScriptTextInputPanelWithPrompt:@"prompt"
                                 defaultText:@"default"
-                                    pageURL:GetEchoURL()
+                                    pageURL:GetEchoOriginURL()
                           completionHandler:mock_completion_handler]);
 
   ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL()));
diff --git a/ios_internal b/ios_internal
index 5faebbb..09a4552 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 5faebbb3e45a687dae0a0cd09f8f8c69e9897386
+Subproject commit 09a455234a0af038336d80a2f116dc4602e49a5c
diff --git a/media/base/media_log_events.h b/media/base/media_log_events.h
index 1b3163a..4c1d73e 100644
--- a/media/base/media_log_events.h
+++ b/media/base/media_log_events.h
@@ -10,6 +10,7 @@
 #include "media/base/media_export.h"
 #include "media/base/media_log_type_enforcement.h"
 #include "media/base/media_track.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -124,7 +125,7 @@
                            std::string,
                            "video_occlusion_state");
 MEDIA_LOG_EVENT_NAMED_DATA(kAutoPictureInPictureInfoChanged,
-                           std::string,
+                           PictureInPictureEventsInfo::AutoPipInfo,
                            "auto_picture_in_picture_info");
 
 MEDIA_LOG_EVENT_NAMED_DATA_OP(kHlsSegmentFetch,
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index b347ce7..dac1b29a 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -454,6 +454,13 @@
 BASE_FEATURE(kChromeWideEchoCancellation,
              "ChromeWideEchoCancellation",
              base::FEATURE_ENABLED_BY_DEFAULT);
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+BASE_FEATURE(kSystemLoopbackAsAecReference,
+             "SystemLoopbackAsAecReference",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+const base::FeatureParam<int> kAddedProcessingDelay{
+    &kSystemLoopbackAsAecReference, "added_delay_ms", 100};
+#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
 #endif
 
 #if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN))
@@ -1697,6 +1704,24 @@
 #endif
 }
 
+bool IsSystemLoopbackAsAecReferenceEnabled() {
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) && \
+    (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
+  return base::FeatureList::IsEnabled(kSystemLoopbackAsAecReference);
+#else
+  return false;
+#endif
+}
+
+std::optional<base::TimeDelta> GetAecAddedDelay() {
+#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) && \
+    (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
+  return base::Milliseconds(kAddedProcessingDelay.Get());
+#else
+  return std::nullopt;
+#endif
+}
+
 bool IsSystemEchoCancellationEnforced() {
 #if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN))
   return base::FeatureList::IsEnabled(kEnforceSystemEchoCancellation);
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index e8fe905..72f3732 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -210,6 +210,10 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kContextMenuSearchForVideoFrame);
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kChromeWideEchoCancellation);
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kSystemLoopbackAsAecReference);
+MEDIA_EXPORT extern const base::FeatureParam<int> kAddedProcessingDelay;
+#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
 #endif
 #if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN))
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kEnforceSystemEchoCancellation);
@@ -543,6 +547,8 @@
     const base::CommandLine& command_line);
 
 MEDIA_EXPORT bool IsChromeWideEchoCancellationEnabled();
+MEDIA_EXPORT bool IsSystemLoopbackAsAecReferenceEnabled();
+MEDIA_EXPORT std::optional<base::TimeDelta> GetAecAddedDelay();
 MEDIA_EXPORT bool IsSystemEchoCancellationEnforced();
 MEDIA_EXPORT bool IsSystemEchoCancellationEnforcedAndAllowAgcInTandem();
 MEDIA_EXPORT bool IsSystemEchoCancellationEnforcedAndAllowNsInTandem();
diff --git a/media/capture/video/apple/video_capture_device_factory_apple.mm b/media/capture/video/apple/video_capture_device_factory_apple.mm
index 7362fa0..cbb60f4f 100644
--- a/media/capture/video/apple/video_capture_device_factory_apple.mm
+++ b/media/capture/video/apple/video_capture_device_factory_apple.mm
@@ -39,6 +39,7 @@
 
 namespace {
 
+#if BUILDFLAG(IS_MAC)
 void EnsureRunsOnCFRunLoopEnabledThread() {
   static bool has_checked_cfrunloop_for_video_capture = false;
   if (!has_checked_cfrunloop_for_video_capture) {
@@ -50,6 +51,7 @@
     has_checked_cfrunloop_for_video_capture = true;
   }
 }
+#endif
 
 media::VideoCaptureFormats GetDeviceSupportedFormats(AVCaptureDevice* device) {
   media::VideoCaptureFormats formats;
@@ -111,7 +113,10 @@
     const VideoCaptureDeviceDescriptor& descriptor) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK_NE(descriptor.capture_api, VideoCaptureApi::UNKNOWN);
+
+#if BUILDFLAG(IS_MAC)
   EnsureRunsOnCFRunLoopEnabledThread();
+#endif
 
   std::unique_ptr<VideoCaptureDevice> capture_device;
   if (descriptor.capture_api != VideoCaptureApi::MACOSX_DECKLINK) {
@@ -144,7 +149,10 @@
 void VideoCaptureDeviceFactoryApple::GetDevicesInfo(
     GetDevicesInfoCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
+#if BUILDFLAG(IS_MAC)
   EnsureRunsOnCFRunLoopEnabledThread();
+#endif
 
   NSArray<AVCaptureDevice*>* devices = media::GetVideoCaptureDevices();
 
diff --git a/media/gpu/v4l2/v4l2_queue.cc b/media/gpu/v4l2/v4l2_queue.cc
index c165302..e28689b2a 100644
--- a/media/gpu/v4l2/v4l2_queue.cc
+++ b/media/gpu/v4l2/v4l2_queue.cc
@@ -33,7 +33,7 @@
 namespace {
 
 // TODO(jkardatzke): Remove this when it is in linux/videodev2.h.
-#define V4L2_MEMORY_FLAG_SECURE 0x2
+#define V4L2_MEMORY_FLAG_RESTRICTED 0x2
 
 // Maximum number of requests that can be created.
 constexpr size_t kMaxNumRequests = 32;
@@ -1194,7 +1194,7 @@
 
   __u8 flags = incoherent ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
   if (allocate_secure_cb_) {
-    flags |= V4L2_MEMORY_FLAG_SECURE;
+    flags |= V4L2_MEMORY_FLAG_RESTRICTED;
   }
   struct v4l2_requestbuffers reqbufs = {
       .count = base::checked_cast<decltype(v4l2_requestbuffers::count)>(count),
@@ -1270,7 +1270,7 @@
   // Free all buffers.
   __u8 flags = incoherent_ ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
   if (allocate_secure_cb_) {
-    flags |= V4L2_MEMORY_FLAG_SECURE;
+    flags |= V4L2_MEMORY_FLAG_RESTRICTED;
   }
   struct v4l2_requestbuffers reqbufs = {
       .count = 0, .type = type_, .memory = memory_, .flags = flags};
diff --git a/media/mojo/mojom/media_player.mojom b/media/mojo/mojom/media_player.mojom
index 7e5e7460d..74bdc6c3 100644
--- a/media/mojo/mojom/media_player.mojom
+++ b/media/mojo/mojom/media_player.mojom
@@ -67,7 +67,7 @@
   // Request the media player to record auto picture in picture related
   // information. This information helps identify why a request to enter
   // picture in picture automatically is denied/accepted.
-  RecordAutoPictureInPictureInfo (string auto_picture_in_picture_info);
+  RecordAutoPictureInPictureInfo (AutoPipInfo auto_picture_in_picture_info);
 };
 
 // Implemented by the MediaWebContentsObserver. The remote lives in the renderer
diff --git a/media/webrtc/helpers.cc b/media/webrtc/helpers.cc
index 578e19d..8dae6a3 100644
--- a/media/webrtc/helpers.cc
+++ b/media/webrtc/helpers.cc
@@ -12,9 +12,12 @@
 #include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
 #include "build/chromecast_buildflags.h"
+#include "media/base/media_switches.h"
 #include "media/webrtc/webrtc_features.h"
 #include "third_party/webrtc/api/audio/audio_processing.h"
 #include "third_party/webrtc/api/audio/builtin_audio_processing_builder.h"
+#include "third_party/webrtc/api/audio/echo_canceller3_config.h"
+#include "third_party/webrtc/api/audio/echo_canceller3_factory.h"
 #include "third_party/webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
 #include "third_party/webrtc_overrides/environment.h"
 
@@ -144,7 +147,29 @@
       webrtc::AudioProcessing::Config::NoiseSuppression::Level::kHigh;
   apm_config.echo_canceller.enabled = settings.echo_cancellation;
   ConfigAutomaticGainControl(settings, apm_config);
-  return webrtc::BuiltinAudioProcessingBuilder(apm_config)
-      .Build(WebRtcEnvironment());
+
+  webrtc::BuiltinAudioProcessingBuilder apm_builder(apm_config);
+
+  // TODO(crbug.com/412581642): Plumb this as a parameter, this should not be
+  // used in the Renderer.
+  std::optional<base::TimeDelta> added_delay = media::GetAecAddedDelay();
+  if (added_delay.has_value()) {
+    webrtc::EchoCanceller3Config config;
+    webrtc::EchoCanceller3Config multichannel_config =
+        webrtc::EchoCanceller3Config::CreateDefaultMultichannelConfig();
+    // If we are using system loopback as AEC reference, we delay the capture
+    // signal so that the reference signal arrives before the capture signal.
+    // AEC considers the delay to be provided at 16 kHz sample rate.
+    config.delay.fixed_capture_delay_samples =
+        added_delay->InMilliseconds() * 16;
+    multichannel_config.delay.fixed_capture_delay_samples =
+        config.delay.fixed_capture_delay_samples;
+    std::unique_ptr<webrtc::EchoControlFactory> aec3_factory =
+        std::make_unique<webrtc::EchoCanceller3Factory>(config,
+                                                        multichannel_config);
+    apm_builder.SetEchoControlFactory(std::move(aec3_factory));
+  }
+
+  return apm_builder.Build(WebRtcEnvironment());
 }
 }  // namespace media
diff --git a/net/base/proxy_chain.h b/net/base/proxy_chain.h
index 2473a8f..361753b 100644
--- a/net/base/proxy_chain.h
+++ b/net/base/proxy_chain.h
@@ -173,6 +173,9 @@
   static constexpr int kDefaultIpProtectionChainId = 0;
 
   // The largest allowed ip_protection_chain_id.
+  // NOTE: Make sure to update the
+  // `Net.IpProtection.CanFalloverToNextProxy.Error.{Chain}` histogram when
+  // modifying this value.
   static constexpr int kMaxIpProtectionChainId = 3;
 
   bool is_for_ip_protection() const {
diff --git a/net/cookies/cookie_partition_key.cc b/net/cookies/cookie_partition_key.cc
index 411ad4c..0b3f9f7f 100644
--- a/net/cookies/cookie_partition_key.cc
+++ b/net/cookies/cookie_partition_key.cc
@@ -113,6 +113,9 @@
 
 std::strong_ordering CookiePartitionKey::operator<=>(
     const CookiePartitionKey& other) const {
+  if (from_script_ || other.from_script_) {
+    return from_script_ <=> other.from_script_;
+  }
   AncestorChainBit this_bit = GetAncestorChainBit();
   AncestorChainBit other_bit = other.GetAncestorChainBit();
   return std::tie(site_, nonce_, this_bit) <=>
@@ -272,6 +275,9 @@
     os << ",nonced";
   }
   os << (cpk.IsThirdParty() ? ",cross_site" : ",same_site");
+  if (cpk.from_script()) {
+    os << ",from_script";
+  }
   return os;
 }
 
diff --git a/net/cookies/cookie_partition_key_unittest.cc b/net/cookies/cookie_partition_key_unittest.cc
index 5a18586..374d0b58 100644
--- a/net/cookies/cookie_partition_key_unittest.cc
+++ b/net/cookies/cookie_partition_key_unittest.cc
@@ -342,10 +342,7 @@
   EXPECT_TRUE(key2->site().opaque());
   EXPECT_TRUE(key2->IsThirdParty());
 
-  // The keys should not be equal because they get created with different opaque
-  // sites. Test both the '==' and '!=' operators here.
-  EXPECT_FALSE(key == key2);
-  EXPECT_TRUE(key != key2);
+  EXPECT_EQ(key, key2);
 }
 
 TEST(CookiePartitionKeyTest, IsSerializeable) {
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc
index 6adfb89..9e47159a 100644
--- a/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -1248,6 +1248,7 @@
   const ProxyChain kNestedProxyChain2 =
       ProxyChain::ForIpProtection({{kBadProxyServer2, kGoodProxyServer}});
 
+  base::HistogramTester histogram_tester;
   for (GURL dest_url :
        {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
     SCOPED_TRACE(dest_url);
@@ -1441,6 +1442,32 @@
       EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
     }
   }
+  // Check that the errors were logged.
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_PROXY_CERTIFICATE_INVALID),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_PROXY_CONNECTION_FAILED),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_SSL_PROTOCOL_ERROR),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_TIMED_OUT),
+            0);
+  // Check the number of buckets.
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0"),
+              SizeIs(4));
+  // Check that no other proxy chains were logged.
+  const base::HistogramTester::CountsMap counts =
+      histogram_tester.GetTotalCountsForPrefix(
+          "Net.IpProtection.CanFalloverToNextProxy.Error.Chain");
+  EXPECT_THAT(counts, SizeIs(1));
 }
 
 // Same as above but using a multi-proxy chain, with errors encountered by the
@@ -1488,6 +1515,7 @@
   const ProxyChain kNestedProxyChain2 =
       ProxyChain::ForIpProtection({{kGoodProxyServer, kBadProxyServer2}});
 
+  base::HistogramTester histogram_tester;
   for (GURL dest_url :
        {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
     SCOPED_TRACE(dest_url);
@@ -1696,6 +1724,28 @@
       EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
     }
   }
+  // Check that the errors were logged.
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_PROXY_CERTIFICATE_INVALID),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_SSL_PROTOCOL_ERROR),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_TIMED_OUT),
+            0);
+  // Check the number of buckets.
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0"),
+              SizeIs(3));
+  // Check that no other proxy chains were logged.
+  const base::HistogramTester::CountsMap counts =
+      histogram_tester.GetTotalCountsForPrefix(
+          "Net.IpProtection.CanFalloverToNextProxy.Error.Chain");
+  EXPECT_THAT(counts, SizeIs(1));
 }
 
 // Test proxy fallback logic for an IP Protection request.
@@ -2009,6 +2059,8 @@
 
   url::SchemeHostPort proxy_server(url::kHttpsScheme, "badproxy", 99);
   url::SchemeHostPort proxy_server2(url::kHttpsScheme, "badfallbackproxy", 98);
+
+  base::HistogramTester histogram_tester;
   for (const auto& mock_error : kRetriableErrors) {
     SCOPED_TRACE(ErrorToString(mock_error.error));
 
@@ -2150,6 +2202,56 @@
     }
     EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
   }
+  // Check that the errors were logged.
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_ADDRESS_UNREACHABLE),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_CONNECTION_CLOSED),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_CONNECTION_RESET),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_CONNECTION_REFUSED),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_CONNECTION_ABORTED),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_NAME_NOT_RESOLVED),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_CONNECTION_TIMED_OUT),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_MSG_TOO_BIG),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_QUIC_PROTOCOL_ERROR),
+            0);
+  EXPECT_GT(histogram_tester.GetBucketCount(
+                "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0",
+                Error::ERR_QUIC_HANDSHAKE_FAILED),
+            0);
+  // Check the number of buckets.
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "Net.IpProtection.CanFalloverToNextProxy.Error.Chain0"),
+              SizeIs(10));
+  // Check that no other proxy chains were logged.
+  const base::HistogramTester::CountsMap counts =
+      histogram_tester.GetTotalCountsForPrefix(
+          "Net.IpProtection.CanFalloverToNextProxy.Error.Chain");
+  EXPECT_THAT(counts, SizeIs(1));
 }
 
 // Same as test above except that this is testing the retry behavior for
diff --git a/net/http/proxy_fallback.cc b/net/http/proxy_fallback.cc
index 70fa7d9d..d3359aa 100644
--- a/net/http/proxy_fallback.cc
+++ b/net/http/proxy_fallback.cc
@@ -4,6 +4,9 @@
 
 #include "net/http/proxy_fallback.h"
 
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
 #include "net/base/net_errors.h"
 #include "net/base/proxy_chain.h"
 #include "net/base/proxy_server.h"
@@ -14,9 +17,20 @@
                                        int error,
                                        int* final_error,
                                        bool is_for_ip_protection) {
+  if (is_for_ip_protection) {
+    // Log the error.
+    // Useful to know if errors not handled below are passed to this function.
+    if (const int chain_id = proxy_chain.ip_protection_chain_id();
+        chain_id != ProxyChain::kNotIpProtectionChainId) {
+      base::UmaHistogramSparse(
+          base::StrCat({"Net.IpProtection.CanFalloverToNextProxy.Error.Chain",
+                        base::NumberToString(chain_id)}),
+          error);
+    }
+  }
   *final_error = error;
   const auto& proxy_servers = proxy_chain.proxy_servers();
-  bool has_quic_proxy = std::any_of(
+  const bool has_quic_proxy = std::any_of(
       proxy_servers.begin(), proxy_servers.end(),
       [](const ProxyServer& proxy_server) { return proxy_server.is_quic(); });
   if (!proxy_chain.is_direct() && has_quic_proxy) {
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 48a4b535..f8c7777 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -24950,7 +24950,6 @@
     { "name": "crazypowered.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ctoin.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "czwartybrat.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "deathsdomain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "diamondgrid.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "directhomeremodelinginc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "djbobbytables.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -87124,7 +87123,6 @@
     { "name": "squaredtechnologies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "steroidswiki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "stonedwarf5.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "strongervision.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "successor.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sunwukong.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "suzannejauchius.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -99227,7 +99225,6 @@
     { "name": "aircash.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airconditioningkemptonpark.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airsial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "airtel.co.tz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ajansmanisa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ajmanded.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "akari.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -127313,7 +127310,6 @@
     { "name": "leyouyou.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lezzetlitatlitarifleri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lgtrees.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "liam.bzh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "libreai.nl.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "libreview.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lifefaithtruth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -143710,7 +143706,6 @@
     { "name": "airport-technology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airportpadova.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airsidemobile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "airtel.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airvistara.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aiskins.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -155670,7 +155665,6 @@
     { "name": "investingrenada.gd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "investmates.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "inviex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ioh.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "iomed.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "iomed.health", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ionescu.sexy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -158452,7 +158446,6 @@
     { "name": "dogownersacademy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "donerightservicepros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "donporque.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "doruk.net.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dosel.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dotycat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dr-tsanova.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -158576,7 +158569,6 @@
     { "name": "giftvoucherbrilliance.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "giorgi.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gita-vam.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "givaudan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gjenopptakelse.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "globalgaragesale.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "go-opencart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -160690,6 +160682,1273 @@
     { "name": "zwaminspectie.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zx-club.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zxavier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100plus.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100pluspro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1031ex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "112zwolle.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "119sh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1b.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1bar.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1plus1tv.zone", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22emesiecle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2rings.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2to.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "345404.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "365yg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "374952.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3b-bilisim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "401202.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4system.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "51lavanderiaindustrial.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "5nanceinsure.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6y666y6yy66.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "86dd.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aaronvdiepen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "academiadascriptomoedas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acafcantabria.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acarkentescortw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "activobank.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acumenpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acupunturameler.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acupunturameler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acupunturameler.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adaptex-shop.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adaptivemachiningcnc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adminbg.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "admtech.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adriantunez.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adventisti.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "affyes.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "afnaan.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agaia.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agar-tw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agph.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agromanagement.kz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ahmettoraman.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ai.futbol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aidigital.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aihub.bid", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "airman.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ajansguru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akkordeon-livemusik.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aleksandar.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexandriamainst.market", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alfatar-milk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alhayah-spine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alkon.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allshiftmed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "altdating.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "altheaarg.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "altinaypipes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alutech34.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amemei9f-lists.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "americannationaldogregistry.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amikekszunkjatek.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amimore.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amoremportugal.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amoresexo.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anewlife.care", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anewlife.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anfra.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "angelicogomme.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "angelrengifo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "annechristinebrunel.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "annekebemer.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anthonymrugacz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anthonymrugacz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antoniosisto.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anyever.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "api2cart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "apostasecasinos.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "appliancerepairteodor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "appshandler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aprizalputra.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aquitysolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arcarwegrow.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arcgpw.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "archaeopilot.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "archimede.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "archis.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arminjon.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armourfloorsnd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arstechni.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artista.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artyoomka.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "as209245.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ascore.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asqnw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "assistanceusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "astanor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asyaport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atelier-eddie.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atramare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atrec.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atropos.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atticode.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "auftragsfertigung.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aurum.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "austinoutline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autocarwash.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autohaus.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avantnr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ayvensbank.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ayzf.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "azey.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aztecagents.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b2bimmo.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ba.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "babysets.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bacelis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "backabc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "backtobed.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "badwolfie.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bakingbydonna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "balti.md", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "banarasiculture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "banes-lab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "banknotesdelarue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baradland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bardiharborow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barghfa.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barlex.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "batac.gov.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bati-consult.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "batoilles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bauermediaoutdoor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baum-gruenpflege.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bazahub.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bdmelbet.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beautybazaarshop.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "behindthemars.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "belkinmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "benecol.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bengalmania.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bess.company", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bess.edu.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestbets.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besties.house", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bewire.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bezbarier.org.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bioagency.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bioaiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biointegritylab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biovest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biovestinternational.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blacksprut.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blacksquad.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blazelock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bliznovice.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluepointatm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blvckseedbarber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boardgamesforallages.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bofplus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boheme.lk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bolduae.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonnins.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boomsourcing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bootspraxis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bootsverleih-buch-balduinstein.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "borneosprings.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boscrowan.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bosquesdevenezuela-caroni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boxexpresslogistic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bozdev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brabantse-delta.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bricogarmadrid.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brinavkuhni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "briskteaching.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brutal.diamonds", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btwexperience.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btwgiftcard.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btwschool.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btwservice.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btwstore.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btyr.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buchbinderei-schaumann.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buffge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bulagro.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bulsec.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bulwarkhealth.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bunnysear.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "businessnews.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buswell-familie.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buzzseminar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bvcf.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cafexpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cahorizontours.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cakrawiratama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calinadrian.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calyxlms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "camelliacourtmotel.kiwi.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canadaimmigration.services", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cannavistawellness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cardozovargas.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caritasgumaca.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carnationmalaysia.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carsdbshop.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "casadentalsas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "casamerced.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caseware-idea.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "casewareanalytics.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ccaeurope.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ccbaltics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cccx.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cctvonline.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cdnto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cellculturecompany.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cellculturecompany.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centerforinterfaithrelations.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "certificazioni-energetiche.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ceslasvegasnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cfoaonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chambre-enfant-bebe.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chancecomdeus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charge-point.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chargeincluded.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charlieconstruction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charlottedaviesphotography.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chatondesk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "checkaninvoice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chenilles-processionnaires-idf.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chiconyitd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chillywhite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chinavicharana-mole.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chinesedanceschool.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "churchcapital.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ciclosis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cimediweb.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cimsp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cinderstravels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cistarolaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "citrincooperman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cleanershub.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cleanpouches.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clearstreamcapital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cleburneinsurance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clockidz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudavy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clover-vtl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clun.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cmnd.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cobalt.tools", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coffeesense.coffee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "collide.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "colnevalleyvets.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coloradogenerac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "community-forward.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "computersharecas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "computersharecas.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "conciergemedical.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "conputant.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consultorseo.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "copy-kait.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "core-rpg.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cotefrete.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coursave.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coursemology.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coyotehillstecate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cpe.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cranstoun.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cravio-icecream.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "creditosonline.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crftvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crisis.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crocs.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crsoresina.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptodnsapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "csekkold.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "csn-boletos.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cursed.foundation", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cursosbajoprecio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cve-wizard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberbs.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberd.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberfortress.security", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberlaracom.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberti.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daisy.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dangeredwolf.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darksilver.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darrenockert.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dataloop.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "datarepositorytatr.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dckhst.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "de4dames.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deccanvalue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deckerammo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dekunstvananders.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltadigital.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltax.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dempseyenergy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deoxyam.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "derinforge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "derinforge.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "derstreuner.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "descalcificadorinhibidorecocal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "designerfabricsforless.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "detus.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dg-pberon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamondinterestcoffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diboochi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dichanho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dina.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dineatbuca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diploma.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diplomaverify.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dipsbd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dis-tract.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "discountduuka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disinfestazioni.varese.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "divinepathretreat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "divipay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dken.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dkoreiba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dndesturia.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "docfliq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dolorhunter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dolsee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "domealert.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dominodijital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dommelzorg.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "donamadeira.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "donnabuswell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dornesolutions.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dotsandarrows.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dotsys.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doublemars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreamconnect.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drobny-app.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dstechnologies.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dstechnologiesinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "duaputra.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dubachinn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "durust.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dwd-devproject.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dyethin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "e-meterai.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "e2time.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eaglesmessageboard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eamda.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eamda.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "earlynotify.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "earthlinkrealestate.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ebenica.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eddygangloff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eifel-adventure.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elanatours.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elchanchoganador.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "electronics.com.bd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "element-ppf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elementarythegame.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elfreelancer.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eliteheatgroup.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "embark.studio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eminencecapital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "empresasavenda.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emy.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "endorsia.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "energo.eng.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "enfantsoleil.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "enisor.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epracawpolsce.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esdisena.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esquirereality.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "essentialsspa.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "euro.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evanserver.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "everchanging.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evolveacandheating.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exceldepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exec.institute", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exploraromundo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exportcargo.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "expose-co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exterminateur-guepes.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "f5techglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fabianbeiner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fabianbeiner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "facemu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "facuint.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fanspace.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fantasy-archery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farmhouse.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farmhouse.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fastgit.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fawnover.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fedthaar.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fehem.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fejasport.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "festivallusitanodocirco.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feuer-u-stein.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feuerwehr-bubikon.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "figuremarkets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "findity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "finotor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "firstaidcourses.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fixiecommerce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fixm.aero", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fkcd.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flangespreader.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flanschspreizer.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fliessendes.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flokylab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flowzone.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fn.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fn.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fn.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnbm.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fncreameries.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fndairies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fndairies.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fngroup.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnlife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnlife.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnn-creameries.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnncreameries.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fnthaidairies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fortunedoor.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fosterunity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fotix.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fouproduction.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foxtare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frankviola.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frankviola.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frankviola.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frankviola.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frankviola.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fraserandneave.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fraserandneave.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fraserandneave.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fraserandneave.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fredericheim.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomassistedliving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomwealthllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freshmilk.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fruittree.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fruittree.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fuck.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fuentesaquatics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fukikaekingdom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "funkydhaga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "futuremadein.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fxci.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fxcm360.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fxcm365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fxembed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaelle-esthetique.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gamestic.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaminglog.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaoice.run", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "garten-kresse.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gassafetymanchester.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gayporn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gees.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gen3marketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "genoadesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gerteis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "get-file.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getkliq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gfiber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gfournier.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ggsforex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ghcr.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gidonellis.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gidress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gincor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globalcareproducts.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globalios.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globalservice.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glueup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goldtagapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gospelofthekingdom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gov-online.go.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grabitvape.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grace.money", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gracefuljourneys.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "graduationsupplies.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greatriverig.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "groupeleriverain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guccigame.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guerande-cosmetiques.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guncreed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gwhoffman.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "h4kr.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hackhit.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haesoolee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "handcraftedinvirginia.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "handwfenceco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hannahandnick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haoskin.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "happyelections.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "happypixeldesigns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "harbingergroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hashti.tn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hatsthings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haveko-vv.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hayesfusion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hayesindustrialsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hazirlikatlamakursu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hazy.gay", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hazy.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hd-rezka.team", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hdrezka.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heba.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heightvale.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helium.computer", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helunahealth.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hequil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heynowbots.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hhk.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hidromar.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "highline-contracts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "himei.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hitstroy-k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hived.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hlyhoodies.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hoby-tech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "holysmart.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homefortress.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homeownershiphub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "houseandofficeclearance.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "howdy.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hushlayer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huskytaildigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iaen.edu.ec", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibda3-jo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibnsina.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icarsoft-france.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iccloyalty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ice-cream.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icecream.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iconicbarbershop.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "idrivegroup.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iduneo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "igniteyoursellingpotential.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ijji.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ikinogo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iluminatia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "imaginenewcastle.net.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impact-fluids.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impressaodigitalsp.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "imput.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indoorbattingcages.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "informeforesea.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infyztoms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ingrijimbatraniladomiciliu.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inherentgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "install-solar.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "installationhotte.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "instantly.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "insurgence.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "insurgencebook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "internetivo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inthekjv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iptor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iranskmei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ironroadpartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isaacscience.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isahaya-media.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isidor.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ismaweb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itc-audio.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itsbait.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ivarfinance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jacksonphysiciansearch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "japandizen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "japandizen.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jascha.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jasekeke.co.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jcrer.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jdl.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jewboyjacob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jf-sulpice.notaires.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jjfloor.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jkwwoodworks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jmgservices.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joelkoeper.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jovenespuntales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jovenespuntales.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jsc588.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "juices.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jutel.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kadri.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaito.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kak.ao", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kariyeryolu.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "karpaysa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "karpfgarten.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kasbahofpeace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "katina.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kawigraphics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kbc-travel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kemsia.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ketaketab.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keydifferencemedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keyfoundation.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "khatnip.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kings-potong.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kingsicecream.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kinogid.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kiratime.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kislepesek.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kizdarkz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kleinhuis-dachterrasse.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kleinhuis-historischer-gasthof.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "klingenberg.works", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "knopf.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kommunen.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kontikimedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "koppenexecutive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kouyanoyojinbo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kpopnewsdaily.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kqweu.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kr.cm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kraftdm.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "krstarica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "krzysztofzaleski.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ksero.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kuchennyhit.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kuratan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kvazimoda.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lacozy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lactec.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landbell-compliance-solutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landbell-marketplace-seller.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawyer-nemoto-office.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leadsapp.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leagueforecaster.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lechner-kuechentechnik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leeshunhing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leher-gz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "letsweel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lgenergy.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "libertesassociatives.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lifeofpromotion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lifestylecityspa.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "likeyesterdaysjam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lincolmlabs.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "link2fleet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liorizik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "litespeedhost.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "littlecourtcottages.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livenutriwell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livesync.win", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liza-floristik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "locanada.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "login.mom", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "logopedischcentrum.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lojazeustech.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lostfilm.cx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lot100cocoaland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lotus-den.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lrpartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ltmetro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luxedent.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lynt.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lyscarrental.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m7kni.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maconqc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madil-thob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magehouse.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnolia.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnolia.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnoliaicecream.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnoliaicecreamth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mainspitze.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mainstreetmeetingspace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maitre-chien-detection-explosif-securite-paca.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maitrechien.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malte.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manimalosteo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manju.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maqnelson.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maqnelsonagricola.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maqnelsonirrigacao.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maranello.wine", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marenbeiner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "margaux-perrin.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "markmysik.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marxists.pp.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "masterladder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matters.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matthewbarnesmusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mattress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mattresspro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mccallkulak.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mchalepersen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcicoach.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcwebpanel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "measurablesolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mediacomponents.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meditrendy.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meinbaustoffversand.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meingartenversand.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-id.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-ma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-mn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-np.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-ph.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-pk.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-srilanka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet-thailand.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbet.com.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melbetapk-vietnam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meleracupuncture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meow.camera", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mercenary-of-darkness.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meritadvisor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "messer-ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metabolicmenu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metasurfaces.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mgarchitekci.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mgs406.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mhc8.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mightyoakmarketing.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mijnpensioenportaal.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mijnstembureau-eindhoven.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mikenas.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "milay.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "milesforwomenshealth.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minty.pink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitchrankin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mixi.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mizuki.pink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mmixm.aero", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moi.gov.sd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monikapierzchala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monostreambr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mosquesofbangladesh.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mothernaturesdoctor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "motywacyjnedna.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mount.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mpssghosp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mron.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mroproperty.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtakconsultancy.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muirsdoneright.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "multiaxisinc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muniorotina.go.cr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "musicc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mycaffee.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myedi.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myfleetistics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myinvista.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myprivatehosts.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "n.ms", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nagyag.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nar.cards", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "naro-oh.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "narod.hr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationalmattressday.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "naturesinfusions.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nawigroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neontri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neoplm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netherwatch.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netsensai.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nettoyagedrone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nettoyageleriverain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nettoyagesleriverain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neumann-th.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "new-flyer.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "new-housebud.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newannual.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newannualfestival.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newborn-screening.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newborn-screening.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newflyer.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newflyeramerica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nexaking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nfi.parts", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nhnature.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nikosgkourtsas.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nirae.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nni-pulse-engagement-prd.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nolomed.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nominalcontabilidade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noobient.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "norgbass.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nortvi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noteapp.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nrb06.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ntangledstate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ntns.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutriflex.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutritea.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutriwell.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutriwellglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutrizionisti.milano.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nuvto.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nygreenapple.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nysusankitchen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oaklandnewsonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obdr.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oblique.security", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "octavianguzu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oegemalogistics.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oemdrink.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "offthegridnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "olejostores.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "omniadigital.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oneanime.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onkoplus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinebathrooms.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlineyokdilkursu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oohcoloring.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "openaccess.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "openfind.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optikabane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optinf.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "optinf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oraclegem.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oraclematerias.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "organicchurch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orxxin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oscarsmovienews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osmestresdainternet.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oswestrysff.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oszteralexandra.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "otp24hr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "outbrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ovarit.rip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ovog.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "owl.et", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oxbowtd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oyoshi.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oyudha.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paganchristianity.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pagbem.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pamba.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pamperedpersians.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panoramaed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pantsdirect.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parcdumbravaminunata.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parceirofinanceiro.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "partall.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "partsbase.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "passionecavalli.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "passwordrecoverytools.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "patrickod.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paulrayden.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pawilony-modulowe.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pelhams2k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pellerinstrategie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peoplesafe.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "percentagecheck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perfecttimingtoday.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perseusmining.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petarte.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pharosiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "philippringli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phonetracker.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "piccolosgombero.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pineviewlogan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pisni.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "piuralift.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pixelbass.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plantiary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pnl.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "podpravkite.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poetbuyback.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pokeymanatee4.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "polibri.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "polskimoskwa.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pondot.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "porlalibertad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "portal-vlastnikov.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prado21.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pradotv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prel.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "premiumlinks.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "premiumtimesng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prestashow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prestashow.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prevajalska-agencija.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prima-bohrmaschinen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prima-fritteusen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prima-router.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "printsfinds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proaxiom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proaxiom.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "professionalmicroblading.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "profix.computer", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "progarr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "project1service.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promedentecuador.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "provent.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prowebservices.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prvaboja.co.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "przyczepki.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "psway.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "psychologos.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "publicaffairssolutions.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "purga.news", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "q.cg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "q.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qisheiosxz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qualitykiosk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quentinrichard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quews.news", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quickmp3.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quietluxury.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quotemoto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "radicalresurgence.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "radisnoir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rafd.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rafy.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rafy.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raku-lab.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "randmevape.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "randoequipement.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rebase.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "receptveka.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "recyclensave.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redenethosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redpandacoding.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reiskh.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rejuveaesthetic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "relaxmasaz.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "renerpaten.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "replacedbyrobot.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "researchrealm.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rethinkingchurch.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rightlinetrading.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rikuwe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rktoptics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rmly.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rolossalon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "romantest.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "romanzolotarev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rosanewalker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rosensejo.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roxyfroxy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royalcresthomesllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpatechnologies.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rsml.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rudehash.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rustarg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rustargentina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rxkids.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rygiel.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sagilityhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sahinpierresnaturelles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saifalghazal.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sailcut.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salamon-it.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salmedia.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salomonsports.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salttherapyoregon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "samaamn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "samueljackhill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sandiegocomicconnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sandycreekrvpark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanjosestorm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sankyo-lease.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanlorenzoruiz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanvicenteferrer.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sapobarber.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saracajner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sardegnachiama.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sarrala.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "satiscation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "satoshistep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saugatuckcapital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "savehumanitynow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schuetzenverein-haselbach.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scootersrolloffs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scottholmesmusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scrapbot.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "screenwatermarksoftware.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scrollbots.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sditinsanutama.sch.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seankrichmar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secnd.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secnode.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secondwarehouse.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seecustom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seguro360.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sekuremerchants.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seo.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "separate.ly", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sermescro.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "serviciodemanitas.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sfmcompile.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shanayasmin.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sheltermap.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sherston.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shibakery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shiftsmm.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shopera.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shopipersia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shutdowntimer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sicurezzasud.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sigromid-construct.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "silhouette-api.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simmonsbedstore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sistemair.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sitiwebferrara.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "situsadvokat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skybass.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skylandsoft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slcmaquinas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sleepexperts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sleepys.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sleepys.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sleepysjob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sluto.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slv.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slv.fyi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sm-sektmanufaktur.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smaltimentoinerti.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smdpp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smidd.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smotrowrelated.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smssalesforce.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "societe-france-irlande.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sokb.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "solid.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "souqfriday.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sourcecredit.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spacedjam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spb-electric.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "speedkitten.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "squall.freeboxos.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "squarednull.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "srinona.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "srvrlss.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starelabs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starteesforsale.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "startspacehq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "statehillcocktailsandkitchen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "statewideoutdoorblinds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stefanochiolo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stellaripl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stemps.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stetsonrealestate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stichtingwerkopmaat.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "storytel.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stronyinternetowekoszalin.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "studentenwoordenboek.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stufen-los.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "substancelaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sudskapraksa.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sugarcribs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suitcompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sukys.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunme-jp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunsandvoids.systems", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supportyourapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supremearvadafencing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "surskiekraski.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sururmedical.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sw-700.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swc-the.exchange", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swcempire.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swd.news", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sweetloaded.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "switch.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sym8.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "syrover.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t4x.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taav.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tabi.tours", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tahaluf.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "talento.dev.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "talkan.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tangentelectricals.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tangselmedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tanzschulerichter.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tarriso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tatra.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taylors-enterprise.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tcl-foundation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tcvafrica.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tdk.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "technologic.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teknoparkistanbul.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "temanbelanja.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "terra-di-mezzo.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "terranomadictravels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tetiritiwaitangi.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tetrimus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texaspaversoutdoorliving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texhfexlabs.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texlan.lk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tfmcentre.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thackba.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdachs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdachs.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdachs.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdachs.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdachs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdax.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdax.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdax.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thcdax.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thebeef.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thedayimetjesus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thedeeperchristianlife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thedigitaldepartment.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thedronevortex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thegardensmall.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thegungrabber.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thegungrabber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theharbourkitchen.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theinsurgence.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thekenyatimes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thekolye.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thenewannual.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thenftlawyer.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thepeoplesvoice.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "therapedicpremier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thereachagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "therlyn.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theuppercode.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thevaluehub.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thever.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thevioniway.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thewellblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thilius.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "threatfender.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tibabeach.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timbertec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timeengraver.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timnextgen.com.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tivara.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tivara.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tivara.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tivara.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tlrksvy.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tobias-sachs.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toeflozeldersankara.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totositetv.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "touchbalance.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toussaint-romain.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "towersolutionsinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tpp.healthcare", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trans-tema.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "transcendconsultoriarh.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "transmax.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trattamenti.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tribeaura.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "triggerskills.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trinityguardion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trouble-clic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trueblueplumbingnw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tugi.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tulosleep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "turkishtranslation.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tuttoperlestetica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twerking.porn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twfier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twoodoo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uknew.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "underskog.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unghie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unicesusc.edu.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "union.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upanh.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uphshrine.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urbansportsclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urnabios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "utopian.capital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uvbaski.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uxtly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uzvod.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "v2generalcontractors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vaanivarta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valuetree.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vates.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vault-tec.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "venting-sochi.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verifiedchat.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "versich.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "versichat.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vertinext.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vessurvey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vetexpressmobilevet.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viajesotur.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viaknit.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viciadasemesmaltes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vietnam-melbet.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vision-ridge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vivekmalipatel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vmvinskin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vogue-lotus.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "volantinando.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vorxdigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vumea.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w-permission.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w3web.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wa-pen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wallsbreaker.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "walset.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wamdajo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wamobilisations.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wapmafija.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warburgvending.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warburgvending.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warburgvending.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wars.aw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waukeshacountywatch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webbcraftinggallery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webbmd.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wecan-it.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "welldeals.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "werkenbijoegema.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wesaveit.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wetheglobalpeople.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whgym.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "who-i-am.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "william.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "willsey.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "witzler.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wproduction.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wrongaddress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wustirr.works", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xavirabarte.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xcashshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xfiles.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xhgzhongzhuanym.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiufeng.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xneelo.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xobot.su", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xopero.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xserownia.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xserownia.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ydskursuankara.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yearning.gay", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yiyume.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yogcham-sangh-asso.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yokefood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yokefood.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youdriver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youlayla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourdigitalangel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youssefmanai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yumekawashrine.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yumikim.design", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zacharylund.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zafiriou.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zafrasa.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zedaflow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zenetek.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zenniereport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeocax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeroscaler.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zhenggangzhao.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zhis.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zipre.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zlund.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zorgbeurs.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ztt.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zuydgroep.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zwalm.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 15dcfe07..2e9ae476 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2025-04-24 12:54 UTC
+# Last updated: 2025-04-25 12:54 UTC
 PinsListTimestamp
-1745499266
+1745585642
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index 8e13d7a..71dc2b7 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2025-04-24 12:54 UTC
+// Last updated: 2025-04-25 12:54 UTC
 //
 {
   "pinsets": [
diff --git a/printing/backend/mojom/print_backend_mojom_traits.cc b/printing/backend/mojom/print_backend_mojom_traits.cc
index 7048e02..02cd2d3 100644
--- a/printing/backend/mojom/print_backend_mojom_traits.cc
+++ b/printing/backend/mojom/print_backend_mojom_traits.cc
@@ -7,7 +7,7 @@
 #include <map>
 
 #include "base/containers/contains.h"
-#include "base/debug/alias.h"
+#include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/logging.h"
 #include "build/build_config.h"
@@ -100,24 +100,10 @@
                   printing::PrinterBasicInfo>::
     Read(printing::mojom::PrinterBasicInfoDataView data,
          printing::PrinterBasicInfo* out) {
-  if (!data.ReadPrinterName(&out->printer_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDisplayName(&out->display_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadPrinterDescription(&out->printer_description)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadOptions(&out->options)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
+  if (!data.ReadPrinterName(&out->printer_name) ||
+      !data.ReadDisplayName(&out->display_name) ||
+      !data.ReadPrinterDescription(&out->printer_description) ||
+      !data.ReadOptions(&out->options)) {
     return false;
   }
 
@@ -126,8 +112,6 @@
   // possible destinations.
   if (out->printer_name.empty()) {
     DLOG(ERROR) << "The printer name must not be empty.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
   // There should be a non-empty value for `display_name` since it needs to
@@ -135,8 +119,6 @@
   // destinations.
   if (out->display_name.empty()) {
     DLOG(ERROR) << "The printer's display name must not be empty.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 
@@ -152,31 +134,34 @@
   std::string vendor_id;
   gfx::Size size_um;
   gfx::Rect printable_area_um;
+  // TODO(crbug.com/372062459): Remove debug code in this function when done.
+  static auto* const crash_key = base::debug::AllocateCrashKeyString(
+      "Bug372062459Paper", base::debug::CrashKeySize::Size64);
   if (!data.ReadDisplayName(&display_name)) {
-    base::debug::Alias(&data);
+    base::debug::ScopedCrashKeyString scoped_crash_str(crash_key,
+                                                       "display_name");
     base::debug::DumpWithoutCrashing();
     return false;
   }
   if (!data.ReadVendorId(&vendor_id)) {
-    base::debug::Alias(&data);
+    base::debug::ScopedCrashKeyString scoped_crash_str(crash_key, "vendor_id");
     base::debug::DumpWithoutCrashing();
     return false;
   }
   if (!data.ReadSizeUm(&size_um)) {
-    base::debug::Alias(&data);
+    base::debug::ScopedCrashKeyString scoped_crash_str(crash_key, "size_um");
     base::debug::DumpWithoutCrashing();
     return false;
   }
   if (!data.ReadPrintableAreaUm(&printable_area_um)) {
-    base::debug::Alias(&data);
+    base::debug::ScopedCrashKeyString scoped_crash_str(crash_key,
+                                                       "printable_area_um");
     base::debug::DumpWithoutCrashing();
     return false;
   }
 #if BUILDFLAG(IS_CHROMEOS)
   std::optional<printing::PaperMargins> supported_margins_um;
   if (!data.ReadSupportedMarginsUm(&supported_margins_um)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
@@ -194,9 +179,9 @@
 
   // If `max_height_um` is specified, ensure it's larger than size.
   if (max_height_um > 0 && max_height_um < size_um.height()) {
-    base::debug::Alias(&data);
-    base::debug::Alias(&max_height_um);
-    base::debug::Alias(&size_um);
+    base::debug::ScopedCrashKeyString scoped_crash_str(
+        crash_key, base::NumberToString(max_height_um) + "," +
+                       base::NumberToString(size_um.height()));
     base::debug::DumpWithoutCrashing();
     return false;
   }
@@ -204,11 +189,16 @@
   // Invalid if the printable area is empty or if the printable area is out of
   // bounds of the paper size.  `max_height_um` doesn't need to be checked here
   // since `printable_area_um` is always relative to `size_um`.
-  if (printable_area_um.IsEmpty() ||
-      !gfx::Rect(size_um).Contains(printable_area_um)) {
-    base::debug::Alias(&data);
-    base::debug::Alias(&printable_area_um);
-    base::debug::Alias(&size_um);
+  if (printable_area_um.IsEmpty()) {
+    base::debug::ScopedCrashKeyString scoped_crash_str(
+        crash_key, "printable_area_um empty");
+    base::debug::DumpWithoutCrashing();
+    return false;
+  }
+
+  if (!gfx::Rect(size_um).Contains(printable_area_um)) {
+    base::debug::ScopedCrashKeyString scoped_crash_str(
+        crash_key, size_um.ToString() + "," + printable_area_um.ToString());
     base::debug::DumpWithoutCrashing();
     return false;
   }
@@ -229,17 +219,8 @@
                   printing::PrinterSemanticCapsAndDefaults::MediaType>::
     Read(printing::mojom::MediaTypeDataView data,
          printing::PrinterSemanticCapsAndDefaults::MediaType* out) {
-  if (!data.ReadDisplayName(&out->display_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadVendorId(&out->vendor_id)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  return true;
+  return data.ReadDisplayName(&out->display_name) &&
+         data.ReadVendorId(&out->vendor_id);
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -288,17 +269,7 @@
                   ::printing::AdvancedCapabilityValue>::
     Read(printing::mojom::AdvancedCapabilityValueDataView data,
          ::printing::AdvancedCapabilityValue* out) {
-  if (!data.ReadName(&out->name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDisplayName(&out->display_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  return true;
+  return data.ReadName(&out->name) && data.ReadDisplayName(&out->display_name);
 }
 
 // static
@@ -306,32 +277,11 @@
                   ::printing::AdvancedCapability>::
     Read(printing::mojom::AdvancedCapabilityDataView data,
          ::printing::AdvancedCapability* out) {
-  if (!data.ReadName(&out->name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDisplayName(&out->display_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadType(&out->type)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDefaultValue(&out->default_value)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadValues(&out->values)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  return true;
+  return data.ReadName(&out->name) &&
+         data.ReadDisplayName(&out->display_name) &&
+         data.ReadType(&out->type) &&
+         data.ReadDefaultValue(&out->default_value) &&
+         data.ReadValues(&out->values);
 }
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
@@ -341,17 +291,7 @@
                   printing::PageOutputQualityAttribute>::
     Read(printing::mojom::PageOutputQualityAttributeDataView data,
          printing::PageOutputQualityAttribute* out) {
-  if (!data.ReadDisplayName(&out->display_name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadName(&out->name)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  return true;
+  return data.ReadDisplayName(&out->display_name) && data.ReadName(&out->name);
 }
 
 // static
@@ -359,17 +299,8 @@
                   printing::PageOutputQuality>::
     Read(printing::mojom::PageOutputQualityDataView data,
          printing::PageOutputQuality* out) {
-  if (!data.ReadQualities(&out->qualities)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDefaultQuality(&out->default_quality)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  return true;
+  return data.ReadQualities(&out->qualities) &&
+         data.ReadDefaultQuality(&out->default_quality);
 }
 #endif
 
@@ -386,69 +317,25 @@
   out->collate_capable = data.collate_capable();
   out->collate_default = data.collate_default();
   out->copies_max = data.copies_max();
-  if (!data.ReadDuplexModes(&out->duplex_modes)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDuplexDefault(&out->duplex_default)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
+  if (!data.ReadDuplexModes(&out->duplex_modes) ||
+      !data.ReadDuplexDefault(&out->duplex_default)) {
     return false;
   }
   out->color_changeable = data.color_changeable();
   out->color_default = data.color_default();
-  if (!data.ReadColorModel(&out->color_model)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadBwModel(&out->bw_model)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadPapers(&out->papers)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadUserDefinedPapers(&out->user_defined_papers)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDefaultPaper(&out->default_paper)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDpis(&out->dpis)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadDefaultDpi(&out->default_dpi)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
+  if (!data.ReadColorModel(&out->color_model) ||
+      !data.ReadBwModel(&out->bw_model) || !data.ReadPapers(&out->papers) ||
+      !data.ReadUserDefinedPapers(&out->user_defined_papers) ||
+      !data.ReadDefaultPaper(&out->default_paper) ||
+      !data.ReadDpis(&out->dpis) || !data.ReadDefaultDpi(&out->default_dpi)) {
     return false;
   }
 
 #if BUILDFLAG(IS_CHROMEOS)
   out->pin_supported = data.pin_supported();
-  if (!data.ReadAdvancedCapabilities(&out->advanced_capabilities)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadPrintScalingTypes(&out->print_scaling_types)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
-    return false;
-  }
-  if (!data.ReadPrintScalingTypeDefault(&out->print_scaling_type_default)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
+  if (!data.ReadAdvancedCapabilities(&out->advanced_capabilities) ||
+      !data.ReadPrintScalingTypes(&out->print_scaling_types) ||
+      !data.ReadPrintScalingTypeDefault(&out->print_scaling_type_default)) {
     return false;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
@@ -458,8 +345,6 @@
   // Can not have less than one copy.
   if (out->copies_max < 1) {
     DLOG(ERROR) << "Must have copies_max greater than zero.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 
@@ -467,8 +352,6 @@
   DuplicateChecker<printing::mojom::DuplexMode> duplex_modes_dup_checker;
   if (duplex_modes_dup_checker.HasDuplicates(out->duplex_modes)) {
     DLOG(ERROR) << "Duplicate duplex_modes detected.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 
@@ -476,7 +359,15 @@
       user_defined_papers_dup_checker;
   if (user_defined_papers_dup_checker.HasDuplicates(out->user_defined_papers)) {
     DLOG(ERROR) << "Duplicate user_defined_papers detected.";
-    base::debug::Alias(&data);
+    // TODO(crbug.com/372062459): Remove debug code when done.
+    std::string names;
+    for (const auto& user_defined_paper : out->user_defined_papers) {
+      names += user_defined_paper.display_name();
+      names += ' ';
+    }
+    static auto* const crash_key = base::debug::AllocateCrashKeyString(
+        "Bug372062459UserDefinedPaper", base::debug::CrashKeySize::Size1024);
+    base::debug::ScopedCrashKeyString scoped_crash_str(crash_key, names);
     base::debug::DumpWithoutCrashing();
     return false;
   }
@@ -487,24 +378,18 @@
   if (advanced_capabilities_dup_checker.HasDuplicates(
           out->advanced_capabilities)) {
     DLOG(ERROR) << "Duplicate advanced_capabilities detected.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
   DuplicateChecker<printing::mojom::PrintScalingType>
       print_scaling_types_dup_checker;
   if (print_scaling_types_dup_checker.HasDuplicates(out->print_scaling_types)) {
     DLOG(ERROR) << "Duplicate print_scaling_types detected.";
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_WIN)
   if (!data.ReadPageOutputQuality(&out->page_output_quality)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
   DuplicateChecker<printing::PageOutputQualityAttribute>
@@ -522,10 +407,6 @@
                           &printing::PageOutputQualityAttribute::name)) {
         DLOG(ERROR) << "Non-null default quality, but page output qualities "
                        "does not contain default quality";
-        base::debug::Alias(&data);
-        base::debug::Alias(&default_quality);
-        base::debug::Alias(&qualities);
-        base::debug::DumpWithoutCrashing();
         return false;
       }
     }
@@ -533,9 +414,6 @@
     // There should be no duplicates in `qualities` array.
     if (page_output_quality_dup_checker.HasDuplicates(qualities)) {
       DLOG(ERROR) << "Duplicate page output qualities detected.";
-      base::debug::Alias(&data);
-      base::debug::Alias(&qualities);
-      base::debug::DumpWithoutCrashing();
       return false;
     }
   }
@@ -543,8 +421,6 @@
 
   if (!data.ReadMediaTypes(&media_types) ||
       !data.ReadDefaultMediaType(&default_media_type)) {
-    base::debug::Alias(&data);
-    base::debug::DumpWithoutCrashing();
     return false;
   }
 
diff --git a/services/audio/BUILD.gn b/services/audio/BUILD.gn
index efbfef58..ebff7ff 100644
--- a/services/audio/BUILD.gn
+++ b/services/audio/BUILD.gn
@@ -113,6 +113,8 @@
       "processing_audio_fifo.h",
       "sync_mixing_graph_input.cc",
       "sync_mixing_graph_input.h",
+      "system_loopback_listener.cc",
+      "system_loopback_listener.h",
     ]
 
     public_deps += [ "//media/webrtc" ]
diff --git a/services/audio/stream_factory.cc b/services/audio/stream_factory.cc
index 037c892..1093f6b 100644
--- a/services/audio/stream_factory.cc
+++ b/services/audio/stream_factory.cc
@@ -23,6 +23,7 @@
 
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
 #include "services/audio/output_device_mixer.h"
+#include "services/audio/system_loopback_listener.h"
 #endif
 
 namespace audio {
@@ -38,6 +39,15 @@
   return std::make_unique<OutputDeviceMixerManager>(
       audio_manager, base::BindRepeating(&OutputDeviceMixer::Create));
 }
+
+std::unique_ptr<SystemLoopbackListener> MaybeCreateSystemLoopbackListener(
+    media::AudioManager* audio_manager) {
+  if (!media::IsSystemLoopbackAsAecReferenceEnabled()) {
+    return nullptr;
+  }
+
+  return std::make_unique<SystemLoopbackListener>(audio_manager);
+}
 #endif  // BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
 
 // Ideally, this would be based on the incoming audio's buffer durations.
@@ -56,6 +66,8 @@
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
       output_device_mixer_manager_(
           MaybeCreateOutputDeviceMixerManager(audio_manager)),
+      system_loopback_listener_(
+          MaybeCreateSystemLoopbackListener(audio_manager)),
 #endif
       loopback_worker_thread_("Loopback Worker", kReatimeThreadPeriod) {
 }
@@ -95,7 +107,11 @@
       std::move(stream_receiver), std::move(client), std::move(observer),
       std::move(pending_log), audio_manager_, aecdump_recording_manager_,
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
-      output_device_mixer_manager_.get(), std::move(processing_config),
+      system_loopback_listener_
+          ? static_cast<DeviceOutputListener*>(system_loopback_listener_.get())
+          : static_cast<DeviceOutputListener*>(
+                output_device_mixer_manager_.get()),
+      std::move(processing_config),
 #else
       nullptr, nullptr,
 #endif
diff --git a/services/audio/stream_factory.h b/services/audio/stream_factory.h
index 7d47338a..ddd9fd5 100644
--- a/services/audio/stream_factory.h
+++ b/services/audio/stream_factory.h
@@ -26,6 +26,7 @@
 
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
 #include "services/audio/output_device_mixer_manager.h"
+#include "services/audio/system_loopback_listener.h"
 #endif
 
 namespace base {
@@ -147,6 +148,7 @@
   // Order of the following members is important for a clean shutdown.
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
   const std::unique_ptr<OutputDeviceMixerManager> output_device_mixer_manager_;
+  const std::unique_ptr<SystemLoopbackListener> system_loopback_listener_;
 #endif
   LoopbackCoordinator coordinator_;
   std::vector<std::unique_ptr<LocalMuter>> muters_;
diff --git a/services/audio/system_loopback_listener.cc b/services/audio/system_loopback_listener.cc
new file mode 100644
index 0000000..e30eb37
--- /dev/null
+++ b/services/audio/system_loopback_listener.cc
@@ -0,0 +1,137 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/system_loopback_listener.h"
+
+#include <memory>
+
+#include "base/containers/flat_set.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_io.h"
+#include "media/base/audio_bus.h"
+#include "services/audio/audio_manager_power_user.h"
+#include "services/audio/device_output_listener.h"
+
+namespace audio {
+
+class SystemLoopbackListener::AudioCallback
+    : public media::AudioInputStream::AudioInputCallback {
+ public:
+  explicit AudioCallback(int sample_rate) : sample_rate_(sample_rate) {}
+
+  void OnData(const media::AudioBus* source,
+              base::TimeTicks capture_time,
+              double volume,
+              const media::AudioGlitchInfo& audio_glitch_info) override {
+    base::AutoLock scoped_lock(lock_);
+    for (ReferenceOutput::Listener* listener : listeners_) {
+      // Since we are using a loopback signal, the audio has likely already been
+      // played out at this point, so the delay would be negative. To avoid
+      // confusion in the AudioProcessor, we set it to 0 for now.
+      // TODO(crbug.com/412581642): Figure out the correct value for this delay.
+      listener->OnPlayoutData(*source, sample_rate_,
+                              /*audio_delay=*/base::TimeDelta());
+    }
+  }
+
+  void OnError() override {
+    // TODO(crbug.com/412581642): Handle errors.
+    LOG(ERROR) << "System loopback AEC reference stream failed.";
+  }
+
+  base::Lock lock_;
+  base::flat_set<ReferenceOutput::Listener*> listeners_ GUARDED_BY(lock_);
+  const int sample_rate_;
+
+  void AddListener(ReferenceOutput::Listener* listener) {
+    base::AutoLock scoped_lock(lock_);
+    listeners_.insert(listener);
+  }
+
+  bool RemoveListener(ReferenceOutput::Listener* listener) {
+    base::AutoLock scoped_lock(lock_);
+    listeners_.erase(listener);
+    return listeners_.empty();
+  }
+};
+
+SystemLoopbackListener::SystemLoopbackListener(
+    media::AudioManager* audio_manager)
+    : audio_manager_(audio_manager) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+}
+
+SystemLoopbackListener::~SystemLoopbackListener() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  EnsureLoopbackStreamClosed();
+}
+
+void SystemLoopbackListener::StartListening(ReferenceOutput::Listener* listener,
+                                            const std::string& device_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  EnsureLoopbackStreamStarted();
+  audio_callback_->AddListener(listener);
+}
+
+void SystemLoopbackListener::StopListening(
+    ReferenceOutput::Listener* listener) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  if (audio_callback_->RemoveListener(listener)) {
+    // TODO(crbug.com/412581642): Close after a delay instead, in case we are
+    // calling StartListening() again soon.
+    EnsureLoopbackStreamClosed();
+  }
+}
+
+void SystemLoopbackListener::EnsureLoopbackStreamStarted() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  if (loopback_stream_ != nullptr) {
+    return;
+  }
+  const std::string loopback_device_id =
+      media::AudioDeviceDescription::kLoopbackInputDeviceId;
+
+  // TODO(crbug.com/412581642): Determine optimal parameters.
+  const media::AudioParameters params =
+      AudioManagerPowerUser(audio_manager_)
+          .GetInputStreamParameters(loopback_device_id);
+  audio_callback_ = std::make_unique<AudioCallback>(params.sample_rate());
+
+  // TODO(crbug.com/412581642): Add a different AudioComponent for the reference
+  // loopback streams and show them in chrome://media-internals
+  audio_log_ = audio_manager_->CreateAudioLog(
+      media::AudioLogFactory::AudioComponent::kAudioInputController,
+      next_loopback_stream_id_++);
+
+  loopback_stream_ = audio_manager_->MakeAudioInputStream(
+      params, loopback_device_id,
+      base::BindRepeating(&media::AudioLog::OnLogMessage,
+                          base::Unretained(audio_log_.get())));
+  loopback_stream_->Open();
+  audio_log_->OnCreated(params, loopback_device_id);
+  loopback_stream_->Start(audio_callback_.get());
+  audio_log_->OnStarted();
+}
+
+void SystemLoopbackListener::EnsureLoopbackStreamClosed() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  if (loopback_stream_ == nullptr) {
+    return;
+  }
+  loopback_stream_->Stop();
+  audio_log_->OnStopped();
+  loopback_stream_->Close();
+  audio_log_->OnClosed();
+  loopback_stream_ = nullptr;
+  audio_callback_.reset();
+  audio_log_.reset();
+}
+
+}  // namespace audio
diff --git a/services/audio/system_loopback_listener.h b/services/audio/system_loopback_listener.h
new file mode 100644
index 0000000..d46883311
--- /dev/null
+++ b/services/audio/system_loopback_listener.h
@@ -0,0 +1,52 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_SYSTEM_LOOPBACK_LISTENER_H_
+#define SERVICES_AUDIO_SYSTEM_LOOPBACK_LISTENER_H_
+
+#include <string>
+#include <string_view>
+
+#include "base/functional/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "base/sequence_checker.h"
+#include "media/audio/audio_manager.h"
+#include "services/audio/device_output_listener.h"
+#include "services/audio/reference_output.h"
+
+namespace audio {
+
+class SystemLoopbackListener : public DeviceOutputListener {
+ public:
+  class AudioCallback;
+
+  explicit SystemLoopbackListener(media::AudioManager* audio_manager);
+  SystemLoopbackListener(const SystemLoopbackListener&) = delete;
+  SystemLoopbackListener& operator=(const SystemLoopbackListener&) = delete;
+  ~SystemLoopbackListener() override;
+
+  void StartListening(ReferenceOutput::Listener* listener,
+                      const std::string& device_id) override;
+
+  void StopListening(ReferenceOutput::Listener* listener) override;
+
+ private:
+  void EnsureLoopbackStreamStarted();
+  void EnsureLoopbackStreamClosed();
+
+  SEQUENCE_CHECKER(owning_sequence_);
+  const raw_ptr<media::AudioManager> audio_manager_;
+  raw_ptr<media::AudioInputStream> loopback_stream_ = nullptr;
+  std::unique_ptr<media::AudioLog> audio_log_;
+  // To differentiate the streams that SystemLoopbackListener creates from the
+  // InputControllers, we start their ids at 1000000.
+  // TODO(crbug.com/412581642): Remove this hack once the reference streams get
+  // their own category.
+  int next_loopback_stream_id_ = 1000000;
+  std::unique_ptr<AudioCallback> audio_callback_;
+};
+
+}  // namespace audio
+
+#endif  // SERVICES_AUDIO_SYSTEM_LOOPBACK_LISTENER_H_
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn
index 9ba2d959..871fb1a8 100644
--- a/services/device/geolocation/BUILD.gn
+++ b/services/device/geolocation/BUILD.gn
@@ -164,6 +164,7 @@
       "//base:base_java",
       "//build/android:build_java",
       "//components/location/android:location_java",
+      "//services/device/public/java:device_feature_list_java",
       "//services/device/public/java:geolocation_java",
       "//third_party/android_deps:chromium_play_services_availability_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java b/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java
index 94edc8d8..a96f8494 100644
--- a/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java
+++ b/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java
@@ -19,6 +19,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.device.DeviceFeatureList;
 import org.chromium.gms.ChromiumPlayServicesAvailability;
 
 /**
@@ -84,6 +85,18 @@
                     .setInterval(UPDATE_INTERVAL_MS);
         }
 
+        if (DeviceFeatureList.sGmsCoreLocationRequestParamOverride.isEnabled()) {
+            locationRequest =
+                    new LocationRequest.Builder(locationRequest)
+                            .setIntervalMillis(
+                                    DeviceFeatureList.sGmsCoreLocationRequestUpdateInterval
+                                            .getValue())
+                            .setMaxUpdateAgeMillis(
+                                    DeviceFeatureList.sGmsCoreLocationRequestMaxLocationAge
+                                            .getValue())
+                            .build();
+        }
+
         stop();
 
         mLocationCallback =
diff --git a/services/device/public/cpp/device_feature_map.cc b/services/device/public/cpp/device_feature_map.cc
index 52a6443..c3561dc8 100644
--- a/services/device/public/cpp/device_feature_map.cc
+++ b/services/device/public/cpp/device_feature_map.cc
@@ -28,7 +28,7 @@
     &kGenericSensorExtraClasses,
     &kBatteryStatusManagerBroadcastReceiverInBackground,
     &device::features::kBluetoothRfcommAndroid,
-};
+    &device::features::kGmsCoreLocationRequestParamOverride};
 
 // static
 base::android::FeatureMap* GetFeatureMap() {
diff --git a/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java b/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
index ad9ca6d..b7c8e5f 100644
--- a/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
+++ b/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
@@ -4,8 +4,12 @@
 
 package org.chromium.device;
 
+import android.text.format.DateUtils;
+
 import org.jni_zero.JNINamespace;
 
+import org.chromium.base.MutableFlagWithSafeDefault;
+import org.chromium.base.MutableIntParamWithSafeDefault;
 import org.chromium.build.annotations.NullMarked;
 
 /**
@@ -25,4 +29,20 @@
     public static final String WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS =
             "WebAuthenticationRemoteDesktopAllowedOriginsPolicy";
     public static final String BLUETOOTH_RFCOMM_ANDROID = "BluetoothRfcommAndroid";
+
+    public static final MutableFlagWithSafeDefault sGmsCoreLocationRequestParamOverride =
+            newMutableFlagWithSafeDefault("GmsCoreLocationRequestParamOverride", false);
+    public static final MutableIntParamWithSafeDefault sGmsCoreLocationRequestUpdateInterval =
+            sGmsCoreLocationRequestParamOverride.newIntParam(
+                    "location_request_min_update_interval_millis",
+                    (int) (9 * DateUtils.SECOND_IN_MILLIS));
+    public static final MutableIntParamWithSafeDefault sGmsCoreLocationRequestMaxLocationAge =
+            sGmsCoreLocationRequestParamOverride.newIntParam(
+                    "location_request_max_location_age_mills",
+                    (int) (5 * DateUtils.SECOND_IN_MILLIS));
+
+    private static MutableFlagWithSafeDefault newMutableFlagWithSafeDefault(
+            String featureName, boolean defaultValue) {
+        return DeviceFeatureMap.getInstance().mutableFlagWithSafeDefault(featureName, defaultValue);
+    }
 }
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy.cc b/services/network/public/cpp/content_security_policy/content_security_policy.cc
index cff00b3..93fa4d9 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -42,7 +42,7 @@
 namespace {
 
 bool IsDirectiveNameCharacter(char c) {
-  return base::IsAsciiAlpha(c) || c == '-';
+  return base::IsAsciiAlphaNumeric(c) || c == '-';
 }
 
 bool IsDirectiveValueCharacter(char c) {
@@ -112,6 +112,10 @@
   if (base::EqualsCaseInsensitiveASCII(name, "script-src")) {
     return CSPDirectiveName::ScriptSrc;
   }
+  if (base::FeatureList::IsEnabled(network::features::kCSPScriptSrcV2) &&
+      base::EqualsCaseInsensitiveASCII(name, "script-src-v2")) {
+    return CSPDirectiveName::ScriptSrcV2;
+  }
   if (base::EqualsCaseInsensitiveASCII(name, "script-src-attr")) {
     return CSPDirectiveName::ScriptSrcAttr;
   }
@@ -171,6 +175,7 @@
     case CSPDirectiveName::ReportURI:
     case CSPDirectiveName::RequireTrustedTypesFor:
     case CSPDirectiveName::ScriptSrc:
+    case CSPDirectiveName::ScriptSrcV2:
     case CSPDirectiveName::ScriptSrcAttr:
     case CSPDirectiveName::ScriptSrcElem:
     case CSPDirectiveName::StyleSrc:
@@ -207,6 +212,7 @@
     case CSPDirectiveName::ReportTo:
     case CSPDirectiveName::RequireTrustedTypesFor:
     case CSPDirectiveName::ScriptSrc:
+    case CSPDirectiveName::ScriptSrcV2:
     case CSPDirectiveName::ScriptSrcAttr:
     case CSPDirectiveName::ScriptSrcElem:
     case CSPDirectiveName::StyleSrc:
@@ -255,6 +261,7 @@
     case CSPDirectiveName::RequireTrustedTypesFor:
     case CSPDirectiveName::Sandbox:
     case CSPDirectiveName::ScriptSrc:
+    case CSPDirectiveName::ScriptSrcV2:
     case CSPDirectiveName::ScriptSrcAttr:
     case CSPDirectiveName::ScriptSrcElem:
     case CSPDirectiveName::StyleSrc:
@@ -1047,6 +1054,7 @@
       case CSPDirectiveName::MediaSrc:
       case CSPDirectiveName::ObjectSrc:
       case CSPDirectiveName::ScriptSrc:
+      case CSPDirectiveName::ScriptSrcV2:
       case CSPDirectiveName::ScriptSrcAttr:
       case CSPDirectiveName::ScriptSrcElem:
       case CSPDirectiveName::StyleSrc:
@@ -1184,6 +1192,7 @@
     case CSPDirectiveName::MediaSrc:
     case CSPDirectiveName::ObjectSrc:
     case CSPDirectiveName::ScriptSrc:
+    case CSPDirectiveName::ScriptSrcV2:
     case CSPDirectiveName::StyleSrc:
       return CSPDirectiveName::DefaultSrc;
 
@@ -1601,6 +1610,8 @@
       return "sandbox";
     case CSPDirectiveName::ScriptSrc:
       return "script-src";
+    case CSPDirectiveName::ScriptSrcV2:
+      return "script-src-v2";
     case CSPDirectiveName::ScriptSrcAttr:
       return "script-src-attr";
     case CSPDirectiveName::ScriptSrcElem:
diff --git a/services/network/public/cpp/content_security_policy/csp_source_list.cc b/services/network/public/cpp/content_security_policy/csp_source_list.cc
index 56d7618..c2b1df7 100644
--- a/services/network/public/cpp/content_security_policy/csp_source_list.cc
+++ b/services/network/public/cpp/content_security_policy/csp_source_list.cc
@@ -50,6 +50,7 @@
 
 bool IsScriptDirective(CSPDirectiveName directive) {
   return directive == CSPDirectiveName::ScriptSrc ||
+         directive == CSPDirectiveName::ScriptSrcV2 ||
          directive == CSPDirectiveName::ScriptSrcAttr ||
          directive == CSPDirectiveName::ScriptSrcElem ||
          directive == CSPDirectiveName::DefaultSrc;
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
index 2868bf2..e27b874 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
@@ -7,12 +7,16 @@
 #include <vector>
 
 #include "base/test/gtest_util.h"
+#include "base/unguessable_token.h"
 #include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_partition_key.h"
+#include "net/cookies/cookie_partition_key_collection.h"
 #include "services/network/public/cpp/cookie_manager_mojom_traits.h"
 #include "services/network/public/mojom/cookie_manager.mojom-shared.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/cookie_partition_key.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/third_party/mozilla/url_parse.h"
@@ -367,30 +371,28 @@
   }
 }
 
-TEST(CookieManagerTraitsTest, Roundtrips_PartitionKey) {
-  auto original = net::CanonicalCookie::CreateUnsafeCookieForTesting(
-      "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), base::Time(),
-      base::Time(), true, false, net::CookieSameSite::NO_RESTRICTION,
-      net::COOKIE_PRIORITY_LOW,
-      net::CookiePartitionKey::FromURLForTesting(
-          GURL("https://toplevelsite.com")),
-      net::CookieSourceScheme::kSecure, 8433);
+TEST(CookieManagerTraitsTest, Roundtrips_CookiePartitionKey) {
+  using enum net::CookiePartitionKey::AncestorChainBit;
+  const GURL url("https://toplevelsite.com");
+  const auto nonce = base::UnguessableToken::Create();
+  for (const auto& original : {
+           net::CookiePartitionKey::FromURLForTesting(url),
+           net::CookiePartitionKey::FromURLForTesting(url, kSameSite),
+           net::CookiePartitionKey::FromURLForTesting(url, kCrossSite),
+           net::CookiePartitionKey::FromURLForTesting(url, kSameSite, nonce),
+           net::CookiePartitionKey::FromURLForTesting(url, kCrossSite, nonce),
+           net::CookiePartitionKey::FromScript().value(),
+       }) {
+    // `copied` is about to be overwritten so it doesn't matter what it is,
+    // but CookiePartitionKey doesn't provide a default ctor, so we have to
+    // initialize it to *some* value.
+    net::CookiePartitionKey copied =
+        net::CookiePartitionKey::FromURLForTesting(GURL());
 
-  net::CanonicalCookie copied;
-
-  EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
-      *original, copied));
-  EXPECT_EQ(original->PartitionKey(), copied.PartitionKey());
-  EXPECT_FALSE(copied.PartitionKey()->from_script());
-
-  original = net::CanonicalCookie::CreateUnsafeCookieForTesting(
-      "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), base::Time(),
-      base::Time(), true, false, net::CookieSameSite::NO_RESTRICTION,
-      net::COOKIE_PRIORITY_LOW, net::CookiePartitionKey::FromScript(),
-      net::CookieSourceScheme::kSecure, 8433);
-  EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CanonicalCookie>(
-      *original, copied));
-  EXPECT_TRUE(copied.PartitionKey()->from_script());
+    EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookiePartitionKey>(
+        original, copied));
+    EXPECT_EQ(original, copied);
+  }
 }
 
 TEST(CookieManagerTraitsTest, Roundtrips_AncestorChainBit) {
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index 9ef26a1..50aeaa0 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -612,4 +612,6 @@
              "DeviceBoundSessionAccessObserverSharedRemote",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kCSPScriptSrcV2, "ScriptSrcV2", base::FEATURE_DISABLED_BY_DEFAULT);
+
 }  // namespace network::features
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h
index fb2a936..3020a8b5 100644
--- a/services/network/public/cpp/features.h
+++ b/services/network/public/cpp/features.h
@@ -326,6 +326,9 @@
 COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES)
 BASE_DECLARE_FEATURE(kDeviceBoundSessionAccessObserverSharedRemote);
 
+COMPONENT_EXPORT(NETWORK_CPP_FLAGS_AND_SWITCHES)
+BASE_DECLARE_FEATURE(kCSPScriptSrcV2);
+
 }  // namespace network::features
 
 #endif  // SERVICES_NETWORK_PUBLIC_CPP_FEATURES_H_
diff --git a/services/network/public/mojom/content_security_policy.mojom b/services/network/public/mojom/content_security_policy.mojom
index b663fe6..63fb842 100644
--- a/services/network/public/mojom/content_security_policy.mojom
+++ b/services/network/public/mojom/content_security_policy.mojom
@@ -107,6 +107,7 @@
   RequireTrustedTypesFor,
   Sandbox,
   ScriptSrc,
+  ScriptSrcV2,
   ScriptSrcAttr,
   ScriptSrcElem,
   StyleSrc,
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
index 9090517f..2df9562 100644
--- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
+++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
@@ -108,7 +108,7 @@
 
 // Wrapper for |ConnectProducerSocketViaMojo| to be used as a function pointer.
 void ConnectProducerSocketAsync(perfetto::CreateSocketCallback cb) {
-  ConnectProducerSocketViaMojo(std::move(cb), base::Milliseconds(100));
+  PerfettoTracedProcess::Get().DeferOrConnectProducerSocket(std::move(cb));
 }
 #endif
 
@@ -171,19 +171,22 @@
   GetDataSourceTaskRunner() = task_runner;
 }
 
-// static
 void PerfettoTracedProcess::RestartThreadInSandbox() {
-  base::Thread* trace_thread = PerfettoTracedProcess::GetTraceThread();
-  if (trace_thread->StartWithOptions(
-          base::Thread::Options(base::MessagePumpType::IO, 0))) {
-    DETACH_FROM_SEQUENCE(PerfettoTracedProcess::Get().sequence_checker_);
-    PerfettoTracedProcess::Get().task_runner_ = trace_thread->task_runner();
-    PerfettoTracedProcess::Get().platform_->ResetTaskRunner(
-        trace_thread->task_runner());
-    DataSourceBase::ResetTaskRunner(trace_thread->task_runner());
-    PerfettoTracedProcess::Get().tracing_backend_->DetachFromMuxerSequence();
-    CustomEventRecorder::GetInstance()->DetachFromSequence();
+  CHECK(trace_process_thread_->StartWithOptions(
+      base::Thread::Options(base::MessagePumpType::IO, 0)));
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+  task_runner_ = trace_process_thread_->task_runner();
+  platform_->ResetTaskRunner(trace_process_thread_->task_runner());
+  DataSourceBase::ResetTaskRunner(trace_process_thread_->task_runner());
+  tracing_backend_->DetachFromMuxerSequence();
+  CustomEventRecorder::GetInstance()->DetachFromSequence();
+  will_trace_thread_restart_ = false;
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+  if (system_tracing_producer_socket_cb_) {
+    task_runner_->PostTask(FROM_HERE,
+                           std::move(system_tracing_producer_socket_cb_));
   }
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
 }
 
 // static
@@ -200,8 +203,10 @@
 }
 
 // static
-PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstanceWithThread() {
-  static base::NoDestructor<PerfettoTracedProcess> traced_process{};
+PerfettoTracedProcess& PerfettoTracedProcess::MaybeCreateInstanceWithThread(
+    bool will_trace_thread_restart) {
+  static base::NoDestructor<PerfettoTracedProcess> traced_process(
+      will_trace_thread_restart);
   return *traced_process;
 }
 
@@ -217,15 +222,18 @@
   return *g_instance;
 }
 
-PerfettoTracedProcess::PerfettoTracedProcess()
+PerfettoTracedProcess::PerfettoTracedProcess(bool will_trace_thread_restart)
     : trace_process_thread_(std::make_unique<base::Thread>("PerfettoTrace")),
       task_runner_(trace_process_thread_->StartWithOptions(
                        base::Thread::Options(base::MessagePumpType::IO, 0))
                        ? trace_process_thread_->task_runner()
                        : nullptr),
-      platform_(
-          std::make_unique<base::tracing::PerfettoPlatform>(task_runner_)),
+      will_trace_thread_restart_(will_trace_thread_restart),
       tracing_backend_(std::make_unique<PerfettoTracingBackend>()) {
+  base::tracing::PerfettoPlatform::Options options{
+      .defer_delayed_tasks = will_trace_thread_restart_};
+  platform_ =
+      std::make_unique<base::tracing::PerfettoPlatform>(task_runner_, options);
   DETACH_FROM_SEQUENCE(sequence_checker_);
   CHECK_EQ(g_instance, nullptr);
   CHECK(task_runner_);
@@ -366,6 +374,20 @@
   CustomEventRecorder::GetInstance();
 }
 
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+void PerfettoTracedProcess::DeferOrConnectProducerSocket(
+    perfetto::CreateSocketCallback cb) {
+  CHECK(!system_tracing_producer_socket_cb_);
+  // Hold off the attempts to get socket fd until trace thread restarts.
+  if (will_trace_thread_restart_) {
+    system_tracing_producer_socket_cb_ = base::BindOnce(
+        ConnectProducerSocketViaMojo, cb, base::Milliseconds(100));
+  } else {
+    ConnectProducerSocketViaMojo(cb, base::Milliseconds(100));
+  }
+}
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+
 void PerfettoTracedProcess::OnThreadPoolAvailable(bool enable_consumer) {
   thread_pool_started_ = true;
   SetupClientLibrary(enable_consumer);
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
index 6901696..a60a3ac 100644
--- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
+++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
@@ -97,6 +97,9 @@
     // By default, data source callbacks (e.g., Start/StopTracingImpl) are
     // called on PerfettoTracedProcess::GetTaskRunner()'s sequence. This method
     // allows overriding that task runner.
+    // Note: The task_runner's thread may stop and restart for Linux/ChromeOS
+    // sandboxing so the task_runner can change and delayed tasks posted to it
+    // may be silently dropped.
     virtual base::SequencedTaskRunner* GetTaskRunner();
 
     static void ResetTaskRunner(
@@ -152,8 +155,8 @@
     perfetto::DataSourceConfig data_source_config_;
   };
 
-  // Restart the trace thread and replace the task_runner for tracing.
-  static void RestartThreadInSandbox();
+  // Restarts the trace thread and replaces the task_runner for tracing.
+  void RestartThreadInSandbox();
 
   // Returns the process-wide ptr to the trace thread, returns nullptr if the
   // task_runner for tracing is from the thread-pool.
@@ -161,7 +164,8 @@
 
   // Creates the process-wide instance of the PerfettoTracedProcess.
   static PerfettoTracedProcess& MaybeCreateInstance();
-  static PerfettoTracedProcess& MaybeCreateInstanceWithThread();
+  static PerfettoTracedProcess& MaybeCreateInstanceWithThread(
+      bool will_trace_thread_restart);
   static PerfettoTracedProcess& MaybeCreateInstanceForTesting();
 
   // Returns the process-wide instance of the PerfettoTracedProcess.
@@ -228,11 +232,15 @@
       const perfetto::TraceConfig& config,
       const perfetto::Tracing::SetupStartupTracingOpts& opts);
 
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+  void DeferOrConnectProducerSocket(perfetto::CreateSocketCallback cb);
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+
  private:
   friend class base::NoDestructor<PerfettoTracedProcess>;
 
   // Default constructor would create a dedicated thread for tracing
-  PerfettoTracedProcess();
+  explicit PerfettoTracedProcess(bool will_trace_thread_restart);
   explicit PerfettoTracedProcess(
       scoped_refptr<base::SequencedTaskRunner> task_runner);
 
@@ -261,6 +269,11 @@
   std::unique_ptr<base::Thread> trace_process_thread_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
+  bool will_trace_thread_restart_ = false;
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+  base::OnceClosure system_tracing_producer_socket_cb_;
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+
   // Platform implementation for the Perfetto client library.
   std::unique_ptr<base::tracing::PerfettoPlatform> platform_;
   std::unique_ptr<PerfettoTracingBackend> tracing_backend_;
diff --git a/services/tracing/public/cpp/trace_startup.cc b/services/tracing/public/cpp/trace_startup.cc
index 71edec3..fc94a93e 100644
--- a/services/tracing/public/cpp/trace_startup.cc
+++ b/services/tracing/public/cpp/trace_startup.cc
@@ -46,17 +46,15 @@
 }  // namespace
 
 bool g_tracing_initialized_after_featurelist = false;
+bool g_tracing_with_thread = false;
 
 bool IsTracingInitialized() {
   return g_tracing_initialized_after_featurelist;
 }
 
-void EnableStartupTracingIfNeeded() {
+void EnableStartupTracingIfNeeded(bool with_thread) {
   RegisterTracedValueProtoWriter();
 
-  // Create the PerfettoTracedProcess.
-  PerfettoTracedProcess::MaybeCreateInstance();
-
   // Initialize the client library's TrackRegistry to support trace points
   // during startup tracing. We don't setup the client library completely here
   // yet, because we don't have field trials loaded yet (which influence which
@@ -65,6 +63,20 @@
   // setting up the client library?
   perfetto::internal::TrackRegistry::InitializeInstance();
 
+  // Create the PerfettoTracedProcess.
+  if (with_thread) {
+    g_tracing_with_thread = true;
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+    PerfettoTracedProcess::MaybeCreateInstanceWithThread(
+        /*will_trace_thread_restart=*/true);
+#else
+    PerfettoTracedProcess::MaybeCreateInstanceWithThread(
+        /*will_trace_thread_restart=*/false);
+#endif
+  } else {
+    PerfettoTracedProcess::MaybeCreateInstance();
+  }
+
   // Ensure TraceLog is initialized first.
   // https://crbug.com/764357
   TraceLog::GetInstance();
@@ -105,7 +117,9 @@
   DCHECK(base::FeatureList::GetInstance());
 
   // Create the PerfettoTracedProcess.
-  PerfettoTracedProcess::MaybeCreateInstance();
+  if (!g_tracing_with_thread) {
+    PerfettoTracedProcess::MaybeCreateInstance();
+  }
   PerfettoTracedProcess::Get().OnThreadPoolAvailable(enable_consumer);
 #if BUILDFLAG(IS_WIN)
   tracing::EnableETWExport();
diff --git a/services/tracing/public/cpp/trace_startup.h b/services/tracing/public/cpp/trace_startup.h
index 15b4f83c..1fcf57b 100644
--- a/services/tracing/public/cpp/trace_startup.h
+++ b/services/tracing/public/cpp/trace_startup.h
@@ -35,7 +35,8 @@
 // TODO(eseckler): Consider allocating the SMB in parent processes outside the
 // sandbox and supply it via the command line. Then, we can revert to call this
 // earlier and from fewer places again.
-void COMPONENT_EXPORT(TRACING_CPP) EnableStartupTracingIfNeeded();
+void COMPONENT_EXPORT(TRACING_CPP)
+    EnableStartupTracingIfNeeded(bool with_thread = false);
 
 // Enable startup tracing for the current process with the provided config. Sets
 // up ProducerClient and trace event and/or sampler profiler data sources, and
diff --git a/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.cc b/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.cc
index 3ba3cd50..36265605 100644
--- a/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.cc
@@ -20,6 +20,8 @@
       return viz::mojom::ContentFrameIntervalType::kAnimatingImage;
     case viz::ContentFrameIntervalType::kScrollBarFadeOutAnimation:
       return viz::mojom::ContentFrameIntervalType::kScrollBarFadeOutAnimation;
+    case viz::ContentFrameIntervalType::kCompositorScroll:
+      return viz::mojom::ContentFrameIntervalType::kCompositorScroll;
   }
   NOTREACHED();
 }
@@ -38,6 +40,9 @@
     case viz::mojom::ContentFrameIntervalType::kScrollBarFadeOutAnimation:
       *out = viz::ContentFrameIntervalType::kScrollBarFadeOutAnimation;
       return true;
+    case viz::mojom::ContentFrameIntervalType::kCompositorScroll:
+      *out = viz::ContentFrameIntervalType::kCompositorScroll;
+      return true;
   }
   return false;
 }
@@ -63,7 +68,13 @@
   if (!inputs.ReadFrameTime(&out->frame_time)) {
     return false;
   }
+  out->has_user_input = inputs.has_user_input();
   out->has_input = inputs.has_input();
+  out->major_scroll_speed_in_pixels_per_second =
+      inputs.major_scroll_speed_in_pixels_per_second();
+  if (out->major_scroll_speed_in_pixels_per_second < 0.f) {
+    return false;
+  }
   if (!inputs.ReadContentIntervalInfo(&out->content_interval_info)) {
     return false;
   }
diff --git a/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.h b/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.h
index 69e2d6d4..1b267b2dd 100644
--- a/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/frame_interval_inputs_mojom_traits.h
@@ -49,10 +49,19 @@
     return inputs.frame_time;
   }
 
+  static bool has_user_input(const viz::FrameIntervalInputs& inputs) {
+    return inputs.has_user_input;
+  }
+
   static bool has_input(const viz::FrameIntervalInputs& inputs) {
     return inputs.has_input;
   }
 
+  static float major_scroll_speed_in_pixels_per_second(
+      const viz::FrameIntervalInputs& inputs) {
+    return inputs.major_scroll_speed_in_pixels_per_second;
+  }
+
   static const std::vector<viz::ContentFrameIntervalInfo>&
   content_interval_info(const viz::FrameIntervalInputs& inputs) {
     return inputs.content_interval_info;
diff --git a/services/viz/public/mojom/compositing/frame_interval_inputs.mojom b/services/viz/public/mojom/compositing/frame_interval_inputs.mojom
index 1041e06..5fa36e40 100644
--- a/services/viz/public/mojom/compositing/frame_interval_inputs.mojom
+++ b/services/viz/public/mojom/compositing/frame_interval_inputs.mojom
@@ -10,21 +10,30 @@
 // These enums/structs are sent from viz clients such as the browser and
 // renderer to the viz compositor in the GPU process.
 
+// Typemapped to `viz::ContentFrameIntervalType` in
+// components/viz/common/quads/frame_interval_inputs.h.
 enum ContentFrameIntervalType {
   kVideo,
   kAnimatingImage,
   kScrollBarFadeOutAnimation,
+  kCompositorScroll,
 };
 
+// Typemapped to `viz::ContentFrameIntervalInfo` in
+// components/viz/common/quads/frame_interval_inputs.h.
 struct ContentFrameIntervalInfo {
   ContentFrameIntervalType type;
   mojo_base.mojom.TimeDelta frame_interval;
   uint32 duplicate_count = 0;
 };
 
+// Typemapped to `viz::FrameIntervalInputs` in
+// components/viz/common/quads/frame_interval_inputs.h.
 struct FrameIntervalInputs {
   mojo_base.mojom.TimeTicks frame_time;
+  bool has_user_input;
   bool has_input;
+  float major_scroll_speed_in_pixels_per_second;
 
   // For optimization, clients may (but are NOT required to) merge
   // ContentFrameIntervalInfo of same type and interval by incrementing
diff --git a/services/webnn/tflite/graph_builder_tflite.cc b/services/webnn/tflite/graph_builder_tflite.cc
index d7efe272..8040b40c 100644
--- a/services/webnn/tflite/graph_builder_tflite.cc
+++ b/services/webnn/tflite/graph_builder_tflite.cc
@@ -1348,8 +1348,6 @@
     return std::nullopt;
   }
 
-  const mojom::Operand& output_operand = GetOperand(conv2d.output_operand_id);
-  const uint32_t output_channels = output_operand.descriptor.shape()[3];
   // TODO(crbug.com/401281047): Support quantization fusion for transposed
   // conv2d.
   if (conv2d.kind != mojom::Conv2d::Kind::kDirect) {
@@ -1364,7 +1362,7 @@
       GetDequantizeOp(conv2d.filter_operand_id);
   const OperandDataType quantized_type =
       GetOperand(input_dequantize.input_operand_id).descriptor.data_type();
-  if (!DataTypeConstraint::kInts8.Has(quantized_type) ||
+  if (!IsInts8AndScalarScale(input_dequantize) ||
       GetOperand(filter_dequantize.input_operand_id).descriptor.data_type() !=
           quantized_type) {
     return std::nullopt;
@@ -1408,10 +1406,6 @@
   // For XNNPack delegate, input and output scale have to be scaler, both filter
   // and bias scale can be either scalar or vector that matches the output
   // channel.
-  CHECK(constant_operands_->contains(input_dequantize.scale_operand_id));
-  CHECK(constant_operands_->contains(quantize_linear.scale_operand_id));
-  CHECK(constant_operands_->contains(bias_dequantize.scale_operand_id));
-  CHECK(constant_operands_->contains(filter_dequantize.scale_operand_id));
   base::span<const float> input_scale_values =
       GetConstantValue<float>(input_dequantize.scale_operand_id);
   base::span<const float> output_scale_values =
@@ -1420,10 +1414,12 @@
       GetConstantValue<float>(bias_dequantize.scale_operand_id);
   base::span<const float> filter_scale_values =
       GetConstantValue<float>(filter_dequantize.scale_operand_id);
-  if (input_scale_values.size() != 1 || output_scale_values.size() != 1) {
+  if (output_scale_values.size() != 1) {
     return std::nullopt;
   }
 
+  const uint32_t output_channels =
+      GetOperand(conv2d.output_operand_id).descriptor.shape()[3];
   if ((bias_scale_values.size() != 1 &&
        bias_scale_values.size() != output_channels) ||
       (filter_scale_values.size() != 1 &&
@@ -1471,16 +1467,14 @@
     return std::nullopt;
   }
 
-  // Input and output operands must be dequantized from int8, and their scale
-  // and zero point must be scalar values, this is required by XNNPACK delegate
-  // in CheckTensorFloat32OrQUInt8Type.
   const mojom::DequantizeLinear& lhs_dequantize =
       GetDequantizeOp(binary.lhs_operand_id);
   const mojom::DequantizeLinear& rhs_dequantize =
       GetDequantizeOp(binary.rhs_operand_id);
   const OperandDataType quantized_type =
       GetOperand(lhs_dequantize.input_operand_id).descriptor.data_type();
-  if (!DataTypeConstraint::kInts8.Has(quantized_type) ||
+  if (!IsInts8AndScalarScale(lhs_dequantize) ||
+      !IsInts8AndScalarScale(rhs_dequantize) ||
       GetOperand(rhs_dequantize.input_operand_id).descriptor.data_type() !=
           quantized_type) {
     return std::nullopt;
@@ -1492,9 +1486,6 @@
     return std::nullopt;
   }
   const mojom::QuantizeLinear& output_quantize = GetQuantizeOp(*next_op);
-  CHECK(constant_operands_->contains(lhs_dequantize.scale_operand_id));
-  CHECK(constant_operands_->contains(rhs_dequantize.scale_operand_id));
-  CHECK(constant_operands_->contains(output_quantize.scale_operand_id));
   base::span<const float> lhs_scale_values =
       GetConstantValue<float>(lhs_dequantize.scale_operand_id);
   base::span<const float> rhs_scale_values =
@@ -1503,16 +1494,9 @@
       GetConstantValue<float>(output_quantize.scale_operand_id);
   // The shape of scale and zero point is the same, that has been verified in
   // the function ValidateScaleZeroPointOperandShapeIsCompatibleWithInput.
-  if (lhs_scale_values.size() != 1 || rhs_scale_values.size() != 1 ||
-      output_scale_values.size() != 1) {
+  if (output_scale_values.size() != 1) {
     return std::nullopt;
   }
-  CHECK_EQ(GetOperand(lhs_dequantize.zero_point_operand_id)
-               .descriptor.NumberOfElements(),
-           1u);
-  CHECK_EQ(GetOperand(rhs_dequantize.zero_point_operand_id)
-               .descriptor.NumberOfElements(),
-           1u);
   CHECK_EQ(GetOperand(output_quantize.zero_point_operand_id)
                .descriptor.NumberOfElements(),
            1u);
@@ -1566,6 +1550,26 @@
   return TrySerializeQuantizedOutput(*next_op);
 }
 
+std::optional<GraphBuilderTflite::TensorInfo>
+GraphBuilderTflite::CanFuseQuantizeAndGetOutput(
+    const mojom::Transpose& transpose) {
+  if (!IsDequantizeOutput(transpose.input_operand_id)) {
+    return std::nullopt;
+  }
+
+  const mojom::DequantizeLinear& input_dequantize =
+      GetDequantizeOp(transpose.input_operand_id);
+  if (!IsInts8AndScalarScale(input_dequantize)) {
+    return std::nullopt;
+  }
+
+  std::optional<size_t> next_op = IsNextOpQuantize(
+      transpose.output_operand_id,
+      {GetOperand(input_dequantize.input_operand_id).descriptor.data_type()});
+
+  return next_op ? TrySerializeQuantizedOutput(*next_op) : std::nullopt;
+}
+
 bool GraphBuilderTflite::IsDequantizeOutput(uint64_t operand_id) {
   return lazy_serialized_dequantize_operations_.contains(operand_id);
 }
@@ -1672,6 +1676,27 @@
   return quantize_op_idx;
 }
 
+bool GraphBuilderTflite::IsInts8AndScalarScale(
+    const mojom::DequantizeLinear& dequantize_linear) {
+  if (!DataTypeConstraint::kInts8.Has(
+          GetOperand(dequantize_linear.input_operand_id)
+              .descriptor.data_type())) {
+    return false;
+  }
+
+  if (GetOperand(dequantize_linear.scale_operand_id)
+          .descriptor.NumberOfElements() != 1) {
+    return false;
+  }
+
+  // The shape of scale and zero point is the same that has been verified in
+  // the function ValidateScaleZeroPointOperandShapeIsCompatibleWithInput.
+  CHECK_EQ(GetOperand(dequantize_linear.zero_point_operand_id)
+               .descriptor.NumberOfElements(),
+           1u);
+  return true;
+}
+
 std::optional<GraphBuilderTflite::TensorInfo>
 GraphBuilderTflite::TrySerializeQuantizedOutput(size_t quantize_op_idx) {
   const mojom::QuantizeLinear& quantize_linear = GetQuantizeOp(quantize_op_idx);
@@ -2858,94 +2883,93 @@
     const mojom::ElementWiseBinary& op)
     -> base::expected<OperatorOffset, std::string> {
   std::optional<TensorInfo> quantized_output;
-  const OperandDataType input_data_type =
-      GetOperand(op.lhs_operand_id).descriptor.data_type();
+  const OperandDescriptor& lhs_operand_descriptor =
+      GetOperand(op.lhs_operand_id).descriptor;
+  const OperandDescriptor& rhs_operand_descriptor =
+      GetOperand(op.rhs_operand_id).descriptor;
   ::tflite::BuiltinOperator code;
   switch (op.kind) {
     case mojom::ElementWiseBinary::Kind::kAdd:
-      CHECK(context_properties_.data_type_limits.add_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.add_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_ADD;
       quantized_output = CanFuseQuantizeAndGetOutput(op);
       break;
     case mojom::ElementWiseBinary::Kind::kSub:
-      CHECK(context_properties_.data_type_limits.sub_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.sub_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_SUB;
       quantized_output = CanFuseQuantizeAndGetOutput(op);
       break;
     case mojom::ElementWiseBinary::Kind::kMul:
-      CHECK(context_properties_.data_type_limits.mul_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.mul_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_MUL;
       quantized_output = CanFuseQuantizeAndGetOutput(op);
       break;
     case mojom::ElementWiseBinary::Kind::kDiv:
-      CHECK(context_properties_.data_type_limits.div_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.div_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_DIV;
       break;
     case mojom::ElementWiseBinary::Kind::kMax:
-      CHECK(context_properties_.data_type_limits.max_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.max_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_MAXIMUM;
       break;
     case mojom::ElementWiseBinary::Kind::kMin:
-      CHECK(context_properties_.data_type_limits.min_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.min_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_MINIMUM;
       break;
     case mojom::ElementWiseBinary::Kind::kPow:
-      CHECK(context_properties_.data_type_limits.pow_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.pow_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_POW;
       break;
     case mojom::ElementWiseBinary::Kind::kEqual:
-      CHECK(context_properties_.data_type_limits.equal_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.equal_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_EQUAL;
       break;
     case mojom::ElementWiseBinary::Kind::kGreater:
-      CHECK(context_properties_.data_type_limits.greater_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.greater_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_GREATER;
       break;
     case mojom::ElementWiseBinary::Kind::kGreaterOrEqual:
       CHECK(context_properties_.data_type_limits.greater_or_equal_input
-                .data_types.Has(input_data_type));
+                .SupportsAll({lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_GREATER_EQUAL;
       break;
     case mojom::ElementWiseBinary::Kind::kLesser:
-      CHECK(context_properties_.data_type_limits.lesser_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.lesser_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_LESS;
       break;
     case mojom::ElementWiseBinary::Kind::kLesserOrEqual:
       CHECK(context_properties_.data_type_limits.lesser_or_equal_input
-                .data_types.Has(input_data_type));
+                .SupportsAll({lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_LESS_EQUAL;
       break;
     case mojom::ElementWiseBinary::Kind::kNotEqual:
-      CHECK(context_properties_.data_type_limits.not_equal_input.data_types.Has(
-          input_data_type));
+      CHECK(context_properties_.data_type_limits.not_equal_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_NOT_EQUAL;
       break;
     case mojom::ElementWiseBinary::Kind::kLogicalAnd:
-      CHECK(
-          context_properties_.data_type_limits.logical_and_input.data_types.Has(
-              input_data_type));
+      CHECK(context_properties_.data_type_limits.logical_and_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_LOGICAL_AND;
       break;
     case mojom::ElementWiseBinary::Kind::kLogicalOr:
-      CHECK(
-          context_properties_.data_type_limits.logical_or_input.data_types.Has(
-              input_data_type));
+      CHECK(context_properties_.data_type_limits.logical_or_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       code = ::tflite::BuiltinOperator_LOGICAL_OR;
       break;
     case mojom::ElementWiseBinary::Kind::kLogicalXor:
-      CHECK(
-          context_properties_.data_type_limits.logical_xor_input.data_types.Has(
-              input_data_type));
+      CHECK(context_properties_.data_type_limits.logical_xor_input.SupportsAll(
+          {lhs_operand_descriptor, rhs_operand_descriptor}));
       // TFLite does not have a logical_xor operator. Since the inputs are
       // converted to bools below, we can use the not_equal operator to get the
       // same results as logical_xor.
@@ -5003,8 +5027,9 @@
 
 auto GraphBuilderTflite::SerializeMatmul(const mojom::Matmul& matmul)
     -> base::expected<OperatorOffset, std::string> {
-  CHECK(context_properties_.data_type_limits.matmul_input.data_types.Has(
-      GetOperand(matmul.a_operand_id).descriptor.data_type()));
+  CHECK(context_properties_.data_type_limits.matmul_input.SupportsAll(
+      {GetOperand(matmul.a_operand_id).descriptor,
+       GetOperand(matmul.b_operand_id).descriptor}));
   ASSIGN_OR_RETURN(const TensorInfo& a_tensor_info,
                    SerializeInputTensorInfo(matmul.a_operand_id));
   ASSIGN_OR_RETURN(const TensorInfo& b_tensor_info,
@@ -6319,13 +6344,26 @@
     -> base::expected<OperatorOffset, std::string> {
   CHECK(context_properties_.data_type_limits.transpose_input.Supports(
       GetOperand(transpose.input_operand_id).descriptor));
+
+  std::optional<TensorInfo> quantized_output =
+      CanFuseQuantizeAndGetOutput(transpose);
+  const bool fuse_dequantize = quantized_output.has_value();
   ASSIGN_OR_RETURN(const TensorInfo& input_tensor_info,
-                   SerializeInputTensorInfo(transpose.input_operand_id));
-  ASSIGN_OR_RETURN(const TensorInfo& output_tensor_info,
-                   SerializeOutputTensorInfo(transpose.output_operand_id));
+                   SerializeInputTensorInfo(
+                       transpose.input_operand_id, /*quantize_params=*/0,
+                       /*operation_supports_float16=*/false, fuse_dequantize));
+
+  int32_t output_tensor_index;
+  if (fuse_dequantize) {
+    output_tensor_index = quantized_output->index;
+  } else {
+    ASSIGN_OR_RETURN(const TensorInfo& output_tensor_info,
+                     SerializeOutputTensorInfo(transpose.output_operand_id));
+    output_tensor_index = output_tensor_info.index;
+  }
 
   return SerializeTransposeOperation(
-      input_tensor_info.index, output_tensor_info.index,
+      input_tensor_info.index, output_tensor_index,
       input_tensor_info.dimensions, transpose.permutation);
 }
 
diff --git a/services/webnn/tflite/graph_builder_tflite.h b/services/webnn/tflite/graph_builder_tflite.h
index 56a2ac7..6ce8088 100644
--- a/services/webnn/tflite/graph_builder_tflite.h
+++ b/services/webnn/tflite/graph_builder_tflite.h
@@ -702,13 +702,15 @@
 
   bool RequiresFloat32Precision(const mojom::Operation& op);
 
-  // Check if conv2d's inputs and outputs are quantized tensors and matches
-  // fusion criteria required by TFLite, if so we can remove the
+  // Check if inputs and outputs are quantized tensors and matches
+  // op specific fusion criteria required by TFLite, if so we can remove the
   // preceding `dequantizeLinear` and subsequent `quantizeLinear`.
   std::optional<TensorInfo> CanFuseQuantizeAndGetOutput(
       const mojom::Conv2d& conv2d);
   std::optional<TensorInfo> CanFuseQuantizeAndGetOutput(
       const mojom::ElementWiseBinary& binary);
+  std::optional<TensorInfo> CanFuseQuantizeAndGetOutput(
+      const mojom::Transpose& transpose);
   bool IsDequantizeOutput(uint64_t operand_id);
   //   Get the dequantize op by its output operand id.
   const mojom::DequantizeLinear& GetDequantizeOp(uint64_t operand_id);
@@ -726,6 +728,12 @@
   std::optional<size_t> IsNextOpQuantize(
       uint64_t output_operand_id,
       SupportedDataTypes supported_quantized_types);
+  // Check if the input is dequantized from (u)int8, and its scale and zero
+  // point are scalar values.
+  //
+  // Used by DQ->op->Q fusion to satisfy XNNPACK delegate's validation in
+  // `CheckTensorFloat32OrQUInt8Type`.
+  bool IsInts8AndScalarScale(const mojom::DequantizeLinear& dequantize_linear);
 
   bool IsSerializedWithMismatchQuantizeParameters(
       uint64_t operand_id,
diff --git a/services/webnn/webnn_graph_builder_impl.cc b/services/webnn/webnn_graph_builder_impl.cc
index 54433a3..278e690 100644
--- a/services/webnn/webnn_graph_builder_impl.cc
+++ b/services/webnn/webnn_graph_builder_impl.cc
@@ -507,17 +507,124 @@
   return component_attributes;
 }
 
+std::vector<uint64_t> GetOperationOutputs(const mojom::Operation& operation) {
+  switch (operation.which()) {
+    case mojom::Operation::Tag::kArgMinMax:
+      return {operation.get_arg_min_max()->output_operand_id};
+    case mojom::Operation::Tag::kBatchNormalization:
+      return {operation.get_batch_normalization()->output_operand_id};
+    case mojom::Operation::Tag::kClamp:
+      return {operation.get_clamp()->output_operand_id};
+    case mojom::Operation::Tag::kConcat:
+      return {operation.get_concat()->output_operand_id};
+    case mojom::Operation::Tag::kConv2d:
+      return {operation.get_conv2d()->output_operand_id};
+    case mojom::Operation::Tag::kCumulativeSum:
+      return {operation.get_cumulative_sum()->output_operand_id};
+    case mojom::Operation::Tag::kDequantizeLinear:
+      return {operation.get_dequantize_linear()->output_operand_id};
+    case mojom::Operation::Tag::kElementWiseBinary:
+      return {operation.get_element_wise_binary()->output_operand_id};
+    case mojom::Operation::Tag::kElu:
+      return {operation.get_elu()->output_operand_id};
+    case mojom::Operation::Tag::kElementWiseUnary:
+      return {operation.get_element_wise_unary()->output_operand_id};
+    case mojom::Operation::Tag::kExpand:
+      return {operation.get_expand()->output_operand_id};
+    case mojom::Operation::Tag::kGather:
+      return {operation.get_gather()->output_operand_id};
+    case mojom::Operation::Tag::kGatherElements:
+      return {operation.get_gather_elements()->output_operand_id};
+    case mojom::Operation::Tag::kGatherNd:
+      return {operation.get_gather_nd()->output_operand_id};
+    case mojom::Operation::Tag::kGelu:
+      return {operation.get_gelu()->output_operand_id};
+    case mojom::Operation::Tag::kGemm:
+      return {operation.get_gemm()->output_operand_id};
+    case mojom::Operation::Tag::kGru:
+      return operation.get_gru()->output_operand_ids;
+    case mojom::Operation::Tag::kGruCell:
+      return {operation.get_gru_cell()->output_operand_id};
+    case mojom::Operation::Tag::kHardSigmoid:
+      return {operation.get_hard_sigmoid()->output_operand_id};
+    case mojom::Operation::Tag::kHardSwish:
+      return {operation.get_hard_swish()->output_operand_id};
+    case mojom::Operation::Tag::kLayerNormalization:
+      return {operation.get_layer_normalization()->output_operand_id};
+    case mojom::Operation::Tag::kInstanceNormalization:
+      return {operation.get_instance_normalization()->output_operand_id};
+    case mojom::Operation::Tag::kLeakyRelu:
+      return {operation.get_leaky_relu()->output_operand_id};
+    case mojom::Operation::Tag::kLinear:
+      return {operation.get_linear()->output_operand_id};
+    case mojom::Operation::Tag::kLstm:
+      return operation.get_lstm()->output_operand_ids;
+    case mojom::Operation::Tag::kLstmCell:
+      return operation.get_lstm_cell()->output_operand_ids;
+    case mojom::Operation::Tag::kMatmul:
+      return {operation.get_matmul()->output_operand_id};
+    case mojom::Operation::Tag::kPad:
+      return {operation.get_pad()->output_operand_id};
+    case mojom::Operation::Tag::kPool2d:
+      return {operation.get_pool2d()->output_operand_id};
+    case mojom::Operation::Tag::kPrelu:
+      return {operation.get_prelu()->output_operand_id};
+    case mojom::Operation::Tag::kQuantizeLinear:
+      return {operation.get_quantize_linear()->output_operand_id};
+    case mojom::Operation::Tag::kReduce:
+      return {operation.get_reduce()->output_operand_id};
+    case mojom::Operation::Tag::kRelu:
+      return {operation.get_relu()->output_operand_id};
+    case mojom::Operation::Tag::kResample2d:
+      return {operation.get_resample2d()->output_operand_id};
+    case mojom::Operation::Tag::kReshape:
+      return {operation.get_reshape()->output_operand_id};
+    case mojom::Operation::Tag::kReverse:
+      return {operation.get_reverse()->output_operand_id};
+    case mojom::Operation::Tag::kScatterElements:
+      return {operation.get_scatter_elements()->output_operand_id};
+    case mojom::Operation::Tag::kScatterNd:
+      return {operation.get_scatter_nd()->output_operand_id};
+    case mojom::Operation::Tag::kSigmoid:
+      return {operation.get_sigmoid()->output_operand_id};
+    case mojom::Operation::Tag::kSlice:
+      return {operation.get_slice()->output_operand_id};
+    case mojom::Operation::Tag::kSoftmax:
+      return {operation.get_softmax()->output_operand_id};
+    case mojom::Operation::Tag::kSoftplus:
+      return {operation.get_softplus()->output_operand_id};
+    case mojom::Operation::Tag::kSoftsign:
+      return {operation.get_softsign()->output_operand_id};
+    case mojom::Operation::Tag::kSplit:
+      return operation.get_split()->output_operand_ids;
+    case mojom::Operation::Tag::kTanh:
+      return {operation.get_tanh()->output_operand_id};
+    case mojom::Operation::Tag::kTile:
+      return {operation.get_tile()->output_operand_id};
+    case mojom::Operation::Tag::kTranspose:
+      return {operation.get_transpose()->output_operand_id};
+    case mojom::Operation::Tag::kTriangular:
+      return {operation.get_triangular()->output_operand_id};
+    case mojom::Operation::Tag::kWhere:
+      return {operation.get_where()->output_operand_id};
+  }
+}
+
 // Helper class to validate a operations with the members passed to the
 // constructor as context.
 class OperationValidationContext {
   STACK_ALLOCATED();
 
  public:
+  struct ValidationResult {
+    base::flat_set<uint64_t> processed_operands;
+    DependentOperationsMap operand_to_dependent_operations;
+    base::flat_map<uint64_t, size_t> operand_to_producing_operation;
+  };
+
   // If `operations` are valid given the passed members as context, returns a
   // mapping of operands to the operations which depend on it.
-  static std::optional<
-      std::pair<base::flat_set<uint64_t>, DependentOperationsMap>>
-  ValidateOperationsAndGetDependencies(
+  static std::optional<ValidationResult> ValidateOperationsAndGetDependencies(
       const std::vector<mojom::OperationPtr>& operations,
       const ContextProperties& context_properties,
       const IdToOperandMap& id_to_operand_map,
@@ -530,12 +637,15 @@
       : context_properties_(context_properties),
         id_to_operand_map_(id_to_operand_map),
         processed_operands_(std::move(processed_operands)) {
-    operands_to_dependent_operations_.reserve(id_to_operand_map.size());
+    operand_to_dependent_operations_.reserve(id_to_operand_map.size());
+    operand_to_producing_operation_.reserve(id_to_operand_map.size());
   }
 
   const mojom::Operand* GetMojoOperand(uint64_t operand_id);
 
-  void NoteDependency(uint64_t operand_id, size_t operation_id);
+  void NoteInputDependency(uint64_t operand_id, size_t operation_id);
+  bool NoteOutputDependency(const mojom::Operation& operation,
+                            size_t operation_id);
 
   template <typename Operation>
   bool ValidateUnaryOperation(const Operation& operation,
@@ -623,7 +733,8 @@
 
   base::flat_set<uint64_t> processed_operands_;
 
-  DependentOperationsMap operands_to_dependent_operations_;
+  DependentOperationsMap operand_to_dependent_operations_;
+  base::flat_map<uint64_t, size_t> operand_to_producing_operation_;
 };
 
 const mojom::Operand* OperationValidationContext::GetMojoOperand(
@@ -631,19 +742,31 @@
   return ::webnn::GetMojoOperand(*id_to_operand_map_, operand_id);
 }
 
-void OperationValidationContext::NoteDependency(uint64_t operand_id,
-                                                size_t operation_id) {
-  auto it = operands_to_dependent_operations_.find(operand_id);
-  if (it == operands_to_dependent_operations_.end()) {
-    operands_to_dependent_operations_.emplace(operand_id,
-                                              std::vector({operation_id}));
+void OperationValidationContext::NoteInputDependency(uint64_t operand_id,
+                                                     size_t operation_id) {
+  auto it = operand_to_dependent_operations_.find(operand_id);
+  if (it == operand_to_dependent_operations_.end()) {
+    operand_to_dependent_operations_.emplace(operand_id,
+                                             std::vector({operation_id}));
   } else {
     it->second.insert(operation_id);
   }
 }
 
+bool OperationValidationContext::NoteOutputDependency(
+    const mojom::Operation& operation,
+    size_t operation_id) {
+  for (uint64_t output_operand_id : GetOperationOutputs(operation)) {
+    RETURN_IF_FALSE(operand_to_producing_operation_
+                        .try_emplace(output_operand_id, operation_id)
+                        .second);
+    RETURN_IF_FALSE(processed_operands_.insert(output_operand_id).second);
+  }
+  return true;
+}
+
 // static
-std::optional<std::pair<base::flat_set<uint64_t>, DependentOperationsMap>>
+std::optional<OperationValidationContext::ValidationResult>
 OperationValidationContext::ValidateOperationsAndGetDependencies(
     const std::vector<mojom::OperationPtr>& operations,
     const ContextProperties& context_properties,
@@ -659,7 +782,8 @@
   }
 
   return {{std::move(context.processed_operands_),
-           std::move(context.operands_to_dependent_operations_)}};
+           std::move(context.operand_to_dependent_operations_),
+           std::move(context.operand_to_producing_operation_)}};
 }
 
 template <typename Operation>
@@ -670,10 +794,7 @@
   if (!processed_operands_.contains(operation.input_operand_id)) {
     return false;
   }
-  NoteDependency(operation.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(operation.output_operand_id).second);
+  NoteInputDependency(operation.input_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(operation.input_operand_id);
   const auto* output = GetMojoOperand(operation.output_operand_id);
@@ -695,10 +816,7 @@
   if (!processed_operands_.contains(operation.input_operand_id)) {
     return false;
   }
-  NoteDependency(operation.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(operation.output_operand_id).second);
+  NoteInputDependency(operation.input_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(operation.input_operand_id);
   const auto* output = GetMojoOperand(operation.output_operand_id);
@@ -730,12 +848,9 @@
       !processed_operands_.contains(batch_normalization.variance_operand_id)) {
     return false;
   }
-  NoteDependency(batch_normalization.input_operand_id, operation_id);
-  NoteDependency(batch_normalization.mean_operand_id, operation_id);
-  NoteDependency(batch_normalization.variance_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(batch_normalization.output_operand_id).second);
+  NoteInputDependency(batch_normalization.input_operand_id, operation_id);
+  NoteInputDependency(batch_normalization.mean_operand_id, operation_id);
+  NoteInputDependency(batch_normalization.variance_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(batch_normalization.input_operand_id);
   const auto* mean = GetMojoOperand(batch_normalization.mean_operand_id);
@@ -753,7 +868,7 @@
       // The scale operand is invalid.
       return false;
     }
-    NoteDependency(scale_operand_id.value(), operation_id);
+    NoteInputDependency(scale_operand_id.value(), operation_id);
 
     auto* scale = GetMojoOperand(scale_operand_id.value());
     if (!scale || scale == output) {
@@ -767,7 +882,7 @@
       // The bias operand is invalid.
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
 
     auto* bias = GetMojoOperand(bias_operand_id.value());
     if (!bias || bias == output) {
@@ -798,10 +913,7 @@
   if (!processed_operands_.contains(arg_min_max.input_operand_id)) {
     return false;
   }
-  NoteDependency(arg_min_max.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(arg_min_max.output_operand_id).second);
+  NoteInputDependency(arg_min_max.input_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(arg_min_max.input_operand_id);
   const auto* output = GetMojoOperand(arg_min_max.output_operand_id);
@@ -853,7 +965,7 @@
     if (!processed_operands_.contains(input_operand_id)) {
       return false;
     }
-    NoteDependency(input_operand_id, operation_id);
+    NoteInputDependency(input_operand_id, operation_id);
 
     auto* input = GetMojoOperand(input_operand_id);
     if (!input || input == output) {
@@ -871,7 +983,6 @@
   if (validated_output != output->descriptor) {
     return false;
   }
-  RETURN_IF_FALSE(processed_operands_.insert(concat.output_operand_id).second);
 
   return true;
 }
@@ -882,8 +993,8 @@
       !processed_operands_.contains(conv2d.filter_operand_id)) {
     return false;
   }
-  NoteDependency(conv2d.input_operand_id, operation_id);
-  NoteDependency(conv2d.filter_operand_id, operation_id);
+  NoteInputDependency(conv2d.input_operand_id, operation_id);
+  NoteInputDependency(conv2d.filter_operand_id, operation_id);
 
   auto* input = GetMojoOperand(conv2d.input_operand_id);
   auto* filter = GetMojoOperand(conv2d.filter_operand_id);
@@ -906,7 +1017,7 @@
     if (!processed_operands_.contains(bias_operand_id.value())) {
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
 
     auto* bias = GetMojoOperand(bias_operand_id.value());
     if (!bias || bias == output) {
@@ -915,7 +1026,6 @@
     }
     bias_operand = bias->descriptor;
   }
-  RETURN_IF_FALSE(processed_operands_.insert(conv2d.output_operand_id).second);
 
   std::optional<base::expected<OperandDescriptor, std::string>>
       validated_output;
@@ -953,10 +1063,7 @@
   if (!processed_operands_.contains(cumulative_sum.input_operand_id)) {
     return false;
   }
-  NoteDependency(cumulative_sum.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(cumulative_sum.output_operand_id).second);
+  NoteInputDependency(cumulative_sum.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(cumulative_sum.input_operand_id);
   auto* output = GetMojoOperand(cumulative_sum.output_operand_id);
@@ -988,12 +1095,9 @@
       !processed_operands_.contains(dequantize_linear.zero_point_operand_id)) {
     return false;
   }
-  NoteDependency(dequantize_linear.input_operand_id, operation_id);
-  NoteDependency(dequantize_linear.scale_operand_id, operation_id);
-  NoteDependency(dequantize_linear.zero_point_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(dequantize_linear.output_operand_id).second);
+  NoteInputDependency(dequantize_linear.input_operand_id, operation_id);
+  NoteInputDependency(dequantize_linear.scale_operand_id, operation_id);
+  NoteInputDependency(dequantize_linear.zero_point_operand_id, operation_id);
 
   auto* input = GetMojoOperand(dequantize_linear.input_operand_id);
   auto* output = GetMojoOperand(dequantize_linear.output_operand_id);
@@ -1100,11 +1204,8 @@
       !processed_operands_.contains(operation.rhs_operand_id)) {
     return false;
   }
-  NoteDependency(operation.lhs_operand_id, operation_id);
-  NoteDependency(operation.rhs_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(operation.output_operand_id).second);
+  NoteInputDependency(operation.lhs_operand_id, operation_id);
+  NoteInputDependency(operation.rhs_operand_id, operation_id);
 
   auto* a = GetMojoOperand(operation.lhs_operand_id);
   auto* b = GetMojoOperand(operation.rhs_operand_id);
@@ -1220,9 +1321,7 @@
   if (!processed_operands_.contains(expand.input_operand_id)) {
     return false;
   }
-  NoteDependency(expand.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(expand.output_operand_id).second);
+  NoteInputDependency(expand.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(expand.input_operand_id);
   auto* output = GetMojoOperand(expand.output_operand_id);
@@ -1250,10 +1349,8 @@
       !processed_operands_.contains(gather.indices_operand_id)) {
     return false;
   }
-  NoteDependency(gather.input_operand_id, operation_id);
-  NoteDependency(gather.indices_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(gather.output_operand_id).second);
+  NoteInputDependency(gather.input_operand_id, operation_id);
+  NoteInputDependency(gather.indices_operand_id, operation_id);
 
   auto* input = GetMojoOperand(gather.input_operand_id);
   auto* output = GetMojoOperand(gather.output_operand_id);
@@ -1284,11 +1381,8 @@
       !processed_operands_.contains(gather_elements.indices_operand_id)) {
     return false;
   }
-  NoteDependency(gather_elements.input_operand_id, operation_id);
-  NoteDependency(gather_elements.indices_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(gather_elements.output_operand_id).second);
+  NoteInputDependency(gather_elements.input_operand_id, operation_id);
+  NoteInputDependency(gather_elements.indices_operand_id, operation_id);
 
   auto* input = GetMojoOperand(gather_elements.input_operand_id);
   auto* output = GetMojoOperand(gather_elements.output_operand_id);
@@ -1318,11 +1412,8 @@
       !processed_operands_.contains(gather_nd.indices_operand_id)) {
     return false;
   }
-  NoteDependency(gather_nd.input_operand_id, operation_id);
-  NoteDependency(gather_nd.indices_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(gather_nd.output_operand_id).second);
+  NoteInputDependency(gather_nd.input_operand_id, operation_id);
+  NoteInputDependency(gather_nd.indices_operand_id, operation_id);
 
   auto* input = GetMojoOperand(gather_nd.input_operand_id);
   auto* output = GetMojoOperand(gather_nd.output_operand_id);
@@ -1350,10 +1441,8 @@
       !processed_operands_.contains(gemm.b_operand_id)) {
     return false;
   }
-  NoteDependency(gemm.a_operand_id, operation_id);
-  NoteDependency(gemm.b_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(gemm.output_operand_id).second);
+  NoteInputDependency(gemm.a_operand_id, operation_id);
+  NoteInputDependency(gemm.b_operand_id, operation_id);
 
   auto* a = GetMojoOperand(gemm.a_operand_id);
   auto* b = GetMojoOperand(gemm.b_operand_id);
@@ -1368,7 +1457,7 @@
       // The third operand is invalid.
       return false;
     }
-    NoteDependency(c_operand_id.value(), operation_id);
+    NoteInputDependency(c_operand_id.value(), operation_id);
 
     auto* c = GetMojoOperand(c_operand_id.value());
     if (!c || c == output) {
@@ -1398,9 +1487,9 @@
       !processed_operands_.contains(gru.recurrent_weight_operand_id)) {
     return false;
   }
-  NoteDependency(gru.input_operand_id, operation_id);
-  NoteDependency(gru.weight_operand_id, operation_id);
-  NoteDependency(gru.recurrent_weight_operand_id, operation_id);
+  NoteInputDependency(gru.input_operand_id, operation_id);
+  NoteInputDependency(gru.weight_operand_id, operation_id);
+  NoteInputDependency(gru.recurrent_weight_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(gru.input_operand_id);
   const auto* weight = GetMojoOperand(gru.weight_operand_id);
@@ -1416,7 +1505,7 @@
         !processed_operands_.contains(gru.bias_operand_id)) {
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
   const auto& recurrent_bias_operand_id = gru.recurrent_bias_operand_id;
   if (recurrent_bias_operand_id.has_value()) {
@@ -1424,7 +1513,7 @@
         !processed_operands_.contains(gru.recurrent_bias_operand_id)) {
       return false;
     }
-    NoteDependency(recurrent_bias_operand_id.value(), operation_id);
+    NoteInputDependency(recurrent_bias_operand_id.value(), operation_id);
   }
   const auto& initial_hidden_state_operand_id =
       gru.initial_hidden_state_operand_id;
@@ -1434,7 +1523,7 @@
         !processed_operands_.contains(gru.initial_hidden_state_operand_id)) {
       return false;
     }
-    NoteDependency(initial_hidden_state_operand_id.value(), operation_id);
+    NoteInputDependency(initial_hidden_state_operand_id.value(), operation_id);
   }
 
   for (uint64_t output_operand_id : gru.output_operand_ids) {
@@ -1448,7 +1537,6 @@
         initial_hidden_state_operand_id == output_operand_id) {
       return false;
     }
-    RETURN_IF_FALSE(processed_operands_.insert(output_operand_id).second);
   }
 
   const base::expected<std::vector<OperandDescriptor>, std::string>
@@ -1483,10 +1571,10 @@
       !processed_operands_.contains(gru_cell.hidden_state_operand_id)) {
     return false;
   }
-  NoteDependency(gru_cell.input_operand_id, operation_id);
-  NoteDependency(gru_cell.weight_operand_id, operation_id);
-  NoteDependency(gru_cell.recurrent_weight_operand_id, operation_id);
-  NoteDependency(gru_cell.hidden_state_operand_id, operation_id);
+  NoteInputDependency(gru_cell.input_operand_id, operation_id);
+  NoteInputDependency(gru_cell.weight_operand_id, operation_id);
+  NoteInputDependency(gru_cell.recurrent_weight_operand_id, operation_id);
+  NoteInputDependency(gru_cell.hidden_state_operand_id, operation_id);
 
   const mojom::Operand* input = GetMojoOperand(gru_cell.input_operand_id);
   const mojom::Operand* weight = GetMojoOperand(gru_cell.weight_operand_id);
@@ -1504,7 +1592,7 @@
         !processed_operands_.contains(gru_cell.bias_operand_id)) {
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
   const std::optional<uint32_t>& recurrent_bias_operand_id =
       gru_cell.recurrent_bias_operand_id;
@@ -1513,7 +1601,7 @@
         !processed_operands_.contains(gru_cell.recurrent_bias_operand_id)) {
       return false;
     }
-    NoteDependency(recurrent_bias_operand_id.value(), operation_id);
+    NoteInputDependency(recurrent_bias_operand_id.value(), operation_id);
   }
 
   if (gru_cell.output_operand_id == gru_cell.input_operand_id ||
@@ -1524,8 +1612,6 @@
       gru_cell.output_operand_id == recurrent_bias_operand_id) {
     return false;
   }
-  RETURN_IF_FALSE(
-      processed_operands_.insert(gru_cell.output_operand_id).second);
 
   const base::expected<OperandDescriptor, std::string> validated_output =
       ValidateGruCellAndInferOutput(
@@ -1570,10 +1656,7 @@
   if (!processed_operands_.contains(layer_normalization.input_operand_id)) {
     return false;
   }
-  NoteDependency(layer_normalization.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(layer_normalization.output_operand_id).second);
+  NoteInputDependency(layer_normalization.input_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(layer_normalization.input_operand_id);
   const auto* output = GetMojoOperand(layer_normalization.output_operand_id);
@@ -1590,7 +1673,7 @@
       // The scale operand is invalid.
       return false;
     }
-    NoteDependency(scale_operand_id.value(), operation_id);
+    NoteInputDependency(scale_operand_id.value(), operation_id);
   }
   const auto& bias_operand_id = layer_normalization.bias_operand_id;
   if (bias_operand_id) {
@@ -1600,7 +1683,7 @@
       // The bias operand is invalid.
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
 
   const base::expected<OperandDescriptor, std::string> validated_output =
@@ -1654,9 +1737,9 @@
       !processed_operands_.contains(lstm.recurrent_weight_operand_id)) {
     return false;
   }
-  NoteDependency(lstm.input_operand_id, operation_id);
-  NoteDependency(lstm.weight_operand_id, operation_id);
-  NoteDependency(lstm.recurrent_weight_operand_id, operation_id);
+  NoteInputDependency(lstm.input_operand_id, operation_id);
+  NoteInputDependency(lstm.weight_operand_id, operation_id);
+  NoteInputDependency(lstm.recurrent_weight_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(lstm.input_operand_id);
   const auto* weight = GetMojoOperand(lstm.weight_operand_id);
@@ -1672,7 +1755,7 @@
         !processed_operands_.contains(lstm.bias_operand_id)) {
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
   const auto& recurrent_bias_operand_id = lstm.recurrent_bias_operand_id;
   if (recurrent_bias_operand_id.has_value()) {
@@ -1680,7 +1763,7 @@
         !processed_operands_.contains(lstm.recurrent_bias_operand_id)) {
       return false;
     }
-    NoteDependency(recurrent_bias_operand_id.value(), operation_id);
+    NoteInputDependency(recurrent_bias_operand_id.value(), operation_id);
   }
   const auto& peephole_weight_operand_id = lstm.peephole_weight_operand_id;
   if (peephole_weight_operand_id.has_value()) {
@@ -1688,7 +1771,7 @@
         !processed_operands_.contains(lstm.peephole_weight_operand_id)) {
       return false;
     }
-    NoteDependency(peephole_weight_operand_id.value(), operation_id);
+    NoteInputDependency(peephole_weight_operand_id.value(), operation_id);
   }
   const auto& initial_hidden_state_operand_id =
       lstm.initial_hidden_state_operand_id;
@@ -1698,7 +1781,7 @@
         !processed_operands_.contains(lstm.initial_hidden_state_operand_id)) {
       return false;
     }
-    NoteDependency(initial_hidden_state_operand_id.value(), operation_id);
+    NoteInputDependency(initial_hidden_state_operand_id.value(), operation_id);
   }
   const auto& initial_cell_state_operand_id =
       lstm.initial_cell_state_operand_id;
@@ -1707,7 +1790,7 @@
         !processed_operands_.contains(lstm.initial_cell_state_operand_id)) {
       return false;
     }
-    NoteDependency(initial_cell_state_operand_id.value(), operation_id);
+    NoteInputDependency(initial_cell_state_operand_id.value(), operation_id);
   }
 
   for (uint64_t output_operand_id : lstm.output_operand_ids) {
@@ -1721,7 +1804,6 @@
         output_operand_id == lstm.initial_cell_state_operand_id) {
       return false;
     }
-    RETURN_IF_FALSE(processed_operands_.insert(output_operand_id).second);
   }
 
   const base::expected<std::vector<OperandDescriptor>, std::string>
@@ -1758,11 +1840,11 @@
       !processed_operands_.contains(lstm_cell.cell_state_operand_id)) {
     return false;
   }
-  NoteDependency(lstm_cell.input_operand_id, operation_id);
-  NoteDependency(lstm_cell.weight_operand_id, operation_id);
-  NoteDependency(lstm_cell.recurrent_weight_operand_id, operation_id);
-  NoteDependency(lstm_cell.hidden_state_operand_id, operation_id);
-  NoteDependency(lstm_cell.cell_state_operand_id, operation_id);
+  NoteInputDependency(lstm_cell.input_operand_id, operation_id);
+  NoteInputDependency(lstm_cell.weight_operand_id, operation_id);
+  NoteInputDependency(lstm_cell.recurrent_weight_operand_id, operation_id);
+  NoteInputDependency(lstm_cell.hidden_state_operand_id, operation_id);
+  NoteInputDependency(lstm_cell.cell_state_operand_id, operation_id);
 
   const mojom::Operand* input = GetMojoOperand(lstm_cell.input_operand_id);
   const mojom::Operand* weight = GetMojoOperand(lstm_cell.weight_operand_id);
@@ -1782,7 +1864,7 @@
         !processed_operands_.contains(bias_operand_id.value())) {
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
   const std::optional<uint64_t> recurrent_bias_operand_id =
       lstm_cell.recurrent_bias_operand_id;
@@ -1791,7 +1873,7 @@
         !processed_operands_.contains(recurrent_bias_operand_id.value())) {
       return false;
     }
-    NoteDependency(recurrent_bias_operand_id.value(), operation_id);
+    NoteInputDependency(recurrent_bias_operand_id.value(), operation_id);
   }
   const std::optional<uint64_t> peephole_weight_operand_id =
       lstm_cell.peephole_weight_operand_id;
@@ -1800,7 +1882,7 @@
         !processed_operands_.contains(peephole_weight_operand_id.value())) {
       return false;
     }
-    NoteDependency(peephole_weight_operand_id.value(), operation_id);
+    NoteInputDependency(peephole_weight_operand_id.value(), operation_id);
   }
 
   for (uint64_t output_operand_id : lstm_cell.output_operand_ids) {
@@ -1814,7 +1896,6 @@
         output_operand_id == lstm_cell.peephole_weight_operand_id) {
       return false;
     }
-    RETURN_IF_FALSE(processed_operands_.insert(output_operand_id).second);
   }
 
   const base::expected<std::vector<webnn::OperandDescriptor>, std::string>
@@ -1849,11 +1930,7 @@
   if (!processed_operands_.contains(instance_normalization.input_operand_id)) {
     return false;
   }
-  NoteDependency(instance_normalization.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(instance_normalization.output_operand_id)
-          .second);
+  NoteInputDependency(instance_normalization.input_operand_id, operation_id);
 
   const auto* input = GetMojoOperand(instance_normalization.input_operand_id);
   const auto* output = GetMojoOperand(instance_normalization.output_operand_id);
@@ -1869,7 +1946,7 @@
       // The scale operand is invalid.
       return false;
     }
-    NoteDependency(scale_operand_id.value(), operation_id);
+    NoteInputDependency(scale_operand_id.value(), operation_id);
   }
   const auto& bias_operand_id = instance_normalization.bias_operand_id;
   if (bias_operand_id) {
@@ -1879,7 +1956,7 @@
       // The bias operand is invalid.
       return false;
     }
-    NoteDependency(bias_operand_id.value(), operation_id);
+    NoteInputDependency(bias_operand_id.value(), operation_id);
   }
 
   const base::expected<OperandDescriptor, std::string> validated_output =
@@ -1904,10 +1981,8 @@
       !processed_operands_.contains(matmul.b_operand_id)) {
     return false;
   }
-  NoteDependency(matmul.a_operand_id, operation_id);
-  NoteDependency(matmul.b_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(matmul.output_operand_id).second);
+  NoteInputDependency(matmul.a_operand_id, operation_id);
+  NoteInputDependency(matmul.b_operand_id, operation_id);
 
   auto* a = GetMojoOperand(matmul.a_operand_id);
   auto* b = GetMojoOperand(matmul.b_operand_id);
@@ -1934,9 +2009,7 @@
   if (!processed_operands_.contains(pad.input_operand_id)) {
     return false;
   }
-  NoteDependency(pad.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(pad.output_operand_id).second);
+  NoteInputDependency(pad.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(pad.input_operand_id);
   auto* output = GetMojoOperand(pad.output_operand_id);
@@ -1964,9 +2037,7 @@
   if (!processed_operands_.contains(pool2d.input_operand_id)) {
     return false;
   }
-  NoteDependency(pool2d.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(pool2d.output_operand_id).second);
+  NoteInputDependency(pool2d.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(pool2d.input_operand_id);
   auto* output = GetMojoOperand(pool2d.output_operand_id);
@@ -1999,10 +2070,8 @@
       !processed_operands_.contains(prelu.slope_operand_id)) {
     return false;
   }
-  NoteDependency(prelu.input_operand_id, operation_id);
-  NoteDependency(prelu.slope_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(prelu.output_operand_id).second);
+  NoteInputDependency(prelu.input_operand_id, operation_id);
+  NoteInputDependency(prelu.slope_operand_id, operation_id);
 
   auto* input = GetMojoOperand(prelu.input_operand_id);
   auto* output = GetMojoOperand(prelu.output_operand_id);
@@ -2033,12 +2102,9 @@
       !processed_operands_.contains(quantize_linear.zero_point_operand_id)) {
     return false;
   }
-  NoteDependency(quantize_linear.input_operand_id, operation_id);
-  NoteDependency(quantize_linear.scale_operand_id, operation_id);
-  NoteDependency(quantize_linear.zero_point_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(quantize_linear.output_operand_id).second);
+  NoteInputDependency(quantize_linear.input_operand_id, operation_id);
+  NoteInputDependency(quantize_linear.scale_operand_id, operation_id);
+  NoteInputDependency(quantize_linear.zero_point_operand_id, operation_id);
 
   auto* input = GetMojoOperand(quantize_linear.input_operand_id);
   auto* output = GetMojoOperand(quantize_linear.output_operand_id);
@@ -2070,10 +2136,7 @@
   if (!processed_operands_.contains(resample2d.input_operand_id)) {
     return false;
   }
-  NoteDependency(resample2d.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(resample2d.output_operand_id).second);
+  NoteInputDependency(resample2d.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(resample2d.input_operand_id);
   auto* output = GetMojoOperand(resample2d.output_operand_id);
@@ -2134,9 +2197,7 @@
   if (!processed_operands_.contains(reshape.input_operand_id)) {
     return false;
   }
-  NoteDependency(reshape.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(reshape.output_operand_id).second);
+  NoteInputDependency(reshape.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(reshape.input_operand_id);
   auto* output = GetMojoOperand(reshape.output_operand_id);
@@ -2166,9 +2227,7 @@
   if (!processed_operands_.contains(reverse.input_operand_id)) {
     return false;
   }
-  NoteDependency(reverse.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(reverse.output_operand_id).second);
+  NoteInputDependency(reverse.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(reverse.input_operand_id);
   auto* output = GetMojoOperand(reverse.output_operand_id);
@@ -2197,12 +2256,9 @@
       !processed_operands_.contains(scatter_elements.updates_operand_id)) {
     return false;
   }
-  NoteDependency(scatter_elements.input_operand_id, operation_id);
-  NoteDependency(scatter_elements.indices_operand_id, operation_id);
-  NoteDependency(scatter_elements.updates_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(scatter_elements.output_operand_id).second);
+  NoteInputDependency(scatter_elements.input_operand_id, operation_id);
+  NoteInputDependency(scatter_elements.indices_operand_id, operation_id);
+  NoteInputDependency(scatter_elements.updates_operand_id, operation_id);
 
   auto* input = GetMojoOperand(scatter_elements.input_operand_id);
   auto* indices = GetMojoOperand(scatter_elements.indices_operand_id);
@@ -2235,12 +2291,9 @@
       !processed_operands_.contains(scatter_nd.updates_operand_id)) {
     return false;
   }
-  NoteDependency(scatter_nd.input_operand_id, operation_id);
-  NoteDependency(scatter_nd.indices_operand_id, operation_id);
-  NoteDependency(scatter_nd.updates_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(scatter_nd.output_operand_id).second);
+  NoteInputDependency(scatter_nd.input_operand_id, operation_id);
+  NoteInputDependency(scatter_nd.indices_operand_id, operation_id);
+  NoteInputDependency(scatter_nd.updates_operand_id, operation_id);
 
   auto* input = GetMojoOperand(scatter_nd.input_operand_id);
   auto* indices = GetMojoOperand(scatter_nd.indices_operand_id);
@@ -2270,9 +2323,7 @@
   if (!processed_operands_.contains(slice.input_operand_id)) {
     return false;
   }
-  NoteDependency(slice.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(slice.output_operand_id).second);
+  NoteInputDependency(slice.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(slice.input_operand_id);
   auto* output = GetMojoOperand(slice.output_operand_id);
@@ -2300,9 +2351,7 @@
   if (!processed_operands_.contains(softmax.input_operand_id)) {
     return false;
   }
-  NoteDependency(softmax.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(softmax.output_operand_id).second);
+  NoteInputDependency(softmax.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(softmax.input_operand_id);
   auto* output = GetMojoOperand(softmax.output_operand_id);
@@ -2328,7 +2377,7 @@
   if (!processed_operands_.contains(split.input_operand_id)) {
     return false;
   }
-  NoteDependency(split.input_operand_id, operation_id);
+  NoteInputDependency(split.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(split.input_operand_id);
   if (!input) {
@@ -2347,7 +2396,6 @@
       return false;
     }
     splits.push_back(output->descriptor.shape()[split.axis]);
-    RETURN_IF_FALSE(processed_operands_.insert(output_id).second);
   }
 
   const base::expected<std::vector<OperandDescriptor>, std::string>
@@ -2379,9 +2427,7 @@
   if (!processed_operands_.contains(tile.input_operand_id)) {
     return false;
   }
-  NoteDependency(tile.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(tile.output_operand_id).second);
+  NoteInputDependency(tile.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(tile.input_operand_id);
   auto* output = GetMojoOperand(tile.output_operand_id);
@@ -2409,10 +2455,7 @@
   if (!processed_operands_.contains(transpose.input_operand_id)) {
     return false;
   }
-  NoteDependency(transpose.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(transpose.output_operand_id).second);
+  NoteInputDependency(transpose.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(transpose.input_operand_id);
   auto* output = GetMojoOperand(transpose.output_operand_id);
@@ -2440,10 +2483,7 @@
   if (!processed_operands_.contains(triangular.input_operand_id)) {
     return false;
   }
-  NoteDependency(triangular.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(
-      processed_operands_.insert(triangular.output_operand_id).second);
+  NoteInputDependency(triangular.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(triangular.input_operand_id);
   auto* output = GetMojoOperand(triangular.output_operand_id);
@@ -2472,11 +2512,9 @@
       !processed_operands_.contains(where.false_value_operand_id)) {
     return false;
   }
-  NoteDependency(where.condition_operand_id, operation_id);
-  NoteDependency(where.true_value_operand_id, operation_id);
-  NoteDependency(where.false_value_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(where.output_operand_id).second);
+  NoteInputDependency(where.condition_operand_id, operation_id);
+  NoteInputDependency(where.true_value_operand_id, operation_id);
+  NoteInputDependency(where.false_value_operand_id, operation_id);
 
   auto* condition = GetMojoOperand(where.condition_operand_id);
   auto* true_value = GetMojoOperand(where.true_value_operand_id);
@@ -2507,9 +2545,7 @@
   if (!processed_operands_.contains(reduce.input_operand_id)) {
     return false;
   }
-  NoteDependency(reduce.input_operand_id, operation_id);
-
-  RETURN_IF_FALSE(processed_operands_.insert(reduce.output_operand_id).second);
+  NoteInputDependency(reduce.input_operand_id, operation_id);
 
   auto* input = GetMojoOperand(reduce.input_operand_id);
   auto* output = GetMojoOperand(reduce.output_operand_id);
@@ -2535,6 +2571,7 @@
 bool OperationValidationContext::ValidateOperation(
     const mojom::Operation& operation,
     size_t operation_id) {
+  RETURN_IF_FALSE(NoteOutputDependency(operation, operation_id));
   switch (operation.which()) {
     case mojom::Operation::Tag::kArgMinMax:
       return ValidateArgMinMax(*operation.get_arg_min_max(), operation_id);
@@ -2970,29 +3007,26 @@
   }
 
   // Validate the operations which are sorted in the topological order.
-  std::optional<std::pair<base::flat_set<uint64_t>, DependentOperationsMap>>
-      result = OperationValidationContext::ValidateOperationsAndGetDependencies(
+  std::optional<OperationValidationContext::ValidationResult> result =
+      OperationValidationContext::ValidateOperationsAndGetDependencies(
           graph_info.operations, context_properties,
           graph_info.id_to_operand_map, processed_operands);
   if (!result.has_value()) {
     return std::nullopt;
   }
 
-  DependentOperationsMap operands_to_dependent_operations;
-  std::tie(processed_operands, operands_to_dependent_operations) =
-      *std::move(result);
 
   // Now that all the operations have been processed we can check that all the
   // operands are connected to the graph inputs and outputs.
   for (auto& [id, operand] : graph_info.id_to_operand_map) {
     if (operand->kind == mojom::Operand::Kind::kOutput && operand->name) {
       // Graph outputs must be the output of some operator.
-      if (!processed_operands.contains(id)) {
+      if (!result->processed_operands.contains(id)) {
         return std::nullopt;
       }
     } else {
       // All other operands must be the input to some operator.
-      if (!operands_to_dependent_operations.contains(id)) {
+      if (!result->operand_to_dependent_operations.contains(id)) {
         return std::nullopt;
       }
     }
@@ -3001,7 +3035,8 @@
   return ValidateGraphSuccessResult{
       WebNNGraphImpl::ComputeResourceInfo(
           std::move(inputs), std::move(outputs),
-          std::move(operands_to_dependent_operations),
+          std::move(result->operand_to_dependent_operations),
+          std::move(result->operand_to_producing_operation),
           base::PassKey<WebNNGraphBuilderImpl>()),
       std::move(graph_constants)};
 }
diff --git a/services/webnn/webnn_graph_impl.cc b/services/webnn/webnn_graph_impl.cc
index 354e3f4..f28ae2e 100644
--- a/services/webnn/webnn_graph_impl.cc
+++ b/services/webnn/webnn_graph_impl.cc
@@ -70,11 +70,14 @@
     base::flat_map<std::string, OperandDescriptor> output_names_to_descriptors,
     base::flat_map<uint64_t, base::flat_set<size_t>>
         operand_to_dependent_operations,
+    base::flat_map<uint64_t, size_t> operand_to_producing_operation,
     base::PassKey<WebNNGraphBuilderImpl> pass_key)
     : input_names_to_descriptors(std::move(input_names_to_descriptors)),
       output_names_to_descriptors(std::move(output_names_to_descriptors)),
       operand_to_dependent_operations(
-          std::move(operand_to_dependent_operations)) {}
+          std::move(operand_to_dependent_operations)),
+      operand_to_producing_operation(
+          std::move(operand_to_producing_operation)) {}
 
 WebNNGraphImpl::ComputeResourceInfo::ComputeResourceInfo(
     ComputeResourceInfo&&) = default;
diff --git a/services/webnn/webnn_graph_impl.h b/services/webnn/webnn_graph_impl.h
index 5e3615c1..9e7d693 100644
--- a/services/webnn/webnn_graph_impl.h
+++ b/services/webnn/webnn_graph_impl.h
@@ -28,13 +28,15 @@
  public:
   // Describes the constraints of a graph's inputs and outputs.
   struct COMPONENT_EXPORT(WEBNN_SERVICE) ComputeResourceInfo {
-    ComputeResourceInfo(base::flat_map<std::string, OperandDescriptor>
-                            input_names_to_descriptors,
-                        base::flat_map<std::string, OperandDescriptor>
-                            output_names_to_descriptors,
-                        base::flat_map<uint64_t, base::flat_set<size_t>>
-                            operand_to_dependent_operations,
-                        base::PassKey<WebNNGraphBuilderImpl> pass_key);
+    ComputeResourceInfo(
+        base::flat_map<std::string, OperandDescriptor>
+            input_names_to_descriptors,
+        base::flat_map<std::string, OperandDescriptor>
+            output_names_to_descriptors,
+        base::flat_map<uint64_t, base::flat_set<size_t>>
+            operand_to_dependent_operations,
+        base::flat_map<uint64_t, size_t> operand_to_producing_operation,
+        base::PassKey<WebNNGraphBuilderImpl> pass_key);
     ~ComputeResourceInfo();
 
     ComputeResourceInfo(const ComputeResourceInfo&) = delete;
@@ -47,6 +49,7 @@
     base::flat_map<std::string, OperandDescriptor> output_names_to_descriptors;
     base::flat_map<uint64_t, base::flat_set<size_t>>
         operand_to_dependent_operations;
+    base::flat_map<uint64_t, size_t> operand_to_producing_operation;
   };
 
   // Constructs a graph where the receiever and implementation is owned by the
diff --git a/sql/fuzzers/recovery_lpm_fuzzer.cc b/sql/fuzzers/recovery_lpm_fuzzer.cc
index d7b70eb4..91659eb 100644
--- a/sql/fuzzers/recovery_lpm_fuzzer.cc
+++ b/sql/fuzzers/recovery_lpm_fuzzer.cc
@@ -35,8 +35,8 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
+#include "base/logging/log_severity.h"
 #include "base/strings/cstring_view.h"
-#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -127,13 +127,6 @@
   // The path the database is copied to after it's been mutated.
   const base::FilePath& out_db_path() const { return out_db_path_; }
 
-  // Deletes the backing file and related journal files.
-  void DeleteDbFiles() const {
-    CHECK(base::DeleteFile(GetTempFilePath("db.sqlite")));
-    CHECK(base::DeleteFile(GetTempFilePath("db.sqlite-journal")));
-    CHECK(base::DeleteFile(GetTempFilePath("db.sqlite-wal")));
-  }
-
   void AssertTempDirIsEmpty() const {
     if (base::IsDirectoryEmpty(temp_dir_.GetPath())) {
       return;
@@ -354,8 +347,9 @@
     database.Close();
   }
 
-  // Delete the backing file to prepare for the next iteration.
-  env.DeleteDbFiles();
+  // Delete the backing file and related journal files so the next iteration
+  // starts with a clean slate.
+  CHECK(database.Delete(env.db_path()));
   // Ensure that no unexpected files were created in the temp directory.
   env.AssertTempDirIsEmpty();
 }
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index c874bff..d6a9586d 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1418,6 +1418,55 @@
       }
     ]
   },
+  "mac-m3-pro-perf": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "-v",
+          "-v",
+          "--browser=builder",
+          "--upload-results",
+          "--test-shard-map-filename=mac-m3-pro-perf_map.json",
+          "--ignore-benchmark-exit-code",
+          "--assert-gpu-compositing"
+        ],
+        "merge": {
+          "args": [
+            "--upload-skia-json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "performance_test_suite",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimensions": {
+            "cpu": "arm",
+            "mac_model": "Mac15,3",
+            "os": "Mac",
+            "pool": "chrome.tests.perf",
+            "synthetic_product_name": "Mac15,3_arm64-64-Apple_M3_apple m3_8192_APPLE SSD AP0512Z"
+          },
+          "expiration": 7200,
+          "hard_timeout": 14400,
+          "io_timeout": 21600,
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 4
+        },
+        "test": "performance_test_suite",
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      }
+    ]
+  },
   "win-10-perf": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/chromium.perf.pinpoint.json b/testing/buildbot/chromium.perf.pinpoint.json
index 9150189..e33ee65 100644
--- a/testing/buildbot/chromium.perf.pinpoint.json
+++ b/testing/buildbot/chromium.perf.pinpoint.json
@@ -1153,6 +1153,55 @@
       }
     ]
   },
+  "mac-m3-pro-perf": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "-v",
+          "-v",
+          "--browser=builder",
+          "--upload-results",
+          "--test-shard-map-filename=mac-m3-pro-perf_map.json",
+          "--ignore-benchmark-exit-code",
+          "--assert-gpu-compositing"
+        ],
+        "merge": {
+          "args": [
+            "--upload-skia-json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "performance_test_suite",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimensions": {
+            "cpu": "arm",
+            "mac_model": "Mac15,3",
+            "os": "Mac",
+            "pool": "chrome.tests.perf",
+            "synthetic_product_name": "Mac15,3_arm64-64-Apple_M3_apple m3_8192_APPLE SSD AP0512Z"
+          },
+          "expiration": 7200,
+          "hard_timeout": 14400,
+          "io_timeout": 21600,
+          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 4
+        },
+        "test": "performance_test_suite",
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "requires_simultaneous_shard_dispatch": true,
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      }
+    ]
+  },
   "win-10-perf": {
     "isolated_scripts": [
       {
diff --git a/testing/scripts/check_static_initializers.py b/testing/scripts/check_static_initializers.py
index 462cba35..0433827 100755
--- a/testing/scripts/check_static_initializers.py
+++ b/testing/scripts/check_static_initializers.py
@@ -33,9 +33,9 @@
         'iostream\\.cpp : _GLOBAL__I_000100',
 
         # TODO(crbug.com/40268361): Rust stdlib argv handling.
-        # https://github.com/rust-lang/rust/blob/b08148f6a76010ea3d4e91d61245aa7aac59e4b4/library/std/src/sys/unix/args.rs#L107-L127
+        # https://github.com/rust-lang/rust/blob/6bc57c6bf7d0024ad9ea5a2c112f3fc9c383c8a4/library/std/src/sys/args/unix.rs#L124
         # https://github.com/rust-lang/rust/issues/111921
-        '.* : std::sys::pal::unix::args::imp::ARGV_INIT_ARRAY::init_wrapper',
+        '.* : std::sys::args::unix::imp::ARGV_INIT_ARRAY::init_wrapper',
 
         # Added by libgcc due to USE_EH_FRAME_REGISTRY.
         'crtstuff\\.c : frame_dummy',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index a7f0bfa..45191ad 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -579,27 +579,28 @@
             ]
         }
     ],
-    "AndroidSpareRendererCreation_V2": [
+    "AndroidSpareRendererCreation_V3": [
         {
             "platforms": [
                 "android"
             ],
             "experiments": [
                 {
-                    "name": "CreateByDefault_AfterLoading",
+                    "name": "CreateWithoutServiceGroupImportance",
                     "params": {
                         "kill_when_backgrounded": "true",
-                        "lowest-ranking": "false",
-                        "not-perceptible-binding": "true",
+                        "omnibox_spare_renderer_delay_ms": "500",
+                        "spare_renderer_creation_delay_ms": "2000",
                         "spare_renderer_creation_timing": "after-loading",
                         "spare_renderer_timeout_seconds": "60"
                     },
                     "enable_features": [
                         "AndroidWarmUpSpareRendererWithTimeout",
-                        "SpareRendererProcessPriority"
+                        "OverrideAndroidOmniboxSpareRendererDelay"
                     ],
                     "disable_features": [
-                        "OverrideAndroidOmniboxSpareRendererDelay"
+                        "ServiceGroupImportance",
+                        "SpareRendererProcessPriority"
                     ]
                 }
             ]
@@ -668,7 +669,7 @@
             ]
         }
     ],
-    "AndroidUseFrameIntervalDeciderNewAndroidFeatures": [
+    "AndroidUseFrameIntervalDeciderAdaptiveFrameRate": [
         {
             "platforms": [
                 "android"
@@ -677,7 +678,7 @@
                 {
                     "name": "Enabled",
                     "enable_features": [
-                        "UseFrameIntervalDeciderNewAndroidFeatures"
+                        "UseFrameIntervalDeciderAdaptiveFrameRate"
                     ]
                 }
             ]
@@ -11450,6 +11451,21 @@
             ]
         }
     ],
+    "HeadlessTabModel": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "HeadlessTabModel"
+                    ]
+                }
+            ]
+        }
+    ],
     "HeapProfilerExcludeChromeOSRenderers": [
         {
             "platforms": [
@@ -12154,6 +12170,21 @@
             ]
         }
     ],
+    "IOSEnterpriseRealtimeEventReporting": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "EnterpriseRealtimeEventReportingOnIOS"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSExplicitUITraitRegistration": [
         {
             "platforms": [
@@ -12481,6 +12512,21 @@
             ]
         }
     ],
+    "IOSOneTapMiniMapRemoveSectionsBreaks": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "IOSOneTapMiniMapRemoveSectionsBreaks"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSOverflowMenuCustomization": [
         {
             "platforms": [
@@ -17699,8 +17745,8 @@
             ],
             "experiments": [
                 {
-                    "name": "Disabled",
-                    "disable_features": [
+                    "name": "Enabled",
+                    "enable_features": [
                         "PermissionsAIv1"
                     ]
                 }
@@ -19026,6 +19072,27 @@
             ]
         }
     ],
+    "PrivateAggregationApiErrorReporting": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "fuchsia",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PrivateAggregationApiErrorReporting"
+                    ]
+                }
+            ]
+        }
+    ],
     "PrivateStateTokens": [
         {
             "platforms": [
@@ -19126,6 +19193,53 @@
             ]
         }
     ],
+    "ProcessRankPolicyAndroid": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "EnabledAll",
+                    "enable_features": [
+                        "ChangeUnfocusedPriority",
+                        "ProcessRankPolicyAndroid",
+                        "ProtectedTabsAndroid"
+                    ]
+                },
+                {
+                    "name": "EnabledProcessRankPolicyAndroid",
+                    "enable_features": [
+                        "ProcessRankPolicyAndroid"
+                    ],
+                    "disable_features": [
+                        "ChangeUnfocusedPriority",
+                        "ProtectedTabsAndroid"
+                    ]
+                },
+                {
+                    "name": "EnabledChangeUnfocusedPriority",
+                    "enable_features": [
+                        "ChangeUnfocusedPriority"
+                    ],
+                    "disable_features": [
+                        "ProcessRankPolicyAndroid",
+                        "ProtectedTabsAndroid"
+                    ]
+                },
+                {
+                    "name": "EnabledProtectedTabsAndroid",
+                    "enable_features": [
+                        "ProcessRankPolicyAndroid",
+                        "ProtectedTabsAndroid"
+                    ],
+                    "disable_features": [
+                        "ChangeUnfocusedPriority"
+                    ]
+                }
+            ]
+        }
+    ],
     "ProcessReuseOnPrerenderCOOPSwapAndroid": [
         {
             "platforms": [
@@ -22854,21 +22968,6 @@
             ]
         }
     ],
-    "ServiceGroupImportance": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Disabled",
-                    "disable_features": [
-                        "ServiceGroupImportance"
-                    ]
-                }
-            ]
-        }
-    ],
     "ServiceWorkerAutoPreload": [
         {
             "platforms": [
@@ -24217,7 +24316,7 @@
             ]
         }
     ],
-    "TabGroupSuggestion": [
+    "TabGroupSuggestionMetricsOnly": [
         {
             "platforms": [
                 "android"
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index bfa2757c..d2ed9df 100644
--- a/third_party/androidx/build.gradle
+++ b/third_party/androidx/build.gradle
@@ -303,7 +303,7 @@
     google()
     maven {
         // This URL is generated by the fetch_all_androidx.py script.
-        url 'https://androidx.dev/snapshots/builds/13405995/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/13408113/artifacts/repository'
     }
     mavenCentral()
 }
diff --git a/third_party/angle b/third_party/angle
index 34d3091..99eb1ce 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 34d30914048ac98a6f50f84aa630cc285b75bc79
+Subproject commit 99eb1ceb5895d57a8859447411f4ccf68c2038d9
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index 9e87b73..e67ff64 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -37,6 +37,7 @@
     "+media/base/media_content_type.h",
     "+media/base/media_log.h",
     "+media/base/output_device_info.h",
+    "+media/base/picture_in_picture_events_info.h",
     "+media/base/stream_parser.h",
     "+media/base/video_frame.h",
     "+media/base/video_frame_metadata.h",
diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h
index fbfd882..d5f8ad70 100644
--- a/third_party/blink/public/platform/web_media_player.h
+++ b/third_party/blink/public/platform/web_media_player.h
@@ -37,6 +37,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "components/viz/common/surfaces/surface_id.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_metadata.h"
 #include "third_party/blink/public/platform/web_audio_source_provider_impl.h"
@@ -452,7 +453,8 @@
   // information. This information helps identify why a request to enter picture
   // in picture automatically is denied/accepted.
   virtual void RecordAutoPictureInPictureInfo(
-      const WebString& auto_picture_in_picture_info) = 0;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/web/modules/mediastream/web_media_player_ms.h b/third_party/blink/public/web/modules/mediastream/web_media_player_ms.h
index 937cbcc..12ea7db 100644
--- a/third_party/blink/public/web/modules/mediastream/web_media_player_ms.h
+++ b/third_party/blink/public/web/modules/mediastream/web_media_player_ms.h
@@ -219,7 +219,8 @@
   void UnregisterFrameSinkHierarchy() override;
 
   void RecordAutoPictureInPictureInfo(
-      const WebString& auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
  private:
   friend class WebMediaPlayerMSTest;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
index 7e1b7a7..644e136 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
@@ -61,9 +61,8 @@
 v8::Local<v8::Value> V8ThrowDOMException::AttachStackProperty(
     v8::Isolate* isolate,
     DOMException* dom_exception) {
-  if (isolate->IsExecutionTerminating() || !isolate->InContext()) {
+  if (isolate->IsExecutionTerminating())
     return v8::Local<v8::Value>();
-  }
 
   // We use the isolate's current context here because we are creating an
   // exception object.
diff --git a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
index 418665a..2207976c3 100644
--- a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
+++ b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
@@ -78,7 +78,7 @@
       if (const auto* number_value = DynamicTo<CSSNumericLiteralValue>(value)) {
         if (number_value->IsNumber()) {
           return MakeGarbageCollected<CompositorKeyframeDouble>(
-              number_value->GetFloatValue());
+              number_value->GetDoubleValue());
         }
       }
 
diff --git a/third_party/blink/renderer/core/css/css_basic_shape_values.cc b/third_party/blink/renderer/core/css/css_basic_shape_values.cc
index 341a04c8..45332ff 100644
--- a/third_party/blink/renderer/core/css/css_basic_shape_values.cc
+++ b/third_party/blink/renderer/core/css/css_basic_shape_values.cc
@@ -659,10 +659,10 @@
   // The spec requires non-negative width and height but we can only validate
   // numeric literals here.
   if (width_->IsNumericLiteralValue()) {
-    DCHECK_GE(To<CSSNumericLiteralValue>(*width_).GetFloatValue(), 0);
+    DCHECK_GE(To<CSSNumericLiteralValue>(*width_).GetDoubleValue(), 0);
   }
   if (height_->IsNumericLiteralValue()) {
-    DCHECK_GE(To<CSSNumericLiteralValue>(*height_).GetFloatValue(), 0);
+    DCHECK_GE(To<CSSNumericLiteralValue>(*height_).GetDoubleValue(), 0);
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index 23830e4..a7ed20c 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -3074,8 +3074,9 @@
 
         auto stream_name = To<CSSIdentifierValue>(stream_name_percent->Item(0))
                                .ConvertTo<TimelineOffset::NamedRange>();
-        auto percent = To<CSSNumericLiteralValue>(stream_name_percent->Item(1))
-                           .GetFloatValue();
+        double percent =
+            To<CSSNumericLiteralValue>(stream_name_percent->Item(1))
+                .GetDoubleValue();
         result->push_back(KeyframeOffset(stream_name, percent / 100.0));
       }
     } else {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 305b7ba..3c8ae19 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -670,7 +670,10 @@
     }
   }
   // Add all non-reading flow items at the end of the reading flow.
-  for (Node& child : FlatTreeTraversal::ChildrenOf(*this)) {
+  // We use LayoutTreeBuilder traversal to make sure all pseudo elements
+  // (including scroll markers) are accounted for.
+  for (Node* child = LayoutTreeBuilderTraversal::FirstChild(*this); child;
+       child = LayoutTreeBuilderTraversal::NextSibling(*child)) {
     // TODO(dizhangg) this check is O(n^2)
     if (!children.Contains(child)) {
       children.push_back(child);
@@ -10827,9 +10830,6 @@
 }
 
 void Element::ScheduleInterestLostTask() {
-  // This should be called on an interest invoker only.
-  auto* target = InterestTargetElement();
-  CHECK(target);
   const ComputedStyle* style =
       ComputedStyle::NullifyEnsured(GetComputedStyle());
   if (!style) {
@@ -10852,7 +10852,8 @@
           [](Element* invoker, Element* target) {
             GainOrLoseInterest(invoker, target, InterestState::kNoInterest);
           },
-          WrapWeakPersistent(this), WrapWeakPersistent(target)),
+          WrapWeakPersistent(this),
+          WrapWeakPersistent(InterestTargetElement())),
       base::Seconds(hide_delay_seconds)));
 }
 
@@ -10955,13 +10956,14 @@
   } else {
     DCHECK(source == InterestTargetSource::kDeHover ||
            source == InterestTargetSource::kBlurElementChain);
-    if (invoker_data && invoker_data->GetInterestState() !=
-                            InterestState::kNoInterest) [[unlikely]] {
-      // This is an active interest invoker which was just de-hovered or
-      // blurred. Cancel any pending InterestGained tasks, and schedule an
-      // InterestLost task if needed.
+    if (invoker_data) [[unlikely]] {
+      // This is an interest invoker which was just de-hovered or blurred.
+      // Cancel any pending InterestGained tasks, and (if the invoker already
+      // has interest) schedule an InterestLost task.
       invoker_data->CancelInterestGainedTask();
-      ScheduleInterestLostTask();
+      if (invoker_data->GetInterestState() != InterestState::kNoInterest) {
+        ScheduleInterestLostTask();
+      }
     }
     if (upstream_invoker) [[unlikely]] {
       // This is the target of an interest invoker, which was just de-hovered or
diff --git a/third_party/blink/renderer/core/dom/observable.cc b/third_party/blink/renderer/core/dom/observable.cc
index 0655f80e..f2aa220 100644
--- a/third_party/blink/renderer/core/dom/observable.cc
+++ b/third_party/blink/renderer/core/dom/observable.cc
@@ -2744,7 +2744,7 @@
   // signals conversion failure, so we must (and can safely) ignore it and let
   // other conversion attempts below continue.
   if (Observable* converted = NativeValueTraits<Observable>::NativeValue(
-          isolate, v8_value, IgnoreException(isolate))) {
+          isolate, v8_value, IGNORE_EXCEPTION)) {
     return converted;
   }
 
diff --git a/third_party/blink/renderer/core/editing/commands/move_commands.cc b/third_party/blink/renderer/core/editing/commands/move_commands.cc
index 9d8cc06..a0df564 100644
--- a/third_party/blink/renderer/core/editing/commands/move_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/move_commands.cc
@@ -31,6 +31,7 @@
 
 #include "third_party/blink/renderer/core/editing/commands/move_commands.h"
 
+#include "cc/input/scroll_utils.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/focus_params.h"
 #include "third_party/blink/renderer/core/editing/editing_behavior.h"
@@ -69,10 +70,7 @@
   const ScrollableArea& scrollable_area = *frame.View()->LayoutViewport();
   const int height = std::min<int>(layout_box.ClientHeight().ToInt(),
                                    scrollable_area.VisibleHeight());
-  return static_cast<unsigned>(
-      max(max<int>(height * ScrollableArea::MinFractionToStepWhenPaging(),
-                   height - scrollable_area.MaxOverlapBetweenPages()),
-          1));
+  return cc::ScrollUtils::CalculatePageStep(height);
 }
 
 bool MoveCommands::ModifySelectionWithPageGranularity(
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc
index dd55ae8..e3067ce5 100644
--- a/third_party/blink/renderer/core/editing/serializers/serialization.cc
+++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -754,8 +754,7 @@
     fragment->ParserAppendChild(Text::Create(output_doc, source_string));
   } else {
     bool successful_parse =
-        fragment->ParseXML(source_string, nullptr,
-                           IgnoreException(output_doc.GetAgent().isolate()),
+        fragment->ParseXML(source_string, nullptr, IGNORE_EXCEPTION,
                            kAllowScriptingContentAndDoNotMarkAlreadyStarted);
     if (!successful_parse)
       return nullptr;
diff --git a/third_party/blink/renderer/core/events/input_event.cc b/third_party/blink/renderer/core/events/input_event.cc
index 19c8f4c..7a4e313f 100644
--- a/third_party/blink/renderer/core/events/input_event.cc
+++ b/third_party/blink/renderer/core/events/input_event.cc
@@ -108,8 +108,7 @@
 
 }  // anonymous namespace
 
-/* static */ InputEvent* InputEvent::Create(v8::Isolate* isolate,
-                                            const AtomicString& type,
+/* static */ InputEvent* InputEvent::Create(const AtomicString& type,
                                             const InputEventInit* initializer,
                                             ExceptionState& exception_state) {
   InputEvent* result;
@@ -121,8 +120,8 @@
       return nullptr;
     }
   } else {
-    result = MakeGarbageCollected<InputEvent>(type, initializer,
-                                              IgnoreException(isolate));
+    result =
+        MakeGarbageCollected<InputEvent>(type, initializer, IGNORE_EXCEPTION);
   }
   return result;
 }
diff --git a/third_party/blink/renderer/core/events/input_event.h b/third_party/blink/renderer/core/events/input_event.h
index fe4cc34..57b7722 100644
--- a/third_party/blink/renderer/core/events/input_event.h
+++ b/third_party/blink/renderer/core/events/input_event.h
@@ -18,8 +18,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static InputEvent* Create(v8::Isolate* isolate,
-                            const AtomicString& type,
+  static InputEvent* Create(const AtomicString& type,
                             const InputEventInit* initializer,
                             ExceptionState& exception_state);
 
diff --git a/third_party/blink/renderer/core/events/input_event.idl b/third_party/blink/renderer/core/events/input_event.idl
index 09f0550..5440ecb41 100644
--- a/third_party/blink/renderer/core/events/input_event.idl
+++ b/third_party/blink/renderer/core/events/input_event.idl
@@ -8,7 +8,7 @@
 [
     Exposed=Window
 ] interface InputEvent : UIEvent {
-    [RaisesException, CallWith=Isolate] constructor(DOMString type, optional InputEventInit eventInitDict = {});
+    [RaisesException] constructor(DOMString type, optional InputEventInit eventInitDict = {});
     readonly attribute DOMString? data;
     readonly attribute boolean isComposing;
 
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
index c476094..57a31ff 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
@@ -96,8 +96,7 @@
   EXPECT_EQ(token, request_data->ServiceWorkerRaceNetworkRequestToken());
 
   // Token is not cloned.
-  auto* cloned_request_data =
-      request_data->Clone(nullptr, IGNORE_EXCEPTION_FOR_TESTING);
+  auto* cloned_request_data = request_data->Clone(nullptr, IGNORE_EXCEPTION);
   EXPECT_TRUE(
       cloned_request_data->ServiceWorkerRaceNetworkRequestToken().is_empty());
 }
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 0be0886..8fe2d35 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -33,6 +33,8 @@
 
 #include "base/containers/contains.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/feature_list.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
 #include "services/network/public/mojom/integrity_algorithm.mojom-blink.h"
@@ -496,6 +498,7 @@
       case CSPDirectiveName::ScriptSrc:
       case CSPDirectiveName::ScriptSrcAttr:
       case CSPDirectiveName::ScriptSrcElem:
+      case CSPDirectiveName::ScriptSrcV2:
       case CSPDirectiveName::StyleSrc:
       case CSPDirectiveName::StyleSrcAttr:
       case CSPDirectiveName::StyleSrcElem:
@@ -831,6 +834,7 @@
              CSPDirectiveName::MediaSrc,
              CSPDirectiveName::ObjectSrc,
              CSPDirectiveName::ScriptSrc,
+             CSPDirectiveName::ScriptSrcV2,
              CSPDirectiveName::ScriptSrcElem,
              CSPDirectiveName::StyleSrc,
              CSPDirectiveName::StyleSrcElem,
@@ -1533,6 +1537,8 @@
       return "sandbox";
     case CSPDirectiveName::ScriptSrc:
       return "script-src";
+    case CSPDirectiveName::ScriptSrcV2:
+      return "script-src-v2";
     case CSPDirectiveName::ScriptSrcAttr:
       return "script-src-attr";
     case CSPDirectiveName::ScriptSrcElem:
@@ -1598,6 +1604,10 @@
     return CSPDirectiveName::Sandbox;
   if (name == "script-src")
     return CSPDirectiveName::ScriptSrc;
+  if (base::FeatureList::IsEnabled(network::features::kCSPScriptSrcV2) &&
+      name == "script-src-v2") {
+    return CSPDirectiveName::ScriptSrcV2;
+  }
   if (name == "script-src-attr")
     return CSPDirectiveName::ScriptSrcAttr;
   if (name == "script-src-elem")
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
index e98d291..b92e4cc 100644
--- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
+++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -300,6 +300,7 @@
                   CSPDirectiveName effective_type) {
   // 'strict-dynamic' only applies to scripts
   if (effective_type != CSPDirectiveName::ScriptSrc &&
+      effective_type != CSPDirectiveName::ScriptSrcV2 &&
       effective_type != CSPDirectiveName::ScriptSrcAttr &&
       effective_type != CSPDirectiveName::ScriptSrcElem &&
       effective_type != CSPDirectiveName::WorkerSrc) {
@@ -529,6 +530,7 @@
       prefix = prefix + "load plugin data from '";
       break;
     case CSPDirectiveName::ScriptSrc:
+    case CSPDirectiveName::ScriptSrcV2:
     case CSPDirectiveName::ScriptSrcAttr:
     case CSPDirectiveName::ScriptSrcElem:
       prefix = prefix + "load the script '";
@@ -862,6 +864,7 @@
          type == CSPDirectiveName::MediaSrc ||
          type == CSPDirectiveName::ObjectSrc ||
          type == CSPDirectiveName::ScriptSrc ||
+         type == CSPDirectiveName::ScriptSrcV2 ||
          type == CSPDirectiveName::ScriptSrcElem ||
          type == CSPDirectiveName::StyleSrc ||
          type == CSPDirectiveName::StyleSrcElem ||
diff --git a/third_party/blink/renderer/core/frame/csp/source_list_directive.cc b/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
index dffb52c..7f3efbb 100644
--- a/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
+++ b/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/frame/csp/source_list_directive.h"
 
 #include "base/feature_list.h"
+#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/csp/csp_source.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -30,6 +31,7 @@
 
 bool IsScriptDirective(CSPDirectiveName directive_type) {
   return (directive_type == CSPDirectiveName::ScriptSrc ||
+          directive_type == CSPDirectiveName::ScriptSrcV2 ||
           directive_type == CSPDirectiveName::ScriptSrcAttr ||
           directive_type == CSPDirectiveName::ScriptSrcElem ||
           directive_type == CSPDirectiveName::DefaultSrc);
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 85138f49..f5e03e8f 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
@@ -1043,12 +1043,14 @@
   // If the canvas is gpu composited, it has another way of getting to screen
   if (!PaintsIntoCanvasBuffer()) {
     // For click-and-drag or printing we still want to draw
-    if (!(flatten_composited_layers || GetDocument().Printing()))
+    if (!(flatten_composited_layers ||
+          GetDocument().IsPrintingOrPaintingPreview())) {
       return;
+    }
   }
 
   if (OffscreenCanvasFrame()) {
-    DCHECK(GetDocument().Printing());
+    DCHECK(GetDocument().IsPrintingOrPaintingPreview());
     scoped_refptr<StaticBitmapImage> image_for_printing =
         OffscreenCanvasFrame()->Bitmap()->MakeUnaccelerated();
     if (!image_for_printing)
diff --git a/third_party/blink/renderer/core/html/forms/option_list.cc b/third_party/blink/renderer/core/html/forms/option_list.cc
index 4d0382b..153467d4 100644
--- a/third_party/blink/renderer/core/html/forms/option_list.cc
+++ b/third_party/blink/renderer/core/html/forms/option_list.cc
@@ -102,7 +102,7 @@
         current = nullptr;
       } else if (IsA<HTMLSelectElement>(current) ||
                  IsA<HTMLHRElement>(current)) {
-        current = ElementTraversal::PreviousAbsoluteSibling(*next, &select_);
+        current = ElementTraversal::PreviousAbsoluteSibling(*current, &select_);
       } else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(current)) {
         // optgroup->OwnerSelectElement() might be null because this method may
         // be called before InsertedInto is called on the optgroup.
@@ -112,7 +112,8 @@
           current = ElementTraversal::Previous(*current, &select_);
         } else {
           // Don't track elements inside nested <optgroup>s.
-          current = ElementTraversal::PreviousAbsoluteSibling(*next, &select_);
+          current =
+              ElementTraversal::PreviousAbsoluteSibling(*current, &select_);
         }
       } else {
         current = ElementTraversal::Previous(*current, &select_);
diff --git a/third_party/blink/renderer/core/html/forms/option_list_test.cc b/third_party/blink/renderer/core/html/forms/option_list_test.cc
index a2006d38..1f7146a 100644
--- a/third_party/blink/renderer/core/html/forms/option_list_test.cc
+++ b/third_party/blink/renderer/core/html/forms/option_list_test.cc
@@ -105,4 +105,21 @@
   EXPECT_FALSE(is_null);
 }
 
+TEST_F(OptionListTest, RetreatOverHRAndOptgroup) {
+  Select().setInnerHTML(R"HTML(
+    <option id=o1>one</option>
+    <hr>
+    <optgroup></optgroup>
+    <option id=o2>two</option>
+  )HTML");
+
+  OptionList list = Select().GetOptionList();
+  OptionList::Iterator it = list.begin();
+  EXPECT_EQ("o1", Id(*it));
+  ++it;
+  EXPECT_EQ("o2", Id(*it));
+  --it;
+  EXPECT_EQ("o1", Id(*it));
+}
+
 }  // naemespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 5e1f32d1..87d3407 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -5018,7 +5018,8 @@
 }
 
 void HTMLMediaElement::RecordAutoPictureInPictureInfo(
-    const String& auto_picture_in_picture_info) {
+    const media::PictureInPictureEventsInfo::AutoPipInfo&
+        auto_picture_in_picture_info) {
   if (web_media_player_) {
     web_media_player_->RecordAutoPictureInPictureInfo(
         auto_picture_in_picture_info);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index c4d20d3..0f38ecb 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -625,7 +625,8 @@
   void RequestVisibility(
       RequestVisibilityCallback request_visibility_cb) override {}
   void RecordAutoPictureInPictureInfo(
-      const String& auto_picture_in_picture_info) override;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override;
 
   void LoadTimerFired(TimerBase*);
   void ProgressEventTimerFired();
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
index 1689d7b..d1e6a36 100644
--- a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
+++ b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
@@ -164,7 +164,7 @@
       GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
 
   GetDocument().body()->setPointerCapture(PointerEventFactory::kMouseId,
-                                          IGNORE_EXCEPTION_FOR_TESTING);
+                                          IGNORE_EXCEPTION);
   ASSERT_TRUE(
       GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
 
@@ -177,7 +177,7 @@
       GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
 
   GetDocument().body()->releasePointerCapture(PointerEventFactory::kMouseId,
-                                              IGNORE_EXCEPTION_FOR_TESTING);
+                                              IGNORE_EXCEPTION);
   ASSERT_FALSE(
       GetDocument().body()->hasPointerCapture(PointerEventFactory::kMouseId));
 }
diff --git a/third_party/blink/renderer/core/inspector/dom_patch_support.cc b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
index 74f64a2..922da58 100644
--- a/third_party/blink/renderer/core/inspector/dom_patch_support.cc
+++ b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
@@ -39,7 +39,6 @@
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/dom/node_traversal.h"
 #include "third_party/blink/renderer/core/dom/xml_document.h"
-#include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/html/html_body_element.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/html/html_head_element.h"
@@ -92,8 +91,7 @@
   Digest* new_info =
       CreateDigest(new_document->documentElement(), &unused_nodes_map_);
 
-  if (!InnerPatchNode(old_info, new_info,
-                      IgnoreException(GetDocument().GetAgent().isolate()))) {
+  if (!InnerPatchNode(old_info, new_info, IGNORE_EXCEPTION_FOR_TESTING)) {
     // Fall back to rewrite.
     GetDocument().write(markup);
     GetDocument().close();
@@ -123,12 +121,10 @@
   auto* target_element = To<Element>(target_node);
 
   // FIXME: This code should use one of createFragment* in Serialization.h
-  if (IsA<HTMLDocument>(GetDocument())) {
+  if (IsA<HTMLDocument>(GetDocument()))
     fragment->ParseHTML(markup, target_element);
-  } else {
-    fragment->ParseXML(markup, target_element,
-                       IgnoreException(GetDocument().GetAgent().isolate()));
-  }
+  else
+    fragment->ParseXML(markup, target_element, IGNORE_EXCEPTION);
 
   // Compose the old list.
   ContainerNode* parent_node = node->parentNode();
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index f23132b..84f058b6 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -63,7 +63,6 @@
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/dom/xml_document.h"
 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
-#include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/fileapi/file.h"
 #include "third_party/blink/renderer/core/frame/frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -1087,13 +1086,10 @@
                               : "<span " + text + "></span>";
     DocumentFragment* fragment =
         element->GetDocument().createDocumentFragment();
-    if (is_html_document && contextElement) {
+    if (is_html_document && contextElement)
       fragment->ParseHTML(markup, contextElement, kAllowScriptingContent);
-    } else {
-      fragment->ParseXML(
-          markup, contextElement,
-          IgnoreException(element->GetDocument().GetAgent().isolate()));
-    }
+    else
+      fragment->ParseXML(markup, contextElement, IGNORE_EXCEPTION);
     return DynamicTo<Element>(fragment->firstChild());
   };
 
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc
index dd92ba0f..cde0e6d6 100644
--- a/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -797,7 +797,7 @@
     const Element& owner,
     FocusController::OwnerMap& owner_map) {
   DCHECK(IsReadingFlowScopeOwner(&owner));
-  HTMLElement& element = const_cast<HTMLElement&>(To<HTMLElement>(owner));
+  Element& element = const_cast<Element&>(owner);
   return ScopedFocusNavigation(element, nullptr, owner_map);
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 857c5d6b..cacb6ca 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -52,6 +52,7 @@
 #include "cc/animation/animation_timeline.h"
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "cc/input/scroll_snap_data.h"
+#include "cc/input/scroll_utils.h"
 #include "cc/input/snap_selection_strategy.h"
 #include "cc/layers/picture_layer.h"
 #include "third_party/blink/public/common/features.h"
@@ -856,20 +857,6 @@
   return GetLayoutBox()->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft();
 }
 
-int PaintLayerScrollableArea::PageStep(ScrollbarOrientation orientation) const {
-  // Paging scroll operations should take scroll-padding into account [1]. So we
-  // use the snapport rect to calculate the page step instead of the visible
-  // rect.
-  // [1] https://drafts.csswg.org/css-scroll-snap/#scroll-padding
-  gfx::Size snapport_size = VisibleScrollSnapportRect().PixelSnappedSize();
-  int length = (orientation == kHorizontalScrollbar) ? snapport_size.width()
-                                                     : snapport_size.height();
-  int min_page_step = static_cast<float>(length) *
-                      ScrollableArea::MinFractionToStepWhenPaging();
-  int page_step = max(min_page_step, length - MaxOverlapBetweenPages());
-  return max(page_step, 1);
-}
-
 bool PaintLayerScrollableArea::IsRootFrameLayoutViewport() const {
   LocalFrame* frame = GetLayoutBox()->GetFrame();
   if (!frame || !frame->View())
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index 87df88b..e07b6c4c 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -344,7 +344,6 @@
   void DeregisterForAnimation() override;
   bool UserInputScrollable(ScrollbarOrientation) const override;
   bool ShouldPlaceVerticalScrollbarOnLeft() const override;
-  int PageStep(ScrollbarOrientation) const override;
   mojom::blink::ScrollBehavior ScrollBehaviorStyle() const override;
   mojom::blink::ColorScheme UsedColorSchemeScrollbars() const override;
   cc::AnimationHost* GetCompositorAnimationHost() const override;
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc
index fcb41fc..f2a76e4 100644
--- a/third_party/blink/renderer/core/scroll/scrollable_area.cc
+++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -84,14 +84,6 @@
       frame, cc::kPixelsPerLineStep);
 }
 
-float ScrollableArea::MinFractionToStepWhenPaging() {
-  return cc::kMinFractionToStepWhenPaging;
-}
-
-int ScrollableArea::MaxOverlapBetweenPages() const {
-  return GetPageScrollbarTheme().MaxOverlapBetweenPages();
-}
-
 // static
 mojom::blink::ScrollBehavior ScrollableArea::DetermineScrollBehavior(
     mojom::blink::ScrollBehavior behavior_from_param,
@@ -1080,15 +1072,12 @@
   // use the snapport rect to calculate the page step instead of the visible
   // rect.
   // [1] https://drafts.csswg.org/css-scroll-snap/#scroll-padding
-  gfx::Size snapport_size =
+  const gfx::Size snapport_size =
       VisibleScrollSnapportRect(kExcludeScrollbars).PixelSnappedSize();
-  int length = (orientation == kHorizontalScrollbar) ? snapport_size.width()
-                                                     : snapport_size.height();
-  int min_page_step =
-      static_cast<float>(length) * MinFractionToStepWhenPaging();
-  int page_step = std::max(min_page_step, length - MaxOverlapBetweenPages());
-
-  return std::max(page_step, 1);
+  const int snapport_length = (orientation == kHorizontalScrollbar)
+                                  ? snapport_size.width()
+                                  : snapport_size.height();
+  return cc::ScrollUtils::CalculatePageStep(snapport_length);
 }
 
 int ScrollableArea::DocumentStep(ScrollbarOrientation orientation) const {
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.h b/third_party/blink/renderer/core/scroll/scrollable_area.h
index 1fbc346..a7a692ba 100644
--- a/third_party/blink/renderer/core/scroll/scrollable_area.h
+++ b/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -106,8 +106,6 @@
   ScrollableArea& operator=(const ScrollableArea&) = delete;
 
   static int PixelsPerLineStep(LocalFrame*);
-  static float MinFractionToStepWhenPaging();
-  int MaxOverlapBetweenPages() const;
 
   // Convert a non-finite scroll value (Infinity, -Infinity, NaN) to 0 as
   // per https://drafts.csswg.org/cssom-view/#normalize-non-finite-values.
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme.h b/third_party/blink/renderer/core/scroll/scrollbar_theme.h
index 189d1000..c9a2a0e 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme.h
@@ -183,10 +183,6 @@
                             const Scrollbar&,
                             const gfx::Rect&);
 
-  virtual int MaxOverlapBetweenPages() const {
-    return std::numeric_limits<int>::max();
-  }
-
   virtual base::TimeDelta InitialAutoscrollTimerDelay() const;
   virtual base::TimeDelta AutoscrollTimerDelay() const;
 
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
index 1bea0ede..048491d3 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
@@ -91,8 +91,6 @@
       bool jump_on_track_click);
 
  protected:
-  int MaxOverlapBetweenPages() const override { return 40; }
-
   bool ShouldDragDocumentInsteadOfThumb(const Scrollbar&,
                                         const WebMouseEvent&) const override;
 
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
index 4b69b66..fd05742 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
@@ -539,11 +539,11 @@
     }
     // Let patterns be an empty list.
     HeapVector<Member<URLPattern>> patterns;
-    v8::Isolate* isolate = execution_context->GetIsolate();
     // For each rawPattern of rawPatterns:
     for (JSONValue* raw_pattern : raw_patterns) {
-      URLPattern* pattern = ParseRawPattern(
-          isolate, raw_pattern, base_url, IgnoreException(isolate), out_error);
+      URLPattern* pattern =
+          ParseRawPattern(execution_context->GetIsolate(), raw_pattern,
+                          base_url, IGNORE_EXCEPTION, out_error);
       // If those steps throw, `pattern` will be null. Ignore the exception and
       // return null.
       if (!pattern) {
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc
index 453e4d2..aa41d8b 100644
--- a/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -319,8 +319,7 @@
   auto* stream = MakeGarbageCollected<ReadableStream>();
   stream->InitWithCountQueueingStrategy(
       script_state, underlying_source, high_water_mark,
-      allow_per_chunk_transferring, std::move(optimizer),
-      IgnoreException(isolate));
+      allow_per_chunk_transferring, std::move(optimizer), IGNORE_EXCEPTION);
   return stream;
 }
 
diff --git a/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.cc b/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.cc
index e381b60..942f0ea1 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.cc
@@ -67,7 +67,7 @@
       isolate, ToMicrotaskQueue(script_state_),
       v8::MicrotasksScope::kDoNotRunMicrotasks);
   ReadableStreamDefaultController::Enqueue(script_state_, controller_, js_chunk,
-                                           IgnoreException(isolate));
+                                           IGNORE_EXCEPTION);
 }
 
 void ReadableStreamDefaultControllerWithScriptScope::Error(
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc
index 2ecc8031..b42d123b 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -839,7 +839,7 @@
       // exceptions.
       dummy_stream->cancel(script_state,
                            ScriptValue(isolate, v8::Undefined(isolate)),
-                           IgnoreException(isolate));
+                           IGNORE_EXCEPTION);
       resolver_->Reject(e);
     }
 
diff --git a/third_party/blink/renderer/core/testing/data/mhtml/.gitattributes b/third_party/blink/renderer/core/testing/data/mhtml/.gitattributes
index a9ebe50e..c6ccda1 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/.gitattributes
+++ b/third_party/blink/renderer/core/testing/data/mhtml/.gitattributes
@@ -2,5 +2,6 @@
 * text=auto
 
 # MHTML files in general should only have CRLF line endings
-# (see RFC2557, section 10).
-*.mht text eol=crlf
+# (see RFC2557, section 10). So treat them as binary as
+# GOB needs them as such.
+*.mht binary
diff --git a/third_party/blink/renderer/core/testing/data/mhtml/form.mht b/third_party/blink/renderer/core/testing/data/mhtml/form.mht
index bbd386e..21948b0 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/form.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/form.mht
@@ -1,30 +1,30 @@
-From: <Saved by Blink>
-Subject: Form
-Date: Thu, 4 Oct 2017 21:18:18 -0000
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----"
-
-------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----
-Content-Type: text/html
-Content-ID: <frame-31894-fca076b5-329b-490d-a9ee-6974bf0c4bcd@mhtml.blink>
-Content-Transfer-Encoding: quoted-printable
-Content-Location: file:///usr/local/google/home/jianli/form.html
-
-<html>
-<head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3DUTF-8">
-</head>
-<body>
-<h1 id="h1">Form</h1>
-<form id="fm">
-<input class="fc" type=3D"text" name=3D"name" value=3D"">
-<input class="fc" type=3D"password" name=3D"pwd">
-<input class="fc" type=3D"button" value=3D"Click">
-<input class="fc" type=3D"reset">
-<input class="fc" type=3D"submit" value=3D"Submit">
-</form>
-</body>
-</html>
-------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK------
+From: <Saved by Blink>

+Subject: Form

+Date: Thu, 4 Oct 2017 21:18:18 -0000

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----"

+

+------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----

+Content-Type: text/html

+Content-ID: <frame-31894-fca076b5-329b-490d-a9ee-6974bf0c4bcd@mhtml.blink>

+Content-Transfer-Encoding: quoted-printable

+Content-Location: file:///usr/local/google/home/jianli/form.html

+

+<html>

+<head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3DUTF-8">

+</head>

+<body>

+<h1 id="h1">Form</h1>

+<form id="fm">

+<input class="fc" type=3D"text" name=3D"name" value=3D"">

+<input class="fc" type=3D"password" name=3D"pwd">

+<input class="fc" type=3D"button" value=3D"Click">

+<input class="fc" type=3D"reset">

+<input class="fc" type=3D"submit" value=3D"Submit">

+</form>

+</body>

+</html>

+------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK------

diff --git a/third_party/blink/renderer/core/testing/data/mhtml/page_with_javascript.mht b/third_party/blink/renderer/core/testing/data/mhtml/page_with_javascript.mht
index 4e9a6a3..ab5f376 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/page_with_javascript.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/page_with_javascript.mht
@@ -1,51 +1,51 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=
-Date: Wed, May 11 2011 15:36:36 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_87206557.D2C008B0";
-	type="text/html"
-
-------=_NextPart_000_0000_87206557.D2C008B0
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_javascript.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page with JavaScript</title>
-<h1>This page has content generated by JavaScript</h1>
-Javascript is not run, so that dynamic content should not show.
-<div id=3D"myDiv"></div>
-
-<script>
- document.getElementById('myDiv').innerHTML =3D
-      "<span id='mySpan'>Foo</span>";
-</script>
-
-<iframe src=3D"http://localhost/another_page_with_javascript.html">
-</iframe>
-</body></html>
-------=_NextPart_000_0000_87206557.D2C008B0
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/another_page_with_javascript.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page with JavaScript</title>
-<h1>This page has content generated by JavaScript</h1>
-Javascript is not run, so that dynamic content should not show.
-<div id=3D"myDiv"></div>
-
-<script>
- document.getElementById('myDiv').innerHTML =3D
-      "<span id='mySpan'>Foo</span>";
-</script>
-
-</body></html>
-------=_NextPart_000_0000_87206557.D2C008B0--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=

+Date: Wed, May 11 2011 15:36:36 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_87206557.D2C008B0";

+	type="text/html"

+

+------=_NextPart_000_0000_87206557.D2C008B0

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_javascript.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page with JavaScript</title>

+<h1>This page has content generated by JavaScript</h1>

+Javascript is not run, so that dynamic content should not show.

+<div id=3D"myDiv"></div>

+

+<script>

+ document.getElementById('myDiv').innerHTML =3D

+      "<span id='mySpan'>Foo</span>";

+</script>

+

+<iframe src=3D"http://localhost/another_page_with_javascript.html">

+</iframe>

+</body></html>

+------=_NextPart_000_0000_87206557.D2C008B0

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/another_page_with_javascript.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page with JavaScript</title>

+<h1>This page has content generated by JavaScript</h1>

+Javascript is not run, so that dynamic content should not show.

+<div id=3D"myDiv"></div>

+

+<script>

+ document.getElementById('myDiv').innerHTML =3D

+      "<span id='mySpan'>Foo</span>";

+</script>

+

+</body></html>

+------=_NextPart_000_0000_87206557.D2C008B0--

diff --git a/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht b/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
index 662c160..08e626a 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/shadow.mht
@@ -1,37 +1,37 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=
-Date: Wed, May 11 2011 15:36:36 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_87206557.D2C008B0";
-	type="text/html"
-
-------=_NextPart_000_0000_87206557.D2C008B0
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/shadow.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page with shadow DOM content</title>
-<h1>This page has shadow DOM content</h1>
-
-<div id=3D"h2">
-  <template shadowmode=3D"open" shadowdelegatesfocus=3D"">Parent
-    <p id=3D"h3">
-      <template shadowmode=3D"closed">Nested</template>
-    </p>
-  </template>
-</div>
-<div id=3D"h4">
-  <template shadowmode=3D"open">
-    <span id='s1'>Foo</span>
-    <script>document.getElementById('s1').innerHTML=3D"<span id='s2'>Bar</span>";
-    </script>
-  </template>
-</div>
-
-</body></html>
-------=_NextPart_000_0000_87206557.D2C008B0--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=

+Date: Wed, May 11 2011 15:36:36 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_87206557.D2C008B0";

+	type="text/html"

+

+------=_NextPart_000_0000_87206557.D2C008B0

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/shadow.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page with shadow DOM content</title>

+<h1>This page has shadow DOM content</h1>

+

+<div id=3D"h2">

+  <template shadowmode=3D"open" shadowdelegatesfocus=3D"">Parent

+    <p id=3D"h3">

+      <template shadowmode=3D"closed">Nested</template>

+    </p>

+  </template>

+</div>

+<div id=3D"h4">

+  <template shadowmode=3D"open">

+    <span id='s1'>Foo</span>

+    <script>document.getElementById('s1').innerHTML=3D"<span id='s2'>Bar</span>";

+    </script>

+  </template>

+</div>

+

+</body></html>

+------=_NextPart_000_0000_87206557.D2C008B0--

diff --git a/third_party/blink/renderer/core/testing/data/mhtml/simple_test.mht b/third_party/blink/renderer/core/testing/data/mhtml/simple_test.mht
index f0afef3..cf0d82f 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/simple_test.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/simple_test.mht
@@ -1,19 +1,19 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject: A simple page
-Date: Wed, 18 May 2011 16:50:01 -0700
-MIME-Version: 1.0
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/simple_page.html
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD><TITLE>A simple page</TITLE>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>
-<H1>This is a very simple page</H1>Very <B>basic</B> page. =
-</BODY></HTML>
+From: "Saved by Windows Internet Explorer 9"

+Subject: A simple page

+Date: Wed, 18 May 2011 16:50:01 -0700

+MIME-Version: 1.0

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/simple_page.html

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD><TITLE>A simple page</TITLE>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>

+<H1>This is a very simple page</H1>Very <B>basic</B> page. =

+</BODY></HTML>

diff --git a/third_party/blink/renderer/core/testing/data/mhtml/soft_line_break.mht b/third_party/blink/renderer/core/testing/data/mhtml/soft_line_break.mht
index fdd9c1d3..993f3d5 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/soft_line_break.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/soft_line_break.mht
@@ -1,27 +1,27 @@
-From: <Saved by Blink>
-Subject: =?utf-8?Q?012345678901234567890123456789012345678901234567890
-	1234567890123456789012345678901234567890123456789
-	=3D=E2=98=9D=F0=9F=8F=BB?=
-Date: Thu, 4 Oct 2017 21:18:18 -0000
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----"
-
-------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----
-Content-Type: text/html
-Content-ID: <frame-31894-fca076b5-329b-490d-a9ee-6974bf0c4bcd@mhtml.blink>
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/soft_line_break.html
-
-<html>
-<head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3DUTF-8">
-</head>
-<body>
-<div id=3D"AVeryLongID01234567890123456789012345678901234567890123456=
-7890End">
-</div>
-</body>
-</html>
-------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK------
+From: <Saved by Blink>

+Subject: =?utf-8?Q?012345678901234567890123456789012345678901234567890

+	1234567890123456789012345678901234567890123456789

+	=3D=E2=98=9D=F0=9F=8F=BB?=

+Date: Thu, 4 Oct 2017 21:18:18 -0000

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----"

+

+------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----

+Content-Type: text/html

+Content-ID: <frame-31894-fca076b5-329b-490d-a9ee-6974bf0c4bcd@mhtml.blink>

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/soft_line_break.html

+

+<html>

+<head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3DUTF-8">

+</head>

+<body>

+<div id=3D"AVeryLongID01234567890123456789012345678901234567890123456=

+7890End">

+</div>

+</body>

+</html>

+------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK------

diff --git a/third_party/blink/renderer/core/testing/data/mhtml/xslt.mht b/third_party/blink/renderer/core/testing/data/mhtml/xslt.mht
index 4392167..a395a20 100644
--- a/third_party/blink/renderer/core/testing/data/mhtml/xslt.mht
+++ b/third_party/blink/renderer/core/testing/data/mhtml/xslt.mht
@@ -1,25 +1,25 @@
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----MultipartBoundary--"
-
-------MultipartBoundary--
-Content-Type: text/xml
-
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xml" href="#stylesheet"?>
-<!DOCTYPE catalog [
-<!ATTLIST xsl:stylesheet
-  id    ID  #REQUIRED>
-]>
-<root>
-<xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-<xsl:template match="/">
-<html>
-<body>
-</body>
-</html>
-</xsl:template>
-</xsl:stylesheet>
-</root>
-------MultipartBoundary----
+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----MultipartBoundary--"

+

+------MultipartBoundary--

+Content-Type: text/xml

+

+<?xml version="1.0" encoding="UTF-8"?>

+<?xml-stylesheet type="text/xml" href="#stylesheet"?>

+<!DOCTYPE catalog [

+<!ATTLIST xsl:stylesheet

+  id    ID  #REQUIRED>

+]>

+<root>

+<xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

+<xsl:template match="/">

+<html>

+<body>

+</body>

+</html>

+</xsl:template>

+</xsl:stylesheet>

+</root>

+------MultipartBoundary----

diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
index 62e3b074..48bb837 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -1035,18 +1035,19 @@
   bool is_first_element = !saw_first_element_;
   saw_first_element_ = true;
 
-  v8::Isolate* isolate = document_->GetAgent().isolate();
   Vector<Attribute, kAttributePrealloc> prefixed_attributes;
   if (!HandleNamespaceAttributes(prefixed_attributes, namespaces,
-                                 IgnoreException(isolate))) {
+                                 IGNORE_EXCEPTION)) {
     StopParsing();
     return;
   }
 
+  v8::Isolate* isolate = document_->GetAgent().isolate();
   v8::TryCatch try_catch(isolate);
   if (!HandleElementAttributes(prefixed_attributes, attributes,
                                prefix_to_namespace_map_,
-                               PassThroughException(isolate))) {
+                               parsing_fragment_ ? PassThroughException(isolate)
+                                                 : IGNORE_EXCEPTION)) {
     StopParsing();
     if (parsing_fragment_) {
       DCHECK(try_catch.HasCaught());
@@ -1159,7 +1160,7 @@
   if (element->IsScriptElement() &&
       !ScriptingContentIsAllowed(GetParserContentPolicy())) {
     PopCurrentNode();
-    n->remove(IgnoreException(document_->GetAgent().isolate()));
+    n->remove(IGNORE_EXCEPTION_FOR_TESTING);
     return;
   }
 
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc
index 004b7a64..8b743d0 100644
--- a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc
+++ b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc
@@ -441,6 +441,16 @@
   double last_score = 1;
   double cumulative_confidence = 0;
 
+  const WTF::UncheckedIterator<LanguageDetectionModel::LanguagePrediction>&
+      unknown_iter = std::find_if(
+          predictions.begin(), predictions.end(),
+          [](const LanguageDetectionModel::LanguagePrediction& prediction) {
+            return prediction.language == "unknown";
+          });
+
+  CHECK_NE(unknown_iter, predictions.end());
+  double unknown = unknown_iter->score;
+
   HeapVector<Member<LanguageDetectionResult>> results;
   for (const auto& prediction : predictions) {
     CHECK_GE(prediction.score, 0);
@@ -448,9 +458,10 @@
     CHECK_LE(prediction.score, last_score);
     last_score = prediction.score;
 
-    if (prediction.score == 0 || prediction.language == "unknown") {
+    if (prediction.score == 0 || prediction.score < unknown) {
       break;
     }
+
     auto* result = MakeGarbageCollected<LanguageDetectionResult>();
     results.push_back(result);
     result->setDetectedLanguage(String(prediction.language));
@@ -463,12 +474,17 @@
     }
   }
 
+  CHECK_GE(1 - cumulative_confidence, unknown);
+  if (!results.empty()) {
+    CHECK_GE(results.back()->confidence(), unknown);
+  }
+
   // Append "und" to end. Set it's confidence so that the total confidences add
   // up to 1.
   auto* und_result = MakeGarbageCollected<LanguageDetectionResult>();
   results.push_back(und_result);
   und_result->setDetectedLanguage(String("und"));
-  und_result->setConfidence(1 - cumulative_confidence);
+  und_result->setConfidence(unknown);
 
   return results;
 }
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
index fbc8cb45..5222a5f0 100644
--- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
+++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
@@ -795,10 +795,8 @@
     EXPECT_CALL(GetPipChromeClient(), SetWindowRect(_, _));
     LocalFrame::NotifyUserActivation(
         document->GetFrame(), mojom::UserActivationNotificationType::kTest);
-    document->domWindow()->resizeTo(10, 10,
-                                    IgnoreException(v8_scope.GetIsolate()));
-    document->domWindow()->resizeTo(20, 20,
-                                    IgnoreException(v8_scope.GetIsolate()));
+    document->domWindow()->resizeTo(10, 10, IGNORE_EXCEPTION);
+    document->domWindow()->resizeTo(20, 20, IGNORE_EXCEPTION);
     testing::Mock::VerifyAndClearExpectations(&GetPipChromeClient());
   }
 
@@ -808,10 +806,8 @@
     EXPECT_CALL(GetPipChromeClient(), SetWindowRect(_, _));
     LocalFrame::NotifyUserActivation(
         document->GetFrame(), mojom::UserActivationNotificationType::kTest);
-    document->domWindow()->resizeBy(10, 10,
-                                    IgnoreException(v8_scope.GetIsolate()));
-    document->domWindow()->resizeBy(20, 20,
-                                    IgnoreException(v8_scope.GetIsolate()));
+    document->domWindow()->resizeBy(10, 10, IGNORE_EXCEPTION);
+    document->domWindow()->resizeBy(20, 20, IGNORE_EXCEPTION);
     testing::Mock::VerifyAndClearExpectations(&GetPipChromeClient());
   }
 
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
index b634d319..f9060bf 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
@@ -15,6 +15,7 @@
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_flags.h"
 #include "media/base/limits.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "media/base/video_frame.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -88,7 +89,8 @@
   void SetVolumeMultiplier(double multiplier) override {}
   void SuspendForFrameClosed() override {}
   void RecordAutoPictureInPictureInfo(
-      const WebString& auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
   void SetWouldTaintOrigin(bool taint) { would_taint_origin_ = taint; }
   bool PassedTimingAllowOriginCheck() const override { return true; }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.cc b/third_party/blink/renderer/modules/mediastream/media_stream.cc
index 74a4e8f..0585533 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream.cc
@@ -296,8 +296,7 @@
   return tracks;
 }
 
-void MediaStream::addTrack(v8::Isolate* isolate,
-                           MediaStreamTrack* track,
+void MediaStream::addTrack(MediaStreamTrack* track,
                            ExceptionState& exception_state) {
   if (!track) {
     exception_state.ThrowDOMException(
@@ -329,12 +328,11 @@
     // If processing by the observer failed, it is most likely because it was
     // not necessary and it became a no-op. The exception can be suppressed,
     // there is nothing to do.
-    observer->OnStreamAddTrack(this, track, IgnoreException(isolate));
+    observer->OnStreamAddTrack(this, track, IGNORE_EXCEPTION);
   }
 }
 
-void MediaStream::removeTrack(v8::Isolate* isolate,
-                              MediaStreamTrack* track,
+void MediaStream::removeTrack(MediaStreamTrack* track,
                               ExceptionState& exception_state) {
   if (!track) {
     exception_state.ThrowDOMException(
@@ -371,7 +369,7 @@
     // If processing by the observer failed, it is most likely because it was
     // not necessary and it became a no-op. The exception can be suppressed,
     // there is nothing to do.
-    observer->OnStreamRemoveTrack(this, track, IgnoreException(isolate));
+    observer->OnStreamRemoveTrack(this, track, IGNORE_EXCEPTION);
   }
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.h b/third_party/blink/renderer/modules/mediastream/media_stream.h
index 4048461..7c35897 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream.h
@@ -114,8 +114,8 @@
   // Adds the track, this may cause "onactive" to fire but it won't cause
   // "onaddtrack" because the track was added explicitly by the JavaScript
   // application.
-  void addTrack(v8::Isolate*, MediaStreamTrack*, ExceptionState&);
-  void removeTrack(v8::Isolate*, MediaStreamTrack*, ExceptionState&);
+  void addTrack(MediaStreamTrack*, ExceptionState&);
+  void removeTrack(MediaStreamTrack*, ExceptionState&);
   MediaStreamTrack* getTrackById(String);
   MediaStream* clone(ScriptState*);
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.idl b/third_party/blink/renderer/modules/mediastream/media_stream.idl
index eed883fe..61beeab 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream.idl
+++ b/third_party/blink/renderer/modules/mediastream/media_stream.idl
@@ -39,8 +39,8 @@
     sequence<MediaStreamTrack> getVideoTracks();
     sequence<MediaStreamTrack> getTracks();
     MediaStreamTrack? getTrackById(DOMString trackId);
-    [CallWith=Isolate, RaisesException] void addTrack(MediaStreamTrack track);
-    [CallWith=Isolate, RaisesException] void removeTrack(MediaStreamTrack track);
+    [RaisesException] void addTrack(MediaStreamTrack track);
+    [RaisesException] void removeTrack(MediaStreamTrack track);
     [CallWith=ScriptState] MediaStream clone();
     [Measure] readonly attribute boolean active;
     attribute EventHandler onaddtrack;
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc
index 8786d9c..c7e2d318 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -462,7 +462,7 @@
       supported_method == kAndroidPayMethod ||
       supported_method == kGooglePayAuthenticationMethod) {
     SetAndroidPayMethodData(execution_context.GetIsolate(), input, output,
-                            IgnoreException(execution_context.GetIsolate()));
+                            IGNORE_EXCEPTION);
   }
 
   // Parse method data to avoid parsing JSON in the browser.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index c155bba3..bbf52e2 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1679,7 +1679,7 @@
   peer_handler_->RestartIce();
 }
 
-void RTCPeerConnection::addStream(v8::Isolate* isolate,
+void RTCPeerConnection::addStream(ScriptState* script_state,
                                   MediaStream* stream,
                                   ExceptionState& exception_state) {
   if (ThrowExceptionIfSignalingStateClosed(signaling_state_, &exception_state))
@@ -1688,14 +1688,13 @@
   MediaStreamVector streams;
   streams.push_back(stream);
   for (const auto& track : stream->getTracks()) {
-    addTrack(track, streams, IgnoreException(isolate));
+    addTrack(track, streams, IGNORE_EXCEPTION);
   }
 
   stream->RegisterObserver(this);
 }
 
-void RTCPeerConnection::removeStream(v8::Isolate* isolate,
-                                     MediaStream* stream,
+void RTCPeerConnection::removeStream(MediaStream* stream,
                                      ExceptionState& exception_state) {
   if (ThrowExceptionIfSignalingStateClosed(signaling_state_, &exception_state))
     return;
@@ -1703,7 +1702,7 @@
     auto* sender = FindSenderForTrackAndStream(track, stream);
     if (!sender)
       continue;
-    removeTrack(sender, IgnoreException(isolate));
+    removeTrack(sender, IGNORE_EXCEPTION);
   }
   stream->UnregisterObserver(this);
 }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
index bb96743..33513874 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -197,9 +197,9 @@
   // A remote stream is any stream associated with a receiver.
   MediaStreamVector getRemoteStreams() const;
 
-  void addStream(v8::Isolate*, MediaStream*, ExceptionState&);
+  void addStream(ScriptState*, MediaStream*, ExceptionState&);
 
-  void removeStream(v8::Isolate*, MediaStream*, ExceptionState&);
+  void removeStream(MediaStream*, ExceptionState&);
 
   ScriptPromise<RTCStatsReport> getStats(ScriptState* script_state,
                                          MediaStreamTrack* selector,
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
index faa33bd..b10eca0 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
@@ -142,8 +142,8 @@
     // Non-standard or removed from the spec:
     [Measure] sequence<MediaStream> getLocalStreams();
     [Measure] sequence<MediaStream> getRemoteStreams();
-    [Measure, CallWith=Isolate, RaisesException] void addStream(MediaStream stream);
-    [Measure, CallWith=Isolate, RaisesException] void removeStream(MediaStream stream);
+    [Measure, CallWith=ScriptState, RaisesException] void addStream(MediaStream stream);
+    [Measure, RaisesException] void removeStream(MediaStream stream);
     [Measure, RaisesException] RTCDTMFSender createDTMFSender(MediaStreamTrack track);
     attribute EventHandler onaddstream;
     attribute EventHandler onremovestream;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
index bf5460f..3fae37d 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
@@ -108,14 +108,14 @@
   void AddStream(V8TestingScope& scope,
                  RTCPeerConnection* pc,
                  MediaStream* stream) {
-    pc->addStream(scope.GetIsolate(), stream, scope.GetExceptionState());
+    pc->addStream(scope.GetScriptState(), stream, scope.GetExceptionState());
     EXPECT_EQ("", GetExceptionMessage(scope));
   }
 
   void RemoveStream(V8TestingScope& scope,
                     RTCPeerConnection* pc,
                     MediaStream* stream) {
-    pc->removeStream(scope.GetIsolate(), stream, scope.GetExceptionState());
+    pc->removeStream(stream, scope.GetExceptionState());
     EXPECT_EQ("", GetExceptionMessage(scope));
   }
 
@@ -212,10 +212,8 @@
     // Transceivers will still reference the stream even after it is "removed".
     // To make the GC tests work, clear the stream from tracks so that the
     // stream does not keep tracks alive.
-    while (!stream->getTracks().empty()) {
-      stream->removeTrack(scope.GetIsolate(), stream->getTracks()[0],
-                          scope.GetExceptionState());
-    }
+    while (!stream->getTracks().empty())
+      stream->removeTrack(stream->getTracks()[0], scope.GetExceptionState());
   }
 
   // This will destroy |MediaStream|, |MediaStreamTrack| and its
@@ -251,10 +249,8 @@
     // Transceivers will still reference the stream even after it is "removed".
     // To make the GC tests work, clear the stream from tracks so that the
     // stream does not keep tracks alive.
-    while (!stream->getTracks().empty()) {
-      stream->removeTrack(scope.GetIsolate(), stream->getTracks()[0],
-                          scope.GetExceptionState());
-    }
+    while (!stream->getTracks().empty())
+      stream->removeTrack(stream->getTracks()[0], scope.GetExceptionState());
   }
 
   // This will destroy |MediaStream| and |MediaStreamTrack| (but not
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.h b/third_party/blink/renderer/modules/webaudio/audio_context.h
index c475862..c24cf82 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -128,7 +128,8 @@
   void RequestVisibility(
       RequestVisibilityCallback request_visibility_cb) override {}
   void RecordAutoPictureInPictureInfo(
-      const String& auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
 
   // https://webaudio.github.io/web-audio-api/#AudioContext
   double baseLatency() const;
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
index 3590ab15..8068888 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -339,7 +339,7 @@
         "Cannot decode detached ArrayBuffer");
     // Fall through in order to invoke the error_callback.
   } else if (!audio_data->Transfer(isolate, buffer_contents,
-                                   IgnoreException(isolate))) {
+                                   IGNORE_EXCEPTION)) {
     // Transfer may throw a TypeError, which is not a DOMException. However, the
     // spec requires throwing a DOMException with kDataCloneError. Hence ignore
     // that exception and throw a DOMException instead.
diff --git a/third_party/blink/renderer/modules/webcodecs/encoder_base.cc b/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
index 9e2907d..c2df463 100644
--- a/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
+++ b/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
@@ -143,8 +143,7 @@
 
   // This will fail if |input| is already closed.
   // Remove exceptions relating to cloning closed input.
-  auto* internal_input =
-      input->clone(IgnoreException(script_state_->GetIsolate()));
+  auto* internal_input = input->clone(IGNORE_EXCEPTION);
 
   if (!internal_input) {
     exception_state.ThrowTypeError("Cannot encode closed input.");
diff --git a/third_party/blink/renderer/modules/webtransport/incoming_stream.cc b/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
index 0370ccd..e29a2a1 100644
--- a/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
+++ b/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
@@ -197,7 +197,7 @@
   if (fin_received_.value()) {
     ScriptState::Scope scope(script_state_);
     // Ignore exception because stream will be errored soon.
-    CloseAbortAndReset(IgnoreException(script_state_->GetIsolate()));
+    CloseAbortAndReset(IGNORE_EXCEPTION);
   }
 
   ScriptValue error;
diff --git a/third_party/blink/renderer/platform/bindings/exception_state.h b/third_party/blink/renderer/platform/bindings/exception_state.h
index 204f9e49..fa370e7 100644
--- a/third_party/blink/renderer/platform/bindings/exception_state.h
+++ b/third_party/blink/renderer/platform/bindings/exception_state.h
@@ -175,22 +175,6 @@
   ExceptionState exception_state_;
 };
 
-class IgnoreException {
-  STACK_ALLOCATED();
-
- public:
-  explicit IgnoreException(v8::Isolate* isolate)
-      : exception_state_(nullptr), try_catch_(isolate) {}
-
-  operator ExceptionState&() & = delete;
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  operator ExceptionState&() && { return exception_state_; }
-
- private:
-  ExceptionState exception_state_;
-  v8::TryCatch try_catch_;
-};
-
 // NonThrowableExceptionState never allow call sites to throw an exception.
 // Should be used if an exception must not be thrown.
 class PLATFORM_EXPORT NonThrowableExceptionState final : public ExceptionState {
@@ -248,8 +232,8 @@
 // This can be used as a default value of an ExceptionState parameter like this:
 //
 //     Node* removeChild(Node*, ExceptionState& = IGNORE_EXCEPTION);
-#define IGNORE_EXCEPTION_FOR_TESTING \
-  (::blink::ExceptionState(nullptr).ReturnThis())
+#define IGNORE_EXCEPTION (::blink::ExceptionState(nullptr).ReturnThis())
+#define IGNORE_EXCEPTION_FOR_TESTING IGNORE_EXCEPTION
 
 // Syntax sugar for NonThrowableExceptionState.
 // This can be used as a default value of an ExceptionState parameter like this:
@@ -258,7 +242,7 @@
 #if DCHECK_IS_ON()
 #define ASSERT_NO_EXCEPTION (::blink::NonThrowableExceptionState().ReturnThis())
 #else
-#define ASSERT_NO_EXCEPTION IGNORE_EXCEPTION_FOR_TESTING
+#define ASSERT_NO_EXCEPTION IGNORE_EXCEPTION
 #endif
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc
index ec9e5aad..39b32a01 100644
--- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc
+++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc
@@ -4149,9 +4149,10 @@
 }
 
 void WebMediaPlayerImpl::RecordAutoPictureInPictureInfo(
-    const WebString& auto_picture_in_picture_info) {
+    const media::PictureInPictureEventsInfo::AutoPipInfo&
+        auto_picture_in_picture_info) {
   media_log_->AddEvent<MediaLogEvent::kAutoPictureInPictureInfoChanged>(
-      auto_picture_in_picture_info.Utf8());
+      auto_picture_in_picture_info);
 }
 
 void WebMediaPlayerImpl::ReportSessionUMAs() const {
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.h b/third_party/blink/renderer/platform/media/web_media_player_impl.h
index 175312e..939fc57f 100644
--- a/third_party/blink/renderer/platform/media/web_media_player_impl.h
+++ b/third_party/blink/renderer/platform/media/web_media_player_impl.h
@@ -34,6 +34,7 @@
 #include "media/base/media_observer.h"
 #include "media/base/media_tracks.h"
 #include "media/base/overlay_info.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "media/base/pipeline_impl.h"
 #include "media/base/renderer_factory_selector.h"
 #include "media/base/routing_token_callback.h"
@@ -340,7 +341,8 @@
   void RecordVideoOcclusionState(std::string_view occlusion_state) override;
 
   void RecordAutoPictureInPictureInfo(
-      const WebString& auto_picture_in_picture_info) override;
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override;
 
   bool IsBackgroundMediaSuspendEnabled() const {
     return is_background_suspend_enabled_;
diff --git a/third_party/blink/renderer/platform/testing/DEPS b/third_party/blink/renderer/platform/testing/DEPS
index 6eb46e2..f7d4cd5 100644
--- a/third_party/blink/renderer/platform/testing/DEPS
+++ b/third_party/blink/renderer/platform/testing/DEPS
@@ -55,6 +55,9 @@
     "empty_web_media_player\.cc": [
         "+media/base/video_frame.h",
     ],
+    "empty_web_media_player\.h": [
+        "+media/base/picture_in_picture_events_info.h",
+    ],
     "exception_state_matchers\.cc": [
         "+third_party/blink/renderer/core/dom/dom_exception.h",
     ],
diff --git a/third_party/blink/renderer/platform/testing/empty_web_media_player.h b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
index 3953e4f..95d67da 100644
--- a/third_party/blink/renderer/platform/testing/empty_web_media_player.h
+++ b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
@@ -7,6 +7,7 @@
 
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
+#include "media/base/picture_in_picture_events_info.h"
 #include "third_party/blink/public/platform/web_media_player.h"
 
 namespace cc {
@@ -69,7 +70,8 @@
   void SetPowerExperimentState(bool enabled) override {}
   void SuspendForFrameClosed() override {}
   void RecordAutoPictureInPictureInfo(
-      const WebString& auto_picture_in_picture_info) override {}
+      const media::PictureInPictureEventsInfo::AutoPipInfo&
+          auto_picture_in_picture_info) override {}
   void Paint(cc::PaintCanvas*, const gfx::Rect&, cc::PaintFlags&) override {}
   scoped_refptr<media::VideoFrame> GetCurrentFrameThenUpdate() override;
   std::optional<media::VideoFrame::ID> CurrentFrameId() const override;
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 7b750e0..cccf864 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
@@ -89,6 +89,7 @@
             'base::GetSystemMemoryInfo',
             'base::HashingLRUCache',
             'base::HashInts',
+            'base::HashMetricName',
             'base::HeapArray',
             'base::Hertz',
             'base::HexStringToUInt64',
@@ -650,6 +651,7 @@
             'cc::kManipulationInfoScrollbar',
             'cc::kManipulationInfoTouch',
             'cc::kManipulationInfoWheel',
+            'cc::kMaxOverlapBetweenPages',
             'cc::kMinFractionToStepWhenPaging',
             'cc::kPixelsPerLineStep',
             'cc::MainThreadScrollingReason',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index d58940f..fa7e7eb 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2546,6 +2546,9 @@
 crbug.com/40268415 [ Debug Win11-arm64 ] external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/no-cors.https.html [ Crash ]
 
 # ====== Test expectations added to unblock wpt-importer ======
+crbug.com/413633034 external/wpt/html/webappapis/scripting/event-loops/new-scroll-event-dispatched-at-next-updating-rendering-time.html [ Failure ]
+crbug.com/413595942 external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html [ Failure ]
+crbug.com/413595942 virtual/dialog-close-when-open-removed-disabled/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html [ Failure ]
 crbug.com/406036293 [ Mac ] external/wpt/css/css-overflow/keyboard-scroll.html [ Failure Pass ]
 crbug.com/626703 external/wpt/trusted-types/DOMWindowTimers-setTimeout-setInterval.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/editing/plaintext-only/insertLineBreak.html?white-space=pre [ Failure ]
@@ -6049,8 +6052,6 @@
 crbug.com/1311431 [ Debug Mac13-arm64 ] fast/scroll-behavior/overscroll-behavior.html [ Failure Pass ]
 crbug.com/1311431 [ Mac Release ] fast/scroll-behavior/overscroll-behavior.html [ Failure Pass ]
 
-crbug.com/40701909 [ Mac ] fast/scroll-behavior/smooth-scroll/track-scroll.html [ Failure ]
-
 # These tests fail on SwiftShader FEMU due to a change in log/exp implementation.
 crbug.com/1311456 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit.html [ Crash Failure Pass Timeout ]
 crbug.com/1311456 [ Fuchsia ] tables/mozilla/core/bloomberg.html [ Crash Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 3d81e63c..b819be8e 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2401,10 +2401,6 @@
       "external/wpt/webnn/conformance_tests/cumulative_sum.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/cos.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/div.https.any.html?cpu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?cpu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?cpu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?cpu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.worker.html?cpu",
       "external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/elu.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/equal.https.any.html?cpu",
@@ -2459,6 +2455,10 @@
       "external/wpt/webnn/conformance_tests/pooling.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/pow.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/prelu.https.any.html?cpu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?cpu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?cpu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?cpu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.worker.html?cpu",
       "external/wpt/webnn/conformance_tests/quantizeLinear.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/reciprocal.https.any.html?cpu",
       "external/wpt/webnn/conformance_tests/reduce_l1.https.any.html?cpu",
@@ -2654,10 +2654,6 @@
       "external/wpt/webnn/conformance_tests/cumulative_sum.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/cos.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/div.https.any.html?npu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?npu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?npu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?npu",
-      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.worker.html?npu",
       "external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/elu.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/equal.https.any.html?npu",
@@ -2712,6 +2708,10 @@
       "external/wpt/webnn/conformance_tests/pooling.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/pow.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/prelu.https.any.html?npu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?npu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?npu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?npu",
+      "external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.worker.html?npu",
       "external/wpt/webnn/conformance_tests/quantizeLinear.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/reciprocal.https.any.html?npu",
       "external/wpt/webnn/conformance_tests/reduce_l1.https.any.html?npu",
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 732e74e..297ae953 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
@@ -410,7 +410,7 @@
    },
    "ai": {
     "language_detection": {
-     "availability-detached-crash.tentative.https.html": [
+     "availability-detached-crash.https.html": [
       "5f76d59eb3540048bc0586f2a1ac5b3b313a147e",
       [
        null,
@@ -5341,6 +5341,13 @@
         {}
        ]
       ],
+      "text-decoration-animation-crash.html": [
+       "a20f166c427159f87daf082ae19e384f96f10939",
+       [
+        null,
+        {}
+       ]
+      ],
       "text-decoration-first-line-multi-crash.html": [
        "f6176334ad6e6ef2662a8f89785f601f48a762cf",
        [
@@ -127724,7 +127731,7 @@
       ]
      ],
      "overflow-area-001.html": [
-      "10685c6e84a1683f75e6822b66d9e02645973ccc",
+      "ac0573a7282fa1a739143c2fba8887f625a47762",
       [
        null,
        [
@@ -127737,7 +127744,7 @@
       ]
      ],
      "overflow-area-002.html": [
-      "1287270f1ef645fb4e04a67fb90b368d03b3f208",
+      "24fb312397dbece40a3262a7ce7678d3ad25b467",
       [
        null,
        [
@@ -127750,7 +127757,7 @@
       ]
      ],
      "overflow-area-003.html": [
-      "ff86dea30f10bf9e8411871b98a249500d74832b",
+      "382fb8863393561389aac105ee24c11d446b22b6",
       [
        null,
        [
@@ -133617,609 +133624,607 @@
      ]
     },
     "css-gaps": {
-     "tentative": {
-      "flex": {
-       "flex-gap-decorations-001.html": [
-        "0667693f38c77e814a09930461f91956af9e3c85",
+     "flex": {
+      "flex-gap-decorations-001.html": [
+       "b32e2f13d8cdb39c12e26423f882734f2f5bf4fd",
+       [
+        null,
         [
-         null,
          [
-          [
-           "/css/reference/ref-filled-green-100px-square.xht",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-002.html": [
-        "58740200d4a8cdb2a9c450353adb920df97763fd",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/agnostic/gap-decorations-001-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-003.html": [
-        "effab7fee24a20936dd0cc487947693c8e87a72d",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-003-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-004.html": [
-        "a5c0698e7fa3829cd515323dbb851cc55c30db7d",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-004-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-005.html": [
-        "1688d447d50dbab028f0a8a82815f5661f921d53",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-005-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-006.html": [
-        "3d7dbfd9fedb7513c77b7c5dce132935c8e52617",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-006-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-007.html": [
-        "34853bb32062009381d7d868fcef8c99fdc9ffa8",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-007-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-008.html": [
-        "bd4e73c158c1d329d7c747d69477d19c8ed6c3fd",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-008-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-009.html": [
-        "6bb406c5b0155c7eb65d0117e388bad2272a6ac9",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-009-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-010.html": [
-        "49f6ec962ada962ac2253b148f316df237bbf5e5",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-010-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-011.html": [
-        "7b142e54ec7d0dade4d8e7b5b46a85c70ca6aa8e",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-011-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-012.html": [
-        "2f1f95c00c8c0eed6e11dc10c1e0e90c392ddb6f",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-012-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-013.html": [
-        "1cdf1c2749660c9147dffc07f171f698d6a9fd2b",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-013-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-014.html": [
-        "b7d19549e038ee8efad8d17065071cab00f6b7af",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-014-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-015.html": [
-        "8d100978205684b4a21dfcc2962f6f47bbe5417a",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-015-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-016.html": [
-        "9f956369d48c08793bafca4cd61653dfd963cc77",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-016-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-017.html": [
-        "21fb643a241139915b5d09022513b8f0435b69db",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-017-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-018.html": [
-        "073fa1b9af7a2830021f3d57e0c648fee6084ce8",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/flex/flex-gap-decorations-018-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "flex-gap-decorations-019.html": [
-        "ebac0e732fa76235287a8e3db361b87d2f7b5ff4",
-        [
-         null,
-         [
-          [
-           "/css/reference/ref-filled-green-100px-square.xht",
-           "=="
-          ]
-         ],
-         {}
-        ]
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
        ]
-      },
-      "grid": {
-       "grid-gap-decorations-001.html": [
-        "5fe13a11bbfdb6086dfac68ef20412d6f8a87dc5",
+      ],
+      "flex-gap-decorations-002.html": [
+       "58740200d4a8cdb2a9c450353adb920df97763fd",
+       [
+        null,
         [
-         null,
          [
-          [
-           "/css/reference/ref-filled-green-100px-square.xht",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-002.html": [
-        "7e7e0e4d325a89d96e9e4978da56d410769a5719",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/agnostic/gap-decorations-001-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-003.html": [
-        "f9d07a183ec5231a9a71d348d70cacb231fef329",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-003-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-004.html": [
-        "e28988151a537d3f7df0e0964590c9f2c44ce49d",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-004-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-005.html": [
-        "741977d2eb47402061fc4976d28bbfcf59d47e13",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-005-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-006.html": [
-        "7b1187c4e44bed68af665462107fa34d7a2cfc4a",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-006-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-007.html": [
-        "adc98e4bc03dd1305402ab33ed1c146f7f4c5718",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-007-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-008.html": [
-        "f8dc0df36e2d7a4a30576e60180647bf7b2edb94",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-008-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-009.html": [
-        "0756b9294be1daae5af190bf27235fdc23f9c5f8",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-009-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-010.html": [
-        "d9201b51cea33053cdab2d55ddb10b06acc7f629",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-010-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-011.html": [
-        "c0540398d0533e66d2f86a3aa15cf4998a4e74f4",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-011-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-012.html": [
-        "26ba45a14ff9b1526bfe44e480171e0f95a0e8a7",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-012-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-013.html": [
-        "4a056134089e58169ae0769633c30ed1ca160478",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-013-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-014.html": [
-        "97ad626e1f24cd489a4470c84118d1161b4c46e2",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-014-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-015.html": [
-        "e575c134353b2c97e16a1440e25fc5d6a28cadc9",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-015-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-016.html": [
-        "a0618e44b56b3621c6d0730a83837792f3b59c21",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-016-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-017.html": [
-        "be0f7fc27515b3d35cde376fd99e6b6c87cfdeb4",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-017-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-018.html": [
-        "dc5e2e38e0b2207388c7c7456758fda49935fb88",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-018-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-019.html": [
-        "637e0467a80116bac40b7270d69e0f0aae214129",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-019-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-020.html": [
-        "eb91644053f7b2287e560c952c1c1600eedf34b1",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-020-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-021.html": [
-        "63db3b4e04868b867d10919f8a1a919eb846b790",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-021-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-022.html": [
-        "a22cd1a2610d92706b2ece0ae27cc53edb49ab9b",
-        [
-         null,
-         [
-          [
-           "/css/reference/ref-filled-green-100px-square.xht",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-023.html": [
-        "706f66ebcfac1a0000debf4c753f11ca4f481f16",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-023-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-024.html": [
-        "104df87c7e22568b93b758c9d17a395ca9f496b8",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-024-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-025.html": [
-        "fc48f15f5c27d591a0b417355156b1a66f5c31a8",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-025-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-026.html": [
-        "17e0a99dd844d607859d09aa85749b0946431f02",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-026-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
-       ],
-       "grid-gap-decorations-027.html": [
-        "e39305f74b8a432cd5b8a1e386c75daab6c1433d",
-        [
-         null,
-         [
-          [
-           "/css/css-gaps/tentative/grid/grid-gap-decorations-027-ref.html",
-           "=="
-          ]
-         ],
-         {}
-        ]
+          "/css/css-gaps/agnostic/gap-decorations-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
        ]
-      }
+      ],
+      "flex-gap-decorations-003.html": [
+       "effab7fee24a20936dd0cc487947693c8e87a72d",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-003-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-004.html": [
+       "a5c0698e7fa3829cd515323dbb851cc55c30db7d",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-004-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-005.html": [
+       "1688d447d50dbab028f0a8a82815f5661f921d53",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-005-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-006.html": [
+       "3d7dbfd9fedb7513c77b7c5dce132935c8e52617",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-006-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-007.html": [
+       "34853bb32062009381d7d868fcef8c99fdc9ffa8",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-007-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-008.html": [
+       "bd4e73c158c1d329d7c747d69477d19c8ed6c3fd",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-008-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-009.html": [
+       "6bb406c5b0155c7eb65d0117e388bad2272a6ac9",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-009-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-010.html": [
+       "49f6ec962ada962ac2253b148f316df237bbf5e5",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-010-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-011.html": [
+       "7b142e54ec7d0dade4d8e7b5b46a85c70ca6aa8e",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-011-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-012.html": [
+       "2f1f95c00c8c0eed6e11dc10c1e0e90c392ddb6f",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-012-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-013.html": [
+       "1cdf1c2749660c9147dffc07f171f698d6a9fd2b",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-013-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-014.html": [
+       "b7d19549e038ee8efad8d17065071cab00f6b7af",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-014-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-015.html": [
+       "8d100978205684b4a21dfcc2962f6f47bbe5417a",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-015-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-016.html": [
+       "9f956369d48c08793bafca4cd61653dfd963cc77",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-016-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-017.html": [
+       "21fb643a241139915b5d09022513b8f0435b69db",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-017-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-018.html": [
+       "073fa1b9af7a2830021f3d57e0c648fee6084ce8",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/flex/flex-gap-decorations-018-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "flex-gap-decorations-019.html": [
+       "5bad5f00d496827b83905aabd39b794e84beae46",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
+     },
+     "grid": {
+      "grid-gap-decorations-001.html": [
+       "648f3f26e56892732d8db78ae0e8a852694f9679",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-002.html": [
+       "7e7e0e4d325a89d96e9e4978da56d410769a5719",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/agnostic/gap-decorations-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-003.html": [
+       "f9d07a183ec5231a9a71d348d70cacb231fef329",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-003-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-004.html": [
+       "e28988151a537d3f7df0e0964590c9f2c44ce49d",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-004-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-005.html": [
+       "741977d2eb47402061fc4976d28bbfcf59d47e13",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-005-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-006.html": [
+       "7b1187c4e44bed68af665462107fa34d7a2cfc4a",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-006-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-007.html": [
+       "adc98e4bc03dd1305402ab33ed1c146f7f4c5718",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-007-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-008.html": [
+       "f8dc0df36e2d7a4a30576e60180647bf7b2edb94",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-008-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-009.html": [
+       "0756b9294be1daae5af190bf27235fdc23f9c5f8",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-009-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-010.html": [
+       "d9201b51cea33053cdab2d55ddb10b06acc7f629",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-010-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-011.html": [
+       "c0540398d0533e66d2f86a3aa15cf4998a4e74f4",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-011-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-012.html": [
+       "26ba45a14ff9b1526bfe44e480171e0f95a0e8a7",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-012-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-013.html": [
+       "4a056134089e58169ae0769633c30ed1ca160478",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-013-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-014.html": [
+       "97ad626e1f24cd489a4470c84118d1161b4c46e2",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-014-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-015.html": [
+       "e575c134353b2c97e16a1440e25fc5d6a28cadc9",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-015-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-016.html": [
+       "a0618e44b56b3621c6d0730a83837792f3b59c21",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-016-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-017.html": [
+       "be0f7fc27515b3d35cde376fd99e6b6c87cfdeb4",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-017-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-018.html": [
+       "dc5e2e38e0b2207388c7c7456758fda49935fb88",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-018-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-019.html": [
+       "637e0467a80116bac40b7270d69e0f0aae214129",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-019-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-020.html": [
+       "eb91644053f7b2287e560c952c1c1600eedf34b1",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-020-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-021.html": [
+       "63db3b4e04868b867d10919f8a1a919eb846b790",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-021-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-022.html": [
+       "ad73239bade785ca3a9d176599ddf75d795e7df1",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-023.html": [
+       "706f66ebcfac1a0000debf4c753f11ca4f481f16",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-023-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-024.html": [
+       "104df87c7e22568b93b758c9d17a395ca9f496b8",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-024-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-025.html": [
+       "fc48f15f5c27d591a0b417355156b1a66f5c31a8",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-025-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-026.html": [
+       "17e0a99dd844d607859d09aa85749b0946431f02",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-026-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "grid-gap-decorations-027.html": [
+       "e39305f74b8a432cd5b8a1e386c75daab6c1433d",
+       [
+        null,
+        [
+         [
+          "/css/css-gaps/grid/grid-gap-decorations-027-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
      }
     },
     "css-grid": {
@@ -170310,6 +170315,19 @@
        {}
       ]
      ],
+     "resize-multicol-with-fixed-size-children-002.html": [
+      "9a582bf51771454df6226b8fa26d982c66ec5ea9",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "resize-multicol-with-fixed-size-children.html": [
       "a3963d06a3d71d50833f6df382e5b330011fe059",
       [
@@ -172500,7 +172518,7 @@
        ]
       ],
       "line-clamp-auto-009.tentative.html": [
-       "44d111056c6b021c796ea694d744816125314def",
+       "33d4a9abbae87bf252413324ac61100c7b1c8f55",
        [
         null,
         [
@@ -172513,7 +172531,7 @@
        ]
       ],
       "line-clamp-auto-010.tentative.html": [
-       "cb706bba08e2c9dd6ff05b926be23eb22c9c25b7",
+       "6b69dc0030aee0ed209b031f6da6870e4c874c1d",
        [
         null,
         [
@@ -173696,7 +173714,7 @@
        ]
       ],
       "webkit-line-clamp-036.html": [
-       "b8d7b194f05dd8dc1189900b399188e0d17391d1",
+       "437a93a711d5611f19ce2f0bc6442a483743b7bb",
        [
         null,
         [
@@ -173709,7 +173727,7 @@
        ]
       ],
       "webkit-line-clamp-037.html": [
-       "86015228f88e4c622c4bd1c20cb35a20619075c7",
+       "70c33f75d1107d83ca0e11e567d6a66fe1520cb9",
        [
         null,
         [
@@ -310125,6 +310143,19 @@
         {}
        ]
       ],
+      "circle-calc-dynamic-viewport.html": [
+       "cff8915d6f0ca9396da0afaaf1c27b86925d8459",
+       [
+        null,
+        [
+         [
+          "/svg/geometry/reftests/circle-calc-dynamic-viewport-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "ellipse-001.svg": [
        "e6d394de206f8831136dbe916d55166038ee94c2",
        [
@@ -310209,6 +310240,19 @@
         {}
        ]
       ],
+      "ellipse-calc-dynamic-viewport.html": [
+       "d817b78824633d3c6afea42c86912b0de090ab7c",
+       [
+        null,
+        [
+         [
+          "/svg/geometry/reftests/ellipse-calc-dynamic-viewport-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "percentage-attribute.svg": [
        "44c386d517179621fbf763d0c82c6750ca8d0f63",
        [
@@ -310286,6 +310330,19 @@
         ],
         {}
        ]
+      ],
+      "rect-calc-dynamic-viewport.html": [
+       "6fe39012511d7c57cae0d522a94299b589912f27",
+       [
+        null,
+        [
+         [
+          "/svg/geometry/reftests/rect-calc-dynamic-viewport-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
       ]
      }
     },
@@ -318765,7 +318822,7 @@
     },
     "resources": {
      "locale-util.js": [
-      "87d32ae620bbc050830705bfdb8902d30d3968e7",
+      "cacb11f4f25e04555a4d2a29b9344b19fc79c4d1",
       []
      ],
      "util.js": [
@@ -340598,15 +340655,15 @@
        []
       ],
       "overflow-area-001-ref.html": [
-       "2c2a825f41ef5aaa51f962d0f46d8b9ac099c1a0",
+       "cd13c7e0915933a662996005d195957a28d2d787",
        []
       ],
       "overflow-area-002-ref.html": [
-       "f5d06c6cf3e3227f9c415c6d5e3e11b3d766bd67",
+       "6422d4f7dfb80db8a9adfd8e5a6d4f63aa64782a",
        []
       ],
       "overflow-area-003-ref.html": [
-       "2d9bf19922ce5bbe12327bd6c833fbe167bcb856",
+       "40df8cb5a8b5dd2a865ab23c9ca971bad8a174d7",
        []
       ],
       "overflow-auto-005-ref.html": [
@@ -348674,177 +348731,175 @@
      }
     },
     "css-gaps": {
-     "tentative": {
-      "agnostic": {
-       "gap-decorations-001-ref.html": [
-        "a7314fc7dca1545dacd710c261c7594117a3894a",
-        []
-       ]
-      },
-      "flex": {
-       "flex-gap-decorations-003-ref.html": [
-        "137a63474b80d8cae010511de93d21144052366f",
-        []
-       ],
-       "flex-gap-decorations-004-ref.html": [
-        "f77dd318db7747a5a7107e69afe2a21436aafc33",
-        []
-       ],
-       "flex-gap-decorations-005-ref.html": [
-        "04b3e8d1af4eee718bda8b432c157a45c3a3f623",
-        []
-       ],
-       "flex-gap-decorations-006-ref.html": [
-        "46c4fd49e39239b3940911f514e169f86cc613b0",
-        []
-       ],
-       "flex-gap-decorations-007-ref.html": [
-        "8511c66acf4511670a0268f8bf170a883e2d3924",
-        []
-       ],
-       "flex-gap-decorations-008-ref.html": [
-        "8ca5749417f4eac98bbd9145f8a7cdd6bddc8cc0",
-        []
-       ],
-       "flex-gap-decorations-009-ref.html": [
-        "0adb9af6994746b1e80d056a0c92cd48f2106108",
-        []
-       ],
-       "flex-gap-decorations-010-ref.html": [
-        "8756c5d038c147a561b20ce4ce2aa45e0ade0ab7",
-        []
-       ],
-       "flex-gap-decorations-011-ref.html": [
-        "082be2875a4274d8744b098f8858635c0df8c8d3",
-        []
-       ],
-       "flex-gap-decorations-012-ref.html": [
-        "33be4b76212fde92bf4488574228c37b50edc1b6",
-        []
-       ],
-       "flex-gap-decorations-013-ref.html": [
-        "3d999788023d13c8414796f6839ceafcd94803d5",
-        []
-       ],
-       "flex-gap-decorations-014-ref.html": [
-        "59ce37deaec3e993e594c01fb9ac9887ced10668",
-        []
-       ],
-       "flex-gap-decorations-015-ref.html": [
-        "48745eff931a803f4da17ea6a527b62367720560",
-        []
-       ],
-       "flex-gap-decorations-016-ref.html": [
-        "155e0bfac7b35307f211535f4a940edc7af32dfc",
-        []
-       ],
-       "flex-gap-decorations-017-ref.html": [
-        "031be2abaf1b856b6b33a40958a7fe7438a01ed2",
-        []
-       ],
-       "flex-gap-decorations-018-ref.html": [
-        "644a409bd977acb91812666ac2f9a6e1c1b66830",
-        []
-       ]
-      },
-      "grid": {
-       "grid-gap-decorations-003-ref.html": [
-        "15fc305633d377c286ed9d8fefc6f86aef78c467",
-        []
-       ],
-       "grid-gap-decorations-004-ref.html": [
-        "e4e6b8b458f30c5b8ef5cefbeaf23c13571e0c15",
-        []
-       ],
-       "grid-gap-decorations-005-ref.html": [
-        "aebfba5a20e97e826e27e27c0ce962f6f675eba2",
-        []
-       ],
-       "grid-gap-decorations-006-ref.html": [
-        "94d455c1d86af89ff2b3e872eeaf9f59cd4bde0a",
-        []
-       ],
-       "grid-gap-decorations-007-ref.html": [
-        "5d89f414ed5fa6f259eb95ad9de96e260586ccdd",
-        []
-       ],
-       "grid-gap-decorations-008-ref.html": [
-        "3e2562cfccb8d4a5c6ce1f6f5b5a0781421392ad",
-        []
-       ],
-       "grid-gap-decorations-009-ref.html": [
-        "964f2111eb8d97cf0c18f705115027136ee147a3",
-        []
-       ],
-       "grid-gap-decorations-010-ref.html": [
-        "0c07124b0864605d7fafabece01988036b501019",
-        []
-       ],
-       "grid-gap-decorations-011-ref.html": [
-        "c8824a5296ea8b87fe3a59f01195ab456cd7b46b",
-        []
-       ],
-       "grid-gap-decorations-012-ref.html": [
-        "51ca67dd6a2ba00b2618e11535b1447ccfaa28c9",
-        []
-       ],
-       "grid-gap-decorations-013-ref.html": [
-        "7ebf7c00b181f6480975367ca97dedad9a4221c5",
-        []
-       ],
-       "grid-gap-decorations-014-ref.html": [
-        "7631d5287a85997f1f2f89dcf2a727f3c0a07c65",
-        []
-       ],
-       "grid-gap-decorations-015-ref.html": [
-        "f95324d3320bbb7653963c0a260c8a4a78ff41ea",
-        []
-       ],
-       "grid-gap-decorations-016-ref.html": [
-        "c11380a68aa09f730a4bd2b609274ff94424c772",
-        []
-       ],
-       "grid-gap-decorations-017-ref.html": [
-        "ac0bbd1f1e19cfc5729486fe5109af8f400f655d",
-        []
-       ],
-       "grid-gap-decorations-018-ref.html": [
-        "072dc508ea340c5dbebb14aa8baf06bbb9e7a127",
-        []
-       ],
-       "grid-gap-decorations-019-ref.html": [
-        "e9f8a87979d0e66aa708911798d6ea5bd1b40b42",
-        []
-       ],
-       "grid-gap-decorations-020-ref.html": [
-        "6f31b5a09fc8717d5fcee2f67b7e765d1b9ba2a4",
-        []
-       ],
-       "grid-gap-decorations-021-ref.html": [
-        "de36d206606d1dd324ee2eb458a840eedb81e140",
-        []
-       ],
-       "grid-gap-decorations-023-ref.html": [
-        "e630694c6a55a5e710c6517574b8377527db6d19",
-        []
-       ],
-       "grid-gap-decorations-024-ref.html": [
-        "94b1eccd7470157065bbc6fbe2961b311a1762fd",
-        []
-       ],
-       "grid-gap-decorations-025-ref.html": [
-        "3834da46a5d58d0785bb3b767f21cbeff5e2f7d4",
-        []
-       ],
-       "grid-gap-decorations-026-ref.html": [
-        "d57c622810dcc70270db45742f14faaf75d65357",
-        []
-       ],
-       "grid-gap-decorations-027-ref.html": [
-        "7e0d9cbcd6ff64b17bc8fe57616a37ba29a9fd8e",
-        []
-       ]
-      }
+     "agnostic": {
+      "gap-decorations-001-ref.html": [
+       "a7314fc7dca1545dacd710c261c7594117a3894a",
+       []
+      ]
+     },
+     "flex": {
+      "flex-gap-decorations-003-ref.html": [
+       "137a63474b80d8cae010511de93d21144052366f",
+       []
+      ],
+      "flex-gap-decorations-004-ref.html": [
+       "f77dd318db7747a5a7107e69afe2a21436aafc33",
+       []
+      ],
+      "flex-gap-decorations-005-ref.html": [
+       "04b3e8d1af4eee718bda8b432c157a45c3a3f623",
+       []
+      ],
+      "flex-gap-decorations-006-ref.html": [
+       "46c4fd49e39239b3940911f514e169f86cc613b0",
+       []
+      ],
+      "flex-gap-decorations-007-ref.html": [
+       "8511c66acf4511670a0268f8bf170a883e2d3924",
+       []
+      ],
+      "flex-gap-decorations-008-ref.html": [
+       "8ca5749417f4eac98bbd9145f8a7cdd6bddc8cc0",
+       []
+      ],
+      "flex-gap-decorations-009-ref.html": [
+       "0adb9af6994746b1e80d056a0c92cd48f2106108",
+       []
+      ],
+      "flex-gap-decorations-010-ref.html": [
+       "8756c5d038c147a561b20ce4ce2aa45e0ade0ab7",
+       []
+      ],
+      "flex-gap-decorations-011-ref.html": [
+       "082be2875a4274d8744b098f8858635c0df8c8d3",
+       []
+      ],
+      "flex-gap-decorations-012-ref.html": [
+       "33be4b76212fde92bf4488574228c37b50edc1b6",
+       []
+      ],
+      "flex-gap-decorations-013-ref.html": [
+       "3d999788023d13c8414796f6839ceafcd94803d5",
+       []
+      ],
+      "flex-gap-decorations-014-ref.html": [
+       "59ce37deaec3e993e594c01fb9ac9887ced10668",
+       []
+      ],
+      "flex-gap-decorations-015-ref.html": [
+       "48745eff931a803f4da17ea6a527b62367720560",
+       []
+      ],
+      "flex-gap-decorations-016-ref.html": [
+       "155e0bfac7b35307f211535f4a940edc7af32dfc",
+       []
+      ],
+      "flex-gap-decorations-017-ref.html": [
+       "031be2abaf1b856b6b33a40958a7fe7438a01ed2",
+       []
+      ],
+      "flex-gap-decorations-018-ref.html": [
+       "644a409bd977acb91812666ac2f9a6e1c1b66830",
+       []
+      ]
+     },
+     "grid": {
+      "grid-gap-decorations-003-ref.html": [
+       "15fc305633d377c286ed9d8fefc6f86aef78c467",
+       []
+      ],
+      "grid-gap-decorations-004-ref.html": [
+       "e4e6b8b458f30c5b8ef5cefbeaf23c13571e0c15",
+       []
+      ],
+      "grid-gap-decorations-005-ref.html": [
+       "aebfba5a20e97e826e27e27c0ce962f6f675eba2",
+       []
+      ],
+      "grid-gap-decorations-006-ref.html": [
+       "94d455c1d86af89ff2b3e872eeaf9f59cd4bde0a",
+       []
+      ],
+      "grid-gap-decorations-007-ref.html": [
+       "5d89f414ed5fa6f259eb95ad9de96e260586ccdd",
+       []
+      ],
+      "grid-gap-decorations-008-ref.html": [
+       "3e2562cfccb8d4a5c6ce1f6f5b5a0781421392ad",
+       []
+      ],
+      "grid-gap-decorations-009-ref.html": [
+       "964f2111eb8d97cf0c18f705115027136ee147a3",
+       []
+      ],
+      "grid-gap-decorations-010-ref.html": [
+       "0c07124b0864605d7fafabece01988036b501019",
+       []
+      ],
+      "grid-gap-decorations-011-ref.html": [
+       "c8824a5296ea8b87fe3a59f01195ab456cd7b46b",
+       []
+      ],
+      "grid-gap-decorations-012-ref.html": [
+       "51ca67dd6a2ba00b2618e11535b1447ccfaa28c9",
+       []
+      ],
+      "grid-gap-decorations-013-ref.html": [
+       "7ebf7c00b181f6480975367ca97dedad9a4221c5",
+       []
+      ],
+      "grid-gap-decorations-014-ref.html": [
+       "7631d5287a85997f1f2f89dcf2a727f3c0a07c65",
+       []
+      ],
+      "grid-gap-decorations-015-ref.html": [
+       "f95324d3320bbb7653963c0a260c8a4a78ff41ea",
+       []
+      ],
+      "grid-gap-decorations-016-ref.html": [
+       "c11380a68aa09f730a4bd2b609274ff94424c772",
+       []
+      ],
+      "grid-gap-decorations-017-ref.html": [
+       "ac0bbd1f1e19cfc5729486fe5109af8f400f655d",
+       []
+      ],
+      "grid-gap-decorations-018-ref.html": [
+       "072dc508ea340c5dbebb14aa8baf06bbb9e7a127",
+       []
+      ],
+      "grid-gap-decorations-019-ref.html": [
+       "e9f8a87979d0e66aa708911798d6ea5bd1b40b42",
+       []
+      ],
+      "grid-gap-decorations-020-ref.html": [
+       "6f31b5a09fc8717d5fcee2f67b7e765d1b9ba2a4",
+       []
+      ],
+      "grid-gap-decorations-021-ref.html": [
+       "de36d206606d1dd324ee2eb458a840eedb81e140",
+       []
+      ],
+      "grid-gap-decorations-023-ref.html": [
+       "e630694c6a55a5e710c6517574b8377527db6d19",
+       []
+      ],
+      "grid-gap-decorations-024-ref.html": [
+       "94b1eccd7470157065bbc6fbe2961b311a1762fd",
+       []
+      ],
+      "grid-gap-decorations-025-ref.html": [
+       "3834da46a5d58d0785bb3b767f21cbeff5e2f7d4",
+       []
+      ],
+      "grid-gap-decorations-026-ref.html": [
+       "d57c622810dcc70270db45742f14faaf75d65357",
+       []
+      ],
+      "grid-gap-decorations-027-ref.html": [
+       "7e0d9cbcd6ff64b17bc8fe57616a37ba29a9fd8e",
+       []
+      ]
      }
     },
     "css-grid": {
@@ -356027,11 +356082,11 @@
         []
        ],
        "webkit-line-clamp-036-ref.html": [
-        "0de35e98ab353519664996fba8ab8ef6916a18d0",
+        "321cce96bb34d11082e15e92416214e9aa055a95",
         []
        ],
        "webkit-line-clamp-037-ref.html": [
-        "2927716d76dbc8ebc8b98169c533301214a517aa",
+        "c5050d5d41453102c2b64faa2e2fd2634c2503ac",
         []
        ],
        "webkit-line-clamp-038-ref.html": [
@@ -371265,7 +371320,7 @@
       []
      ],
      "calc-infinity-nan-serialize-length-expected.txt": [
-      "095830023778eece99e09294da5c48a23da7eac1",
+      "cced79a004c0e7f1acdd55298a1221212bdfe94d",
       []
      ],
      "calc-letter-spacing-expected.txt": [
@@ -371335,7 +371390,7 @@
         []
        ],
        "calc-size-interpolation-expansion-expected.txt": [
-        "1f00faa6a79cfbcacc252fac70c2994d90d5eddf",
+        "4107bdeb9a3236ecf1a4d67cee7733c85792fccb",
         []
        ]
       },
@@ -383399,7 +383454,7 @@
       []
      ],
      "trust-token-redemption-supported-by-feature-policy.tentative-expected.txt": [
-      "3afa9fcfc2e7a663d654060cdb63bebfd1eea074",
+      "07cc1d1916b5324520c64d8b75643900eafb0005",
       []
      ],
      "vertical-scroll-main-frame-manual.tentative.html.headers": [
@@ -395599,7 +395654,11 @@
        "349b4eb9117b1c397e656435c8c1adf85964baa8",
        []
       ]
-     }
+     },
+     "shared-workers.tentative.https-expected.txt": [
+      "13173132988cf1e1b591e89ed917e05b4b6f8b57",
+      []
+     ]
     },
     "dom": {
      "WEB_FEATURES.yml": [
@@ -414346,7 +414405,7 @@
      ],
      "resources": {
       "helpers.mjs": [
-       "341befc10565d0759fd517258b2a6883fe6d564a",
+       "22752e4cfed7baaf26afc52db6569feb1af07e2a",
        []
       ],
       "notify-top-early.html": [
@@ -419364,7 +419423,7 @@
      []
     ],
     "sethtml-safety.sub.dat": [
-     "6969835d66d7142625ebf19dfddaa01baaeeef38",
+     "314d5ac37b135f9303a76ad84bce5d8065524140",
      []
     ],
     "sethtml-tree-construction.sub.dat": [
@@ -419372,7 +419431,7 @@
      []
     ],
     "sethtml-unsafety.sub.dat": [
-     "bc162c04e5f7dee88414c2f8cb1794ed58c7e5b7",
+     "3b132a254cac94b46679e80bf9623819ec7ae7f2",
      []
     ],
     "support": {
@@ -424073,32 +424132,24 @@
       ]
      },
      "redirect-to-prefetch-url.https_origin=cross-site-initial-expected.txt": [
-      "934667b71b5fe475df711ec71be69e00a2fc35d6",
+      "effa2dd15da6bdd0a024891ee617b8e10d0b7c66",
       []
      ],
      "redirect-to-prefetch-url.https_origin=cross-site-redirect-expected.txt": [
-      "934667b71b5fe475df711ec71be69e00a2fc35d6",
+      "effa2dd15da6bdd0a024891ee617b8e10d0b7c66",
       []
      ],
      "redirect-to-prefetch-url.https_origin=same-origin-expected.txt": [
-      "934667b71b5fe475df711ec71be69e00a2fc35d6",
+      "effa2dd15da6bdd0a024891ee617b8e10d0b7c66",
       []
      ],
      "resources": {
       "authenticate.py": [
-       "8820781709d30f11cb842f54d8e25d1ed24a4a8e",
+       "ea0c546afffb5ab7701557ce9d7bf54aa8fbc95a",
        []
       ],
       "basic-service-worker.js": [
-       "07beb37d660ed465e6eef57131f3d140cefbb27a",
-       []
-      ],
-      "cacheable-executor.sub.html": [
-       "ba1b3acb0c1198284c74c345b3de5c6d98fc2421",
-       []
-      ],
-      "cacheable-executor.sub.html.headers": [
-       "0ee6ec2ab103e45685829452b0b50b3ac8e3f343",
+       "18432ed62eddb209488a5dd00f39e9c77e071498",
        []
       ],
       "conditional-status.py": [
@@ -424106,7 +424157,7 @@
        []
       ],
       "cookies.py": [
-       "304f999570b22f432681f93c17db4d06d439ad5b",
+       "54aaabee70e697283fddd5016358b0775bf9d0a6",
        []
       ],
       "counting-executor.py": [
@@ -424114,7 +424165,7 @@
        []
       ],
       "executor.sub.html": [
-       "6e4f18ba85405fc5688f6af1b8e7c89f6262576d",
+       "d27acfe100a6a3567606bd64df0b8cd1c5bdbfc1",
        []
       ],
       "executor.sub.html.headers": [
@@ -424126,7 +424177,7 @@
        []
       ],
       "prefetch_nvs_hint.py": [
-       "d912eff90a5b9cc7f726a2a9c9d5da7eb4103fa6",
+       "223135dc8b82ea8f32b7abab8e1e3ed0d77d0bbd",
        []
       ],
       "random_redirect.py": [
@@ -424149,8 +424200,12 @@
        "dd8a9631b4e8d25e0f3a4258806b909b07e682d7",
        []
       ],
+      "util.py": [
+       "1ef6778badf0078af48e06b8ff1b289c8eb5935e",
+       []
+      ],
       "utils.sub.js": [
-       "61411073aecf8b6082938de0cce69e2e54474438",
+       "a90459fdf03822446dc445b294e974587e507717",
        []
       ]
      },
@@ -425611,10 +425666,18 @@
       ]
      },
      "reftests": {
+      "circle-calc-dynamic-viewport-ref.html": [
+       "dfd1f609496d760807e93b4c6e4e90d6f3a383b6",
+       []
+      ],
       "circle-ref.svg": [
        "36ccde7fce5f82093b4930f314f3a2558a5518f9",
        []
       ],
+      "ellipse-calc-dynamic-viewport-ref.html": [
+       "70576349bc034b9fc255061400218649f1e4103e",
+       []
+      ],
       "ellipse-ref.svg": [
        "57e6f4d5e854cd1672f987d5f639bcb1e6186d5e",
        []
@@ -425623,6 +425686,10 @@
        "09fd10f287ba2f0b51f91048ff416d8e03ead34d",
        []
       ],
+      "rect-calc-dynamic-viewport-ref.html": [
+       "84971d4b811c2eb0b0d6d0f8446e326676bae775",
+       []
+      ],
       "rect-ref.svg": [
        "ddfd51eed1f2403e2c6a964cee6a307c0d3838fb",
        []
@@ -465351,17 +465418,17 @@
    },
    "ai": {
     "language_detection": {
-     "detector-iframe.tentative.https.html": [
+     "detector-iframe.https.html": [
       "3e90d36b5aa63a556b82337cdf7a26410b80ac36",
       [
        null,
        {}
       ]
      ],
-     "detector-locale.https.tentative.window.js": [
-      "1991ac3ecfb5259c15b9e561138e8b9c6efebe6c",
+     "detector-locale.https.window.js": [
+      "a1c67db912961d8850bb4a430f92f7be4b450c87",
       [
-       "ai/language_detection/detector-locale.https.tentative.window.html",
+       "ai/language_detection/detector-locale.https.window.html",
        {
         "script_metadata": [
          [
@@ -465384,10 +465451,32 @@
        }
       ]
      ],
-     "detector.https.tentative.window.js": [
-      "28c397db59d2dbd25ab5186e1a355e337d7aad13",
+     "detector.https.window.js": [
+      "7c86d011032a22c9479d2c746152cf299a69561a",
       [
-       "ai/language_detection/detector.https.tentative.window.html",
+       "ai/language_detection/detector.https.window.html",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "Detect english"
+         ],
+         [
+          "global",
+          "window"
+         ],
+         [
+          "script",
+          "../resources/util.js"
+         ]
+        ]
+       }
+      ]
+     ],
+     "detector.optional.https.window.js": [
+      "7ffa1362dd5f97b68e7c678463dd5afa186d10dc",
+      [
+       "ai/language_detection/detector.optional.https.window.html",
        {
         "script_metadata": [
          [
@@ -492707,6 +492796,13 @@
        {}
       ]
      ],
+     "remove-position-try-rules-001.html": [
+      "56ad5cf7b3268304a457ef9cf06fa794cfeb98b0",
+      [
+       null,
+       {}
+      ]
+     ],
      "try-tactic-alignment.html": [
       "b39a92983717e40a37d6092583cbc95ce7b967f5",
       [
@@ -502943,160 +503039,158 @@
      }
     },
     "css-gaps": {
-     "tentative": {
-      "grid": {
-       "grid-gap-decorations-028.html": [
-        "125a34ca9668ecfc430f76e26365c62da17e3b4b",
-        [
-         null,
-         {}
-        ]
+     "grid": {
+      "grid-gap-decorations-028.html": [
+       "125a34ca9668ecfc430f76e26365c62da17e3b4b",
+       [
+        null,
+        {}
        ]
-      },
-      "parsing": {
-       "gap-decorations-bidirectional-shorthands.html": [
-        "9ff3815c21f0f2707c4813b1c32423dbdfe15c19",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-color-computed.html": [
-        "fbc3c3f4c976b344d48a9bd927547214f072e3ab",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-color-invalid.html": [
-        "5a0128e2303ebaef9469330ddfdb290ebeeff912",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-color-valid.html": [
-        "f4cc0156e3f432d6193c1041d65077295496f1c3",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-style-computed.html": [
-        "8c78bf618e3226609ad451e27ff97816b6b73cf6",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-style-invalid.html": [
-        "48ac0680338de220caaa23eae06fbbffdabab634",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-style-valid.html": [
-        "1eb259a82bce43751f6d511f33134a924f5b2aab",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-width-computed.html": [
-        "299cbe0f3bbd8bc495912e59f6866b19513da914",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-width-invalid.html": [
-        "025d52636266b1961cd5c0295a552eb612cf6455",
-        [
-         null,
-         {}
-        ]
-       ],
-       "gap-decorations-width-valid.html": [
-        "bd42d8356234cd51968877986b1927c7af301a12",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-break-computed.html": [
-        "0490428f3e723f0e108aa6875cdaa676e145a859",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-break-invalid.html": [
-        "a6eb68a1644ba848d86e7f92d0c8d121d0280403",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-break-valid.html": [
-        "02f338806196110a12cd8c4a1b36d04b88a6905a",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-outset-computed.html": [
-        "dd59018ccf5356a987cba45e4f1bddba2c6c4bd7",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-outset-invalid.html": [
-        "f39139ade83af7d4b79d400f24c07a10a498d715",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-outset-valid.html": [
-        "6ad45bbc7acd1eb95fd0b015b31dc41667c480d1",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-paint-order-computed.html": [
-        "441be8670d782ccc6dbb252bea4288f87e43918e",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-paint-order-invalid.html": [
-        "b18349a1aedadf9eda10fdea21ab03c99d9b0825",
-        [
-         null,
-         {}
-        ]
-       ],
-       "rule-paint-order-valid.html": [
-        "6a4294f7f4b5c07ea3b556e6cade62f47c6f72b3",
-        [
-         null,
-         {}
-        ]
+      ]
+     },
+     "parsing": {
+      "gap-decorations-bidirectional-shorthands.html": [
+       "9ff3815c21f0f2707c4813b1c32423dbdfe15c19",
+       [
+        null,
+        {}
        ]
-      },
-      "serialization": {
-       "gap-decorations-properties.html": [
-        "4985b5550f25f0ee0a2be125900f16c65c6ec0cf",
-        [
-         null,
-         {}
-        ]
+      ],
+      "gap-decorations-color-computed.html": [
+       "fbc3c3f4c976b344d48a9bd927547214f072e3ab",
+       [
+        null,
+        {}
        ]
-      }
+      ],
+      "gap-decorations-color-invalid.html": [
+       "5a0128e2303ebaef9469330ddfdb290ebeeff912",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-color-valid.html": [
+       "f4cc0156e3f432d6193c1041d65077295496f1c3",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-style-computed.html": [
+       "8c78bf618e3226609ad451e27ff97816b6b73cf6",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-style-invalid.html": [
+       "48ac0680338de220caaa23eae06fbbffdabab634",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-style-valid.html": [
+       "1eb259a82bce43751f6d511f33134a924f5b2aab",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-width-computed.html": [
+       "299cbe0f3bbd8bc495912e59f6866b19513da914",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-width-invalid.html": [
+       "025d52636266b1961cd5c0295a552eb612cf6455",
+       [
+        null,
+        {}
+       ]
+      ],
+      "gap-decorations-width-valid.html": [
+       "bd42d8356234cd51968877986b1927c7af301a12",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-break-computed.html": [
+       "0490428f3e723f0e108aa6875cdaa676e145a859",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-break-invalid.html": [
+       "a6eb68a1644ba848d86e7f92d0c8d121d0280403",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-break-valid.html": [
+       "02f338806196110a12cd8c4a1b36d04b88a6905a",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-outset-computed.html": [
+       "dd59018ccf5356a987cba45e4f1bddba2c6c4bd7",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-outset-invalid.html": [
+       "f39139ade83af7d4b79d400f24c07a10a498d715",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-outset-valid.html": [
+       "6ad45bbc7acd1eb95fd0b015b31dc41667c480d1",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-paint-order-computed.html": [
+       "441be8670d782ccc6dbb252bea4288f87e43918e",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-paint-order-invalid.html": [
+       "b18349a1aedadf9eda10fdea21ab03c99d9b0825",
+       [
+        null,
+        {}
+       ]
+      ],
+      "rule-paint-order-valid.html": [
+       "6a4294f7f4b5c07ea3b556e6cade62f47c6f72b3",
+       [
+        null,
+        {}
+       ]
+      ]
+     },
+     "serialization": {
+      "gap-decorations-properties.html": [
+       "4985b5550f25f0ee0a2be125900f16c65c6ec0cf",
+       [
+        null,
+        {}
+       ]
+      ]
      }
     },
     "css-grid": {
@@ -509768,6 +509862,13 @@
        ]
       ]
      },
+     "resize-multicol-with-fixed-size-children-003.html": [
+      "7e73c8373ed115002f6fb650f6ab5def0c673902",
+      [
+       null,
+       {}
+      ]
+     ],
      "scroll-width-height.tentative.html": [
       "9efaf1bff881264e2da85e28aa911c479d7739cf",
       [
@@ -525866,6 +525967,15 @@
        {}
       ]
      ],
+     "interactivity-inert-animated.html": [
+      "8fc86dabbfd7245c1a88246597757931d7bb3ba3",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
      "interactivity-inert-click-002.html": [
       "4304aa47cf8d4042a731d532f72a4e84800c8d36",
       [
@@ -526662,7 +526772,7 @@
         ]
        ],
        "calc-size-interpolation-expansion.html": [
-        "e4cf50129706940743c2e579d1cc0eaeb067811c",
+        "0b2a60cde7ff5ff93b492d9a1b7a53a231d3e445",
         [
          null,
          {}
@@ -527226,7 +527336,7 @@
       ]
      ],
      "minmax-length-serialize.html": [
-      "bd00ee058859b3b805e621474fa9221f2cd44d17",
+      "1ab6f84637913eb34dd16ac56dd5c7d22dbfbf35",
       [
        null,
        {}
@@ -528554,6 +528664,13 @@
       ]
      ],
      "scoped": {
+      "capture.html": [
+       "06f848d2de16d7a26defcc3279d24622ceb32f54",
+       [
+        null,
+        {}
+       ]
+      ],
       "start-view-transition.html": [
        "a1bc95891956e6678c8ee2ecd51be7d6e94b70ca",
        [
@@ -534410,7 +534527,7 @@
       ]
      ],
      "open-pseudo.html": [
-      "0f3b9f3c37966fa0be02d583ba8549c663e54df1",
+      "c215bf18645c1fda60bd15fffe650e0ba0edcc80",
       [
        null,
        {
@@ -535738,6 +535855,13 @@
       ]
      ]
     },
+    "scoped-registry-initialize.html": [
+     "18dbd0ebeddc0d115d596058fc11d863397c4ee5",
+     [
+      null,
+      {}
+     ]
+    ],
     "state": {
      "ElementInternals-states.html": [
       "1521a8098a36f0c0339fc1e7dceac12d149de385",
@@ -540975,7 +541099,7 @@
        ]
       ],
       "observable-from.any.js": [
-       "3caf99052c84162043cbada1dea784a3d0885676",
+       "20b2c8010ccf3b870bfb9d731b2e0273bdc2384c",
        [
         "dom/observable/tentative/observable-from.any.html",
         {}
@@ -562119,7 +562243,7 @@
       ]
      ],
      "trust-token-redemption-supported-by-feature-policy.tentative.html": [
-      "e349eadc5d1f79b4423052bee9b1903ae6c5e437",
+      "646f8eee548bc186a445b02fca3e6c04c809e07f",
       [
        null,
        {}
@@ -603557,7 +603681,7 @@
         ]
        ],
        "location_hash_set_empty_string.html": [
-        "bfde4e638290c0ef1b4068b399e7428d090544b2",
+        "8eef392e611f5fbe6afa07b4c8ea77a8aef2c440",
         [
          null,
          {}
@@ -633104,12 +633228,16 @@
       ]
      ],
      "credentialless-cache.tentative.window.js": [
-      "99a0f077102b4ab914c553897426c6b160d6ee0a",
+      "0c52d6ced32e1f7b1f20cf04d7fdc5b6250b3f11",
       [
        "html/document-isolation-policy/credentialless-cache.tentative.window.html",
        {
         "script_metadata": [
          [
+          "timeout",
+          "long"
+         ],
+         [
           "script",
           "/common/get-host-info.sub.js"
          ],
@@ -633125,7 +633253,8 @@
           "script",
           "./resources/common.js"
          ]
-        ]
+        ],
+        "timeout": "long"
        }
       ]
      ],
@@ -648294,7 +648423,7 @@
         ]
        ],
        "dialog-requestclose.html": [
-        "f63bc91ab475e3d21bd6002ffae1c669e8a493c2",
+        "61fc27183d7710393ac9b36223946e792bbd7d63",
         [
          null,
          {
@@ -648876,7 +649005,7 @@
        ]
       ],
       "invalid-css-properties.tentative.html": [
-       "2f6fc07b3922e230201e42307f9269bbe0ec48b0",
+       "f8dd5b681161e86a62bc353062d3e1bc83cf334e",
        [
         null,
         {}
@@ -658645,6 +658774,13 @@
          {}
         ]
        ],
+       "new-scroll-event-dispatched-at-next-updating-rendering-time.html": [
+        "a858c205d051ee15d2cd2e47cedb9668ffe32cc4",
+        [
+         null,
+         {}
+        ]
+       ],
        "task_microtask_ordering.html": [
         "c14a043b6ab10ab5e9e08d5bae1088f8dbf5e9c3",
         [
@@ -674318,7 +674454,7 @@
       ]
      ],
      "intercept-async.html": [
-      "d402340b068837ab29807f5d2b083565034e1e8c",
+      "4fa7c88833e0232bd743c206d0d10605c7357d1a",
       [
        "navigation-api/ordering-and-transition/intercept-async.html?currententrychange",
        {}
@@ -674408,7 +674544,7 @@
       ]
      ],
      "navigate-double-intercept.html": [
-      "8baea7bf1ea00ccfa919cb178c12ce8deb16ad5d",
+      "0598fb554e0a8d57b0dfcb0ba365058a2f83dbd5",
       [
        "navigation-api/ordering-and-transition/navigate-double-intercept.html?currententrychange",
        {}
@@ -674419,7 +674555,7 @@
       ]
      ],
      "navigate-in-transition-finished.html": [
-      "6f8b667ce314dae6c7ae06965dbf5369ca5d0a06",
+      "8b3811dd36fd5586930492e5d1d514d61453fc66",
       [
        "navigation-api/ordering-and-transition/navigate-in-transition-finished.html?currententrychange",
        {}
@@ -674430,7 +674566,7 @@
       ]
      ],
      "navigate-intercept-precommitHandler-redirect.html": [
-      "90cf813d0587c2c6bf3c299360890060255ed275",
+      "2f60bfd749d271808cc1f56e2e2566768c607866",
       [
        "navigation-api/ordering-and-transition/navigate-intercept-precommitHandler-redirect.html?currententrychange",
        {}
@@ -674440,8 +674576,19 @@
        {}
       ]
      ],
+     "navigate-intercept-precommitHandler-reject.tentative.html": [
+      "6d19614f7437fa95f41ba5c6cabf977f44bbdcc2",
+      [
+       "navigation-api/ordering-and-transition/navigate-intercept-precommitHandler-reject.tentative.html?currententrychange",
+       {}
+      ],
+      [
+       "navigation-api/ordering-and-transition/navigate-intercept-precommitHandler-reject.tentative.html?no-currententrychange",
+       {}
+      ]
+     ],
      "navigate-intercept-precommitHandler.html": [
-      "27e317cfc6759c8efc01ba40648a315304744e63",
+      "8257e56d44e15e9a29d74c3990f8f29afd58b0d7",
       [
        "navigation-api/ordering-and-transition/navigate-intercept-precommitHandler.html?currententrychange",
        {}
@@ -674452,7 +674599,7 @@
       ]
      ],
      "navigate-intercept-stop.html": [
-      "189475d5de1edabd6d33032885b2f4aa9fdd1811",
+      "1a7faa4e0eebc7ef490c15805086ac16de385fb1",
       [
        "navigation-api/ordering-and-transition/navigate-intercept-stop.html?currententrychange",
        {}
@@ -674463,7 +674610,7 @@
       ]
      ],
      "navigate-intercept.html": [
-      "cdbd8f6ef668432b939477260c5f9b0ced1b80d0",
+      "eec9d3ca119b82406cdd93ad4de6af93f0ef1cf2",
       [
        "navigation-api/ordering-and-transition/navigate-intercept.html?currententrychange",
        {}
@@ -674474,7 +674621,7 @@
       ]
      ],
      "navigate-same-document-intercept-reentrant.html": [
-      "0106e997c9fdc4f408fef6c77046ee877f7da4df",
+      "88715fda355252a1ec299df1c00ce0277fe5fcd2",
       [
        "navigation-api/ordering-and-transition/navigate-same-document-intercept-reentrant.html?currententrychange",
        {}
@@ -674485,7 +674632,7 @@
       ]
      ],
      "navigate-same-document-intercept-reject.html": [
-      "6713edca2d9234ae7e90c04540ffe96894273a14",
+      "05f295177a062bc9f471952cf8d821b7bfad3bce",
       [
        "navigation-api/ordering-and-transition/navigate-same-document-intercept-reject.html?currententrychange",
        {}
@@ -674514,7 +674661,7 @@
       ]
      ],
      "reload-intercept-reject.html": [
-      "7394ce4d17a06887d2c8281ad777e2c8fb8125ad",
+      "96833f314f464724ec32c71837c7439cb687a46a",
       [
        "navigation-api/ordering-and-transition/reload-intercept-reject.html?currententrychange",
        {}
@@ -674525,7 +674672,7 @@
       ]
      ],
      "reload-intercept.html": [
-      "18ff6191c0d05078c097333f9a360d37f6bcdee6",
+      "1494136e199c508564a7449586c2f5579d9be69c",
       [
        "navigation-api/ordering-and-transition/reload-intercept.html?currententrychange",
        {}
@@ -674536,7 +674683,7 @@
       ]
      ],
      "reload-no-popstate.html": [
-      "9c1186344dc7f1c988166b459e67b8b482ba9413",
+      "6c4592b67cc1417e1aa69491c41bb69cc8caba6e",
       [
        null,
        {}
@@ -710188,7 +710335,7 @@
    "speculation-rules": {
     "prefetch": {
      "anonymous-client.https.html": [
-      "bf5896b2dd0626a14e80fe694bd443fea784c4b7",
+      "902724cdb0e08e603d0d41566a2fe889646088f0",
       [
        null,
        {}
@@ -710247,7 +710394,7 @@
       ]
      ],
      "cross-origin-cookies.https.html": [
-      "a16872fcef9c1b836b6b24a380bd12f068d55209",
+      "95c95197a70e200542bf3691f10ee1a73a4deb76",
       [
        null,
        {
@@ -710860,7 +711007,7 @@
       ]
      ],
      "prefetch-uses-cache.sub.https.html": [
-      "c0e9e73c75e877f4e130a26de6764c8966ef8620",
+      "59071c82021ccb3726f58c73a6c5fdf5036fb240",
       [
        "speculation-rules/prefetch/prefetch-uses-cache.sub.https.html?cross-site",
        {
@@ -710938,7 +711085,7 @@
       ]
      ],
      "referrer-policy-from-rules.https.html": [
-      "5024052eb464a38a0f5c244af1deac239af6f30c",
+      "f877bd848246fff7b2145edd106ae48af696b24b",
       [
        "speculation-rules/prefetch/referrer-policy-from-rules.https.html?1-1",
        {}
@@ -710988,7 +711135,7 @@
       ]
      ],
      "referrer-policy.https.html": [
-      "8eb24c45815fd2601d19a7f46152ecc36cb0e6a9",
+      "a1d2aa4b188de828d93174eab1e59d219c56a067",
       [
        "speculation-rules/prefetch/referrer-policy.https.html?1-1",
        {}
@@ -711024,7 +711171,7 @@
       ]
      ],
      "sec-fetch-headers.https.html": [
-      "730f0720995b9b548617e437d7d748f66c83335f",
+      "3d1d1770d789e6a8591c742c4129fb276e7bc289",
       [
        null,
        {
@@ -711035,7 +711182,7 @@
      "tentative": {
       "service-worker": {
        "basic.sub.https.html": [
-        "e4c103535cc9f3ff2ba23fbe2ca7ff4bfb82a576",
+        "bee8e2ff1f4515afa805fa37e86f25effe66c22e",
         [
          "speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=cross-site&sw=fetch-handler",
          {
@@ -711067,6 +711214,18 @@
          }
         ],
         [
+         "speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-modify-referrer",
+         {
+          "timeout": "long"
+         }
+        ],
+        [
+         "speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-modify-url",
+         {
+          "timeout": "long"
+         }
+        ],
+        [
          "speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-to-fallback",
          {
           "timeout": "long"
@@ -711088,7 +711247,7 @@
       }
      },
      "user-pass.https.html": [
-      "011e6137e61ad8afb21070a7d3e341a42061c000",
+      "c6cc51bdb04ba860142de6a789bc30f9d36cf740",
       [
        "speculation-rules/prefetch/user-pass.https.html?cross-origin=false",
        {
@@ -719856,6 +720015,71 @@
        }
       ]
      ],
+     "crashtests": {
+      "garbage-collection.any.js": [
+       "b2ba5cd4c27e9120a9e69c358e6ff5be31b107fd",
+       [
+        "streams/readable-streams/crashtests/garbage-collection.any.html",
+        {
+         "script_metadata": [
+          [
+           "global",
+           "window,worker"
+          ],
+          [
+           "script",
+           "/common/gc.js"
+          ]
+         ]
+        }
+       ],
+       [
+        "streams/readable-streams/crashtests/garbage-collection.any.serviceworker.html",
+        {
+         "script_metadata": [
+          [
+           "global",
+           "window,worker"
+          ],
+          [
+           "script",
+           "/common/gc.js"
+          ]
+         ]
+        }
+       ],
+       [
+        "streams/readable-streams/crashtests/garbage-collection.any.sharedworker.html",
+        {
+         "script_metadata": [
+          [
+           "global",
+           "window,worker"
+          ],
+          [
+           "script",
+           "/common/gc.js"
+          ]
+         ]
+        }
+       ],
+       [
+        "streams/readable-streams/crashtests/garbage-collection.any.worker.html",
+        {
+         "script_metadata": [
+          [
+           "global",
+           "window,worker"
+          ],
+          [
+           "script",
+           "/common/gc.js"
+          ]
+         ]
+        }
+       ]
+      ]
+     },
      "cross-realm-crash.window.js": [
       "5fc7ce37a5f6d2dbd90b5f898bcd7b198f0c50b0",
       [
@@ -752378,7 +752602,7 @@
      ]
     ],
     "audio-data.any.js": [
-     "c18606e2b7054a1965233f9dc602e1b6fdfeaadc",
+     "dd199c485fb22370d7af03cb8b3df6601a825dbe",
      [
       "webcodecs/audio-data.any.html",
       {
@@ -765035,7 +765259,7 @@
       ]
      ],
      "dequantizeLinear.https.any.js": [
-      "35c15055661d4cde7033faca57d6436795f02fc8",
+      "900bb57bacfd379bc81a24b1ec622d914a3e5455",
       [
        "webnn/conformance_tests/dequantizeLinear.https.any.html?cpu",
        {
@@ -771112,6 +771336,441 @@
        }
       ]
      ],
+     "qdq_subgraph.https.any.js": [
+      "8e2d785c436d0245702b841ebd6f2609abff8e63",
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.html?cpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.html?gpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.html?npu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?cpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?gpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?npu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?cpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?gpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?npu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.worker.html?cpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.worker.html?gpu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ],
+      [
+       "webnn/conformance_tests/qdq_subgraph.https.any.worker.html?npu",
+       {
+        "script_metadata": [
+         [
+          "title",
+          "test WebNN `dequantization -> operators -> quantization` subgraph"
+         ],
+         [
+          "global",
+          "window,worker"
+         ],
+         [
+          "variant",
+          "?cpu"
+         ],
+         [
+          "variant",
+          "?gpu"
+         ],
+         [
+          "variant",
+          "?npu"
+         ],
+         [
+          "script",
+          "../resources/utils.js"
+         ],
+         [
+          "timeout",
+          "long"
+         ]
+        ],
+        "timeout": "long"
+       }
+      ]
+     ],
      "quantizeLinear.https.any.js": [
       "af46c8945a3dcbedf573543c58b8299d86e5f2ff",
       [
@@ -775019,7 +775678,7 @@
       ]
      ],
      "subgraph.https.any.js": [
-      "a494a8b7a95d7ff9b4a4be717d7f876a1b061b26",
+      "9b21d6e4f9453fb72c3f7a6850c5690cc9ed87cf",
       [
        "webnn/conformance_tests/subgraph.https.any.html?cpu",
        {
@@ -793652,7 +794311,7 @@
      ]
     ],
     "script-metadata-transform.https.html": [
-     "11c88b469363e3faeff5723e07628f9ba2f1c6b1",
+     "106593879c24e1903beebc146f6c804854cc441b",
      [
       null,
       {
@@ -793682,7 +794341,7 @@
      ]
     ],
     "script-transform-sendKeyFrameRequest.https.html": [
-     "51b797eb68346e928bba18bff94c39f1c9d7a4e4",
+     "9bc75bd7a0e0894cdecab7ffb7eb70d9bf967159",
      [
       null,
       {
diff --git a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js
index 7c86d01..e85ea6d 100644
--- a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js
@@ -1,6 +1,7 @@
 // META: title=Detect english
 // META: global=window
 // META: script=../resources/util.js
+// META: script=../resources/locale-util.js
 
 'use strict';
 
@@ -15,6 +16,9 @@
   const detector = await LanguageDetector.create();
   const results = await detector.detect('Hello world!');
 
+  // must at least have the 'und' result.
+  assert_greater_than_equal(results.length, 1);
+
   // The last result should be 'und'.
   const undResult = results.pop();
   assert_equals(undResult.detectedLanguage, 'und');
@@ -22,24 +26,31 @@
 
   let total_confidence_without_und = 0;
   let last_confidence = 1;
-  for (const {confidence} of results) {
+  for (const {detectedLanguage, confidence} of results) {
+    // All results must be in canonical form.
+    assert_is_canonical(detectedLanguage);
+
     assert_greater_than(confidence, 0);
+    assert_greater_than(confidence, undResult.confidence);
 
     total_confidence_without_und += confidence;
 
-    // Except for 'und', results should be from high to low confidence.
+    // Except for 'und', results must be from high to low confidence.
     assert_greater_than_equal(last_confidence, confidence);
     last_confidence = confidence;
   }
 
-  // Confidences, excluding both 'und' and the last non-'und' result, should be
-  // less than 0.99.
-  assert_less_than(
-      total_confidence_without_und - results.at(-1).confidence, 0.99);
+  // If we have non-und results, their confidences, excluding the last non-'und'
+  // result, must be less than 0.99.
+  if (results.length > 0) {
+    assert_less_than(
+        total_confidence_without_und - results.at(-1).confidence, 0.99);
+  }
 
-  // Confidences, including 'und', should add up to 1.
-  assert_equals(total_confidence_without_und + undResult.confidence, 1);
-}, 'Simple LanguageDetector.detect() call');
+  // Confidences, including 'und', should be less than or equal to one.
+  assert_less_than_equal(
+      total_confidence_without_und + undResult.confidence, 1);
+}, 'LanguageDetector.detect() returns valid results');
 
 promise_test(async t => {
   const error = new Error('CreateMonitorCallback threw an error');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-001.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-001.html
index 10685c6..ac0573a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-001.html
@@ -15,7 +15,7 @@
   overflow: scroll;
   border: solid blue;
   background: aqua;
-  margin: 1em 0.5em;
+  margin: 0.5em;
   float: left;
 }
 div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-002.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-002.html
index 1287270..24fb3123 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-002.html
@@ -16,7 +16,7 @@
   overflow: scroll;
   border: solid blue;
   background: aqua;
-  margin: 1em 0.5em;
+  margin: 0.5em;
   float: left;
 }
 div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-003.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-003.html
index ff86dea..382fb886 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/overflow-area-003.html
@@ -22,7 +22,7 @@
     width: 60px;
     height: 60px;
     background: teal;
-    margin: 1em 0.5em;
+    margin: 0.5em;
     float: left;
   }
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-001-ref.html
index 2c2a825..cd13c7e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-001-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-001-ref.html
@@ -12,7 +12,7 @@
   overflow: scroll;
   border: solid blue;
   background: aqua;
-  margin: 1em 0.5em;
+  margin: 0.5em;
   float: left;
   width: 80px;
   height: 80px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-002-ref.html
index f5d06c6cf..6422d4f7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-002-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-002-ref.html
@@ -13,7 +13,7 @@
   overflow: scroll;
   border: solid blue;
   background: aqua;
-  margin: 1em 0.5em;
+  margin: 0.5em;
   float: left;
   width: 80px;
   height: 80px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-003-ref.html
index 2d9bf19..40df8cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-003-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/overflow-area-003-ref.html
@@ -17,7 +17,7 @@
      width: 60px;
      height: 60px;
      background: teal;
-     margin: 1em 0.5em;
+     margin: 0.5em;
      float: left;
    }
   </style>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize-expected.txt b/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize-expected.txt
new file mode 100644
index 0000000..03a54da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize-expected.txt
@@ -0,0 +1,39 @@
+This is a testharness.js-based test.
+[FAIL] Document: customElementRegistry of an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] Document: customElementRegistry of an upgrade candidate created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] Document: customElementRegistry of an unknown element after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] Document: customElementRegistry of an unknown element created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] Document: customElementRegistry of document and an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+[FAIL] Document: customElementRegistry of an element created after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+[FAIL] HTMLDocument: customElementRegistry of an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] HTMLDocument: customElementRegistry of an upgrade candidate created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] HTMLDocument: customElementRegistry of an unknown element after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] HTMLDocument: customElementRegistry of an unknown element created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] HTMLDocument: customElementRegistry of document and an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+[FAIL] HTMLDocument: customElementRegistry of an element created after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+[FAIL] XHTMLDocument: customElementRegistry of an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] XHTMLDocument: customElementRegistry of an upgrade candidate created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] XHTMLDocument: customElementRegistry of an unknown element after calling CustomElementRegistry.prototype.initialize should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] XHTMLDocument: customElementRegistry of an unknown element created with an explicit customElementRegistry argument should return the registry
+  assert_equals: expected object "[object CustomElementRegistry]" but got null
+[FAIL] XHTMLDocument: customElementRegistry of document and an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+[FAIL] XHTMLDocument: customElementRegistry of an element created after calling CustomElementRegistry.prototype.initialize should return the registry
+  Failed to execute 'initialize' on 'CustomElementRegistry': The provided value is not of type '(Element or ShadowRoot)'.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize.html b/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize.html
new file mode 100644
index 0000000..18dbd0e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/scoped-registry-initialize.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/custom-elements.html#dom-customelementregistry-initialize">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+function runTest(title, makeDocument, customElementRegistry) {
+    test(() => {
+        assert_equals(makeDocument().createElement('a-b').customElementRegistry, null);
+    }, `${title}: customElementRegistry of an upgrade candidate created with a document without a browsing context uses null regsitry by default`);
+
+    test(() => {
+        const element = makeDocument().createElement('a-b');
+        customElementRegistry.initialize(element);
+        assert_equals(element.customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry`);
+
+    test(() => {
+        const element = makeDocument().createElement('a-b', {customElementRegistry});
+        customElementRegistry.initialize(element);
+        assert_equals(element.customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of an upgrade candidate created with an explicit customElementRegistry argument should return the registry`);
+
+    test(() => {
+        const element = makeDocument().createElement('foo');
+        assert_equals(element.customElementRegistry, null);
+    }, `${title}: customElementRegistry of an unknown element created with a document without a browsing context uses null regsitry by default`);
+
+    test(() => {
+        const element = makeDocument().createElement('foo');
+        customElementRegistry.initialize(element);
+        assert_equals(element.customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of an unknown element after calling CustomElementRegistry.prototype.initialize should return the registry`);
+
+    test(() => {
+        const element = makeDocument().createElement('foo', {customElementRegistry});
+        assert_equals(element.customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of an unknown element created with an explicit customElementRegistry argument should return the registry`);
+
+    const addElement = (doc) => {
+        const element = doc.createElement('b-c');
+        if (doc.body)
+            doc.body.appendChild(element);
+        else if (doc.documentElement)
+            doc.documentElement.appendChild(element);
+        else
+            doc.appendChild(element);
+        return element;
+    }
+
+    test(() => {
+        assert_equals(addElement(makeDocument()).customElementRegistry, null);
+    }, `${title}: customElementRegistry of an upgrade candidate connected to a document without a browsing context uses null regsitry by default`);
+
+    test(() => {
+        const doc = makeDocument();
+        const element = addElement(doc);
+        customElementRegistry.initialize(doc);
+        assert_equals(doc.customElementRegistry, customElementRegistry);
+        assert_equals(element.customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of document and an upgrade candidate after calling CustomElementRegistry.prototype.initialize should return the registry`);
+
+    test(() => {
+        const doc = makeDocument();
+        const element = addElement(doc);
+        customElementRegistry.initialize(doc);
+        assert_equals(doc.customElementRegistry, customElementRegistry);
+        assert_equals(element.customElementRegistry, customElementRegistry);
+        element.innerHTML = '<a-b></a-b>';
+        assert_equals(element.querySelector('a-b').customElementRegistry, customElementRegistry);
+    }, `${title}: customElementRegistry of an element created after calling CustomElementRegistry.prototype.initialize should return the registry`);
+}
+
+runTest('Document', () => new Document, new CustomElementRegistry);
+runTest('HTMLDocument', () => document.implementation.createHTMLDocument(), new CustomElementRegistry);
+runTest('XHTMLDocument', () => document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null), new CustomElementRegistry);
+
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string-expected.txt
deleted file mode 100644
index 4150dc96..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] window.location.hash is an empty string
-  assert_true: expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html
index bfde4e63..8eef392 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash_set_empty_string.html
@@ -12,6 +12,6 @@
 
 test(() => {
     assert_true(window.location.hash === '');
-    assert_true(window.location.href === orig_location + '#');
+    assert_true(window.location.href === orig_location);
 }, 'window.location.hash is an empty string');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative.html
index 5ccaa11..0e8c16f8 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative.html
@@ -12,18 +12,26 @@
 }
 </style>
 
-<select>
+<select id=s1>
   <button>button</button>
   <option class=one>one</option>
   <option>two</option>
 </select>
 
-<script>
-promise_test(async () => {
-  const select = document.querySelector('select');
-  const firstOption = document.querySelector('option.one');
-  const arrowUp = '\uE013';
+<select id=s2>
+  <option class=one>one</option>
+  <hr>
+  <optgroup></optgroup>
+  <option class=two>two</option>
+</select>
 
+<script>
+const arrowUp = '\uE013';
+const arrowDown = '\uE015';
+
+promise_test(async () => {
+  const select = document.getElementById('s1');
+  const firstOption = select.querySelector('option.one');
   assert_equals(getComputedStyle(select).appearance, 'base-select',
     'appearance:base-select must be supported in order to run this test.');
 
@@ -38,5 +46,37 @@
     assert_equals(document.activeElement, firstOption,
       'The first option should remain focused after pressing ArrowUp.');
   }
+
+  // close select for the next test
+  await test_driver.click(select);
+  assert_false(select.matches(':open'),
+    'select should be closed at the end of the test.');
 }, 'Attempting to focus the previous option while focused on the first option should not crash.');
+
+promise_test(async () => {
+  const select = document.getElementById('s2');
+  const firstOption = select.querySelector('option.one');
+  const secondOption = select.querySelector('option.two');
+  assert_equals(getComputedStyle(select).appearance, 'base-select',
+    'appearance:base-select must be supported in order to run this test.');
+
+  await test_driver.click(select);
+  assert_true(select.matches(':open'),
+    'select should open after clicking it.');
+
+  assert_equals(document.activeElement, firstOption,
+    'first option should be focused after opening select.');
+
+  await test_driver.send_keys(document.activeElement, arrowDown);
+  assert_equals(document.activeElement, secondOption,
+    'second option should be focused after arrow down.');
+
+  await test_driver.send_keys(document.activeElement, arrowUp);
+  assert_equals(document.activeElement, firstOption,
+    'first option should be focused after arrow up.');
+
+  await test_driver.click(select);
+  assert_false(select.matches(':open'),
+    'select should be closed at the end of the test.');
+}, 'Keyboard navigating backwards over an <hr> and <optgroup> should not crash.');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html
index f63bc91..61fc2718 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-requestclose.html
@@ -10,6 +10,8 @@
 <dialog>Dialog</dialog>
 
 <script>
+const waitForTick = () =>  new Promise(resolve => step_timeout(resolve, 0));
+
 const dialog = document.querySelector('dialog');
 function openDialog(openMethod) {
   assert_false(dialog.open);
@@ -49,7 +51,7 @@
     dialog.setAttribute('closedby',closedby);
   }
   // Be sure any pending close events get fired.
-  await new Promise(resolve => requestAnimationFrame(resolve));
+  await waitForTick();
   return getSignal(t);
 }
 
@@ -75,7 +77,7 @@
       assert_false(dialog.open);
       assert_false(dialog.matches(':open'));
       assert_array_equals(events,['cancel'],'close is scheduled');
-      await new Promise(resolve => requestAnimationFrame(resolve));
+      await waitForTick();
       assert_array_equals(events,['cancel','close']);
     },`requestClose fires both cancel and close ${testDescription}`);
 
@@ -100,7 +102,7 @@
       assert_array_equals(events,['cancel']);
     },`closedby has no effect on dialog.requestClose() ${testDescription}`);
 
-    if (dialog.closedBy != "none") {
+    if (closedby != "none") {
       promise_test(async (t) => {
         const signal = await setup(t,closedby);
         let shouldPreventDefault = true;
@@ -180,7 +182,7 @@
   dialog.requestClose();
   assert_false(dialog.open);
   assert_array_equals(events,['cancel'],'close is scheduled');
-  await new Promise(resolve => requestAnimationFrame(resolve));
+  await waitForTick();
   assert_array_equals(events,['cancel','close']);
 },`requestClose fires cancel and close when dialog is open via attribute`);
 
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-hide-delay.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-hide-delay.tentative.html
index 9ec1c229..8828d879 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-hide-delay.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-hide-delay.tentative.html
@@ -10,8 +10,17 @@
 <script src="/resources/testdriver-vendor.js"></script>
 <script src="resources/invoker-utils.js"></script>
 
+<meta name=variant content=?method=hover>
+<meta name=variant content=?method=focus>
+
 <body>
 <script>
+// The invokerMethod parameter is provided by variants, to
+// effectively split this (slow) test into multiple runs.
+const urlParams = new URLSearchParams(window.location.search);
+invokerMethod = urlParams.get('method');
+description = `method ${invokerMethod}`;
+
 // NOTE about testing methodology:
 // This test uses popovers as an invoker target, and checks whether they are
 // hidden *after* the appropriate de-hover delay. The delay used for testing is
@@ -29,19 +38,19 @@
   // This ensures the tests in this file don't succeed sometimes, due to the above NOTE.
   assert_true(HTMLAnchorElement.prototype.hasOwnProperty('interestTargetElement'),'interesttarget is not supported');
   let {popover, invoker, unrelated} = await createPopoverAndInvokerForHoverTests(t, /*showdelayMs*/ 0, invokerHideDelay);
-  let mouseOverInvoker;
+  let specificInvokerElement;
   invoker.innerHTML = '<span><span>Click me</span></span>';
-  mouseOverInvoker = invoker.firstElementChild.firstElementChild;
-  assert_true(!!mouseOverInvoker);
-  assert_false(popover.matches(':popover-open'));
-  await hoverOver(invoker); // Always start with the mouse over the invoker, which will invoke the popover immediately
-  assert_true(popover.matches(':popover-open'));
-  return {popover, invoker, unrelated, mouseOverInvoker};
+  specificInvokerElement = invoker.firstElementChild.firstElementChild;
+  assert_true(!!specificInvokerElement,'invalid');
+  assert_false(popover.matches(':popover-open'),'popover should start closed');
+  await hoverOrFocus(invokerMethod,invoker); // Always start with the focus/mouse over the invoker, which will invoke the popover immediately
+  assert_true(popover.matches(':popover-open'),'popover should be open');
+  return {popover, invoker, unrelated, specificInvokerElement};
 }
 
 promise_test(async (t) => {
   const {popover,invoker} = await makeTestParts(t);
-  const token = await mouseOverAndRecord(t,invoker);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,invoker);
   await waitForHoverTime(hoverWaitTime);
   assert_true(msSinceMouseOver(token) >= hoverWaitTime,'waitForHoverTime should wait the specified time');
   assert_true(hoverWaitTime > invokerHideDelay,'invokerHideDelay is the value from CSS, hoverWaitTime should be longer than that');
@@ -49,41 +58,55 @@
 
 promise_test(async (t) => {
   const {popover,invoker,unrelated} = await makeTestParts(t);
-  const token = await mouseOverAndRecord(t,unrelated);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,unrelated);
   let showing = popover.matches(':popover-open');
   if (msSinceMouseOver(token) < invokerHideDelay) {
     // Only check if the WPT runner wasn't too slow.
     assert_true(showing,'interest shouldn\'t be immediately lost');
   }
-  await hoverOver(unrelated);
+  await hoverOrFocus(invokerMethod,unrelated);
   await waitForHoverTime(hoverWaitTime);
   assert_false(popover.matches(':popover-open'),'interest should be lost after delay');
-},`The interest-target-hide-delay causes interest to be lost after a delay`);
+},`The interest-target-hide-delay causes interest to be lost after a delay, ${description}`);
 
 promise_test(async (t) => {
   const {popover,invoker,unrelated} = await makeTestParts(t);
-  await hoverOver(popover);
+  // First hover/focus unrelated.
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,unrelated);
+  // Then immediately re-hover/focus the invoker.
+  await hoverOrFocus(invokerMethod,invoker);
+  if (msSinceMouseOver(token) >= invokerHideDelay)
+    return; // The WPT runner was too slow.
+  let showing1 = popover.matches(':popover-open');
+  await waitForHoverTime(hoverWaitTime);
+  let showing2 = popover.matches(':popover-open');
+  assert_true(showing1 && showing2,'interest should not be lost');
+},`Hide delay is cancelled if hover/focus returns, ${description}`);
+
+promise_test(async (t) => {
+  const {popover,invoker,unrelated} = await makeTestParts(t);
+  await hoverOrFocus(invokerMethod,popover);
   await waitForHoverTime(hoverWaitTime);
   assert_true(popover.matches(':popover-open'),'hovering the interest target element should keep it showing');
-  const token = await mouseOverAndRecord(t,unrelated);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,unrelated);
   let showing = popover.matches(':popover-open');
   if (msSinceMouseOver(token) >= invokerHideDelay)
     return; // The WPT runner was too slow.
   assert_true(showing,'subsequently hovering unrelated element shouldn\'t immediately cause interest lost');
-  await hoverOver(unrelated);
+  await hoverOrFocus(invokerMethod,unrelated);
   await waitForHoverTime(hoverWaitTime);
   assert_false(popover.matches(':popover-open'),'hovering unrelated element should cause interest lost after delay');
-},`hovering the interest target element keeps the invoker from losing interest`);
+},`hovering/focusing the interest target element keeps the invoker from losing interest, ${description}`);
 
 promise_test(async (t) => {
-  const {popover,invoker,unrelated,mouseOverInvoker} = await makeTestParts(t);
-  await hoverOver(popover);
+  const {popover,invoker,unrelated,specificInvokerElement} = await makeTestParts(t);
+  await hoverOrFocus(invokerMethod,popover);
   await waitForHoverTime(hoverWaitTime);
-  await hoverOver(mouseOverInvoker);
+  await hoverOrFocus(invokerMethod,specificInvokerElement);
   await waitForHoverTime(hoverWaitTime);
   assert_true(popover.matches(':popover-open'),'Moving hover between invoker and target should not cause interest lost');
-  await hoverOver(unrelated);
+  await hoverOrFocus(invokerMethod,unrelated);
   await waitForHoverTime(hoverWaitTime);
   assert_false(popover.matches(':popover-open'),'Moving hover to unrelated should cause interest lost');
-},`moving hover between the invoker and the target prevents interest lost`);
+},`moving hover/focus between the invoker and the target prevents interest lost, ${description}`);
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-show-delay.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-show-delay.tentative.html
index ca47c0f2..8d7b78d 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-show-delay.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/interesttarget-show-delay.tentative.html
@@ -10,27 +10,41 @@
 <script src="/resources/testdriver-vendor.js"></script>
 <script src="resources/invoker-utils.js"></script>
 
+<meta name=variant content=?layout=plain&method=hover>
+<meta name=variant content=?layout=nested&method=hover>
+<meta name=variant content=?layout=nested-offset&method=hover>
+<meta name=variant content=?layout=plain&method=focus>
+<meta name=variant content=?layout=nested&method=focus>
+<meta name=variant content=?layout=nested-offset&method=focus>
+
 <body>
 <script>
+// The invokerLayout and invokerMethod parameters are provided by variants, to
+// effectively split this (slow) test into multiple runs.
+const urlParams = new URLSearchParams(window.location.search);
+invokerLayout = urlParams.get('layout');
+invokerMethod = urlParams.get('method');
+description = `layout ${invokerLayout}, method ${invokerMethod}`;
+
 // NOTE about testing methodology:
 // This test uses popovers as an invoker target, and checks whether they are
-// triggered *after* the appropriate hover delay. The delay used for testing is
-// kept low, to avoid this test taking too long, but that means that sometimes
-// on a slow bot/client, the hover delay can elapse before we are able to check
-// the popover status. And that can make this test flaky. To avoid that, the
-// msSinceMouseOver() function is used to check that not-too-much time has
-// passed, and if it has, the test is simply skipped. Because of this
+// triggered *after* the appropriate hover/focus delay. The delay used for
+// testing is kept low, to avoid this test taking too long, but that means that
+// sometimes on a slow bot/client, the hover delay can elapse before we are able
+// to check the popover status. And that can make this test flaky. To avoid
+// that, the msSinceMouseOver() function is used to check that not-too-much time
+// has passed, and if it has, the test is simply skipped. Because of this
 // methodology, many/most of these tests will pass on browsers that do not
 // implement `interesttarget`. See the `interesttarget-basic-delays` test.
 
-const invokerShowDelay = 100; // The CSS delay setting.
-const hoverWaitTime = 200; // How long to wait to cover the delay for sure.
+const invokerShowDelayMs = 100; // The CSS delay setting.
+const hoverFocusWaitTimeMs = 200; // How long to wait to cover the delay for sure.
 
 async function makePopoverAndInvoker(test, invokerLayout, showdelayMs) {
   // This ensures the tests in this file don't succeed sometimes, due to the above NOTE.
   assert_true(HTMLAnchorElement.prototype.hasOwnProperty('interestTargetElement'),'interesttarget is not supported');
   if (showdelayMs === undefined) {
-    showdelayMs = invokerShowDelay;
+    showdelayMs = invokerShowDelayMs;
   }
   let {popover, invoker, unrelated} = await createPopoverAndInvokerForHoverTests(test, showdelayMs, /*hidedelayMs*/10000000);
   invoker.setAttribute('class','invoker');
@@ -53,131 +67,142 @@
       // Reassign invoker to the child:
       invoker = invoker.appendChild(document.createElement('div'));
       invoker.textContent = 'Invoker child';
+      invoker.tabIndex = 0;
       invoker.setAttribute('style','position:relative; top:300px; left:300px;');
       break;
     default:
       assert_unreached(`Invalid invokerLayout ${invokerLayout}`);
   }
-  test.add_cleanup(async () => {
+  test.add_cleanup(() => {
     originalInvoker.remove();
-    await waitForRender();
   });
-  await hoverOver(unrelated); // Start by mousing over the unrelated element
-  await waitForRender();
   assert_false(popover.matches(':popover-open'),'Popover should start out closed');
   return {popover,invoker,unrelated,reassignInvokerTargetFn};
 }
 
-["plain","nested","nested-offset"].forEach(invokerLayout => {
-  promise_test(async (t) => {
-    const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
-    const token = await mouseOverAndRecord(t,invoker);
-    let showing = popover.matches(':popover-open');
-    // See NOTE above.
-    if (msSinceMouseOver(token) < invokerShowDelay)
-      assert_false(showing,'interest should not be shown immediately');
-    await waitForHoverTime(hoverWaitTime);
-    assert_true(msSinceMouseOver(token) >= hoverWaitTime,'waitForHoverTime should wait the specified time');
-    assert_true(popover.matches(':popover-open'),'interest should be shown after the delay');
-    assert_true(hoverWaitTime > invokerShowDelay,'invokerShowDelay is the CSS setting, hoverWaitTime should be longer than that');
-  },`interesttarget fires after a delay, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,invoker);
+  let showing = popover.matches(':popover-open');
+  // See NOTE above.
+  if (msSinceMouseOver(token) < invokerShowDelayMs)
+    assert_false(showing,'interest should not be shown immediately');
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  assert_true(msSinceMouseOver(token) >= hoverFocusWaitTimeMs,'waitForHoverTime should wait the specified time');
+  assert_true(popover.matches(':popover-open'),'interest should be shown after the delay');
+  assert_true(hoverFocusWaitTimeMs > invokerShowDelayMs,'invokerShowDelayMs is the CSS setting, hoverFocusWaitTimeMs should be longer than that');
+},`interesttarget fires after a delay, ${description}`);
 
-  promise_test(async (t) => {
-    const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
-    assert_false(popover.matches(':popover-open'));
-    invoker.click(); // Click the invoker
-    assert_false(popover.matches(':popover-open'),'Clicking the invoker should not "show interest"');
-  },`interesttarget should not trigger via mouse click, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
+  assert_false(popover.matches(':popover-open'));
+  invoker.click(); // Click the invoker
+  assert_false(popover.matches(':popover-open'),'Clicking the invoker should not "show interest"');
+},`interesttarget should not trigger via mouse click, ${description}`);
 
-  promise_test(async (t) => {
-    const longerHoverDelay = hoverWaitTime*2;
-    const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout,longerHoverDelay);
-    const token = await mouseOverAndRecord(t,invoker);
-    await waitForHoverTime(hoverWaitTime);
-    showing = popover.matches(':popover-open');
-    if (msSinceMouseOver(token) >= longerHoverDelay)
-      return; // The WPT runner was too slow.
-    assert_false(showing,'interesttarget should respect CSS setting');
-  },`interesttarget interest-target-show-delay is respected, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const longerHoverDelay = hoverFocusWaitTimeMs*2;
+  const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout,longerHoverDelay);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,invoker);
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  showing = popover.matches(':popover-open');
+  if (msSinceMouseOver(token) >= longerHoverDelay)
+    return; // The WPT runner was too slow.
+  assert_false(showing,'interesttarget should respect CSS setting');
+},`interesttarget interest-target-show-delay is respected, ${description}`);
 
-  promise_test(async (t) => {
-    const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
-    popover.showPopover();
-    assert_true(popover.matches(':popover-open'));
-    let gotInterest = false;
-    popover.addEventListener('interest',() => (gotInterest=true),{once:true});
-    await hoverOver(invoker);
-    const stillOpen = popover.matches(':popover-open');
-    await waitForHoverTime(hoverWaitTime);
-    assert_true(popover.matches(':popover-open'),'popover should stay showing after delay');
-    assert_true(stillOpen,'popover should have been open before the delay also');
-    assert_true(gotInterest,'interest event should still be fired');
-  },`interesttarget does not close an already-open popover, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const longerHoverDelay = hoverFocusWaitTimeMs*4;
+  const {popover,invoker,unrelated} = await makePopoverAndInvoker(t,invokerLayout,longerHoverDelay);
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,invoker);
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  showing1 = popover.matches(':popover-open');
+  await hoverOrFocus(invokerMethod,unrelated);
+  if (msSinceMouseOver(token) >= longerHoverDelay)
+    return; // The WPT runner was too slow.
+  await waitForHoverTime(longerHoverDelay);
+  showing2 = popover.matches(':popover-open');
+  assert_false(showing1,'interest shouldn\'t be shown immediately');
+  assert_false(showing2,'because target was de-hovered/de-focused before the delay elapsed, interest should never be shown');
+},`Show delay is cancelled if hover/focus changes, ${description}`);
 
-  promise_test(async (t) => {
-    const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
-    popover.remove(); // Remove from the document
-    let gotInterest = false;
-    popover.addEventListener('interest',() => (gotInterest=true),{once:true});
-    await hoverOver(invoker);
-    await waitForHoverTime(hoverWaitTime);
-    assert_false(gotInterest,'interest should not be shown if the target is removed');
-    // Now put it back in the document and make sure it doesn't trigger.
-    document.body.appendChild(popover);
-    await waitForHoverTime(hoverWaitTime);
-    assert_false(gotInterest,'interest should not be shown even when returned to the document');
-  },`interesttarget does nothing when the target is moved out of the document, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
+  popover.showPopover();
+  assert_true(popover.matches(':popover-open'));
+  let gotInterest = false;
+  popover.addEventListener('interest',() => (gotInterest=true),{once:true});
+  await hoverOrFocus(invokerMethod,invoker);
+  const stillOpen = popover.matches(':popover-open');
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  assert_true(popover.matches(':popover-open'),'popover should stay showing after delay');
+  assert_true(stillOpen,'popover should have been open before the delay also');
+  assert_true(gotInterest,'interest event should still be fired');
+},`interesttarget does not close an already-open popover, ${description}`);
 
-  promise_test(async (t) => {
-    const {popover,invoker,reassignInvokerTargetFn} = await makePopoverAndInvoker(t,invokerLayout);
-    const popover2 = document.createElement('div');
-    popover2.popover = 'auto';
-    document.body.appendChild(popover2);
-    t.add_cleanup(() => popover2.remove());
-    const token = await mouseOverAndRecord(t,invoker);
-    let eitherShowing = popover.matches(':popover-open') || popover2.matches(':popover-open');
-    reassignInvokerTargetFn(popover2);
-    // See NOTE above.
-    if (msSinceMouseOver(token) >= invokerShowDelay)
-      return; // The WPT runner was too slow.
-    assert_false(eitherShowing,'interest should should not be shown immediately');
-    await waitForHoverTime(hoverWaitTime);
-    assert_false(popover.matches(':popover-open'),'old target should not receive interest, since interesttarget was reassigned');
-    assert_false(popover2.matches(':popover-open'),'new target should not receive interest, since interesttarget was reassigned');
-  },`interesttarget does nothing when the target changes, invokerLayout=${invokerLayout}`);
+promise_test(async (t) => {
+  const {popover,invoker} = await makePopoverAndInvoker(t,invokerLayout);
+  popover.remove(); // Remove from the document
+  let gotInterest = false;
+  popover.addEventListener('interest',() => (gotInterest=true),{once:true});
+  await hoverOrFocus(invokerMethod,invoker);
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  assert_false(gotInterest,'interest should not be shown if the target is removed');
+  // Now put it back in the document and make sure it doesn't trigger.
+  document.body.appendChild(popover);
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  assert_false(gotInterest,'interest should not be shown even when returned to the document');
+},`interesttarget does nothing when the target is moved out of the document, ${description}`);
 
-  promise_test(async (t) => {
-    const {popover,invoker,unrelated} = await makePopoverAndInvoker(t,invokerLayout,/*showdelayMs*/0);
-    const invoker2 = document.createElement('button');
-    invoker2.interestTargetElement = popover;
-    document.body.appendChild(invoker2);
-    t.add_cleanup(() => invoker2.remove());
-    invoker2.setAttribute('style',`
-      interest-target-show-delay: 0s;
-      interest-target-hide-delay: 10000s;
-      position:fixed;
-      top:300px;
-    `);
-    invoker2.innerText = 'Invoker 2';
-    let events = [];
-    popover.addEventListener('interest',() => events.push('interest'));
-    popover.addEventListener('loseinterest',() => events.push('lose interest'));
-    popover.addEventListener('beforetoggle',(e) => events.push(e.newState));
-    assert_array_equals(events,[]);
-    await hoverOver(invoker);
-    assert_array_equals(events,['interest','open']);
-    // Different invoker for same target - should first (immediately) lose interest on old invoker.
-    await hoverOver(invoker2);
-    assert_array_equals(events,['interest','open','lose interest','closed','interest','open']);
-    // Lose interest delays are long, so nothing happens here.
-    events = [];
-    await hoverOver(unrelated);
-    assert_array_equals(events,[]);
-    // Back to the same invoker - shouldn't re-fire events.
-    await hoverOver(invoker2);
-    assert_array_equals(events,[]);
-    assert_true(popover.matches(':popover-open'));
-    popover.hidePopover();
-  },`moving hover between two invokers for the same target does the right thing, invokerLayout=${invokerLayout}`);
-});
+promise_test(async (t) => {
+  const {popover,invoker,reassignInvokerTargetFn} = await makePopoverAndInvoker(t,invokerLayout);
+  const popover2 = document.createElement('div');
+  popover2.popover = 'auto';
+  document.body.appendChild(popover2);
+  t.add_cleanup(() => popover2.remove());
+  const token = await mouseOverOrFocusAndRecord(t,invokerMethod,invoker);
+  let eitherShowing = popover.matches(':popover-open') || popover2.matches(':popover-open');
+  reassignInvokerTargetFn(popover2);
+  // See NOTE above.
+  if (msSinceMouseOver(token) >= invokerShowDelayMs)
+    return; // The WPT runner was too slow.
+  assert_false(eitherShowing,'interest should should not be shown immediately');
+  await waitForHoverTime(hoverFocusWaitTimeMs);
+  assert_false(popover.matches(':popover-open'),'old target should not receive interest, since interesttarget was reassigned');
+  assert_false(popover2.matches(':popover-open'),'new target should not receive interest, since interesttarget was reassigned');
+},`interesttarget does nothing when the target changes, ${description}`);
+
+promise_test(async (t) => {
+  const {popover,invoker,unrelated} = await makePopoverAndInvoker(t,invokerLayout,/*showdelayMs*/0);
+  const invoker2 = document.createElement('button');
+  invoker2.interestTargetElement = popover;
+  document.body.appendChild(invoker2);
+  t.add_cleanup(() => invoker2.remove());
+  invoker2.setAttribute('style',`
+    interest-target-show-delay: 0s;
+    interest-target-hide-delay: 10000s;
+    position:fixed;
+    top:300px;
+  `);
+  invoker2.innerText = 'Invoker 2';
+  let events = [];
+  popover.addEventListener('interest',() => events.push('interest'));
+  popover.addEventListener('loseinterest',() => events.push('lose interest'));
+  popover.addEventListener('beforetoggle',(e) => events.push(e.newState));
+  assert_array_equals(events,[]);
+  await hoverOrFocus(invokerMethod,invoker);
+  assert_array_equals(events,['interest','open']);
+  // Different invoker for same target - should first (immediately) lose interest on old invoker.
+  await hoverOrFocus(invokerMethod,invoker2);
+  assert_array_equals(events,['interest','open','lose interest','closed','interest','open']);
+  // Lose interest delays are long, so nothing happens here.
+  events = [];
+  await hoverOrFocus(invokerMethod,unrelated);
+  assert_array_equals(events,[]);
+  // Back to the same invoker - shouldn't re-fire events.
+  await hoverOrFocus(invokerMethod,invoker2);
+  assert_array_equals(events,[]);
+  assert_true(popover.matches(':popover-open'));
+  popover.hidePopover();
+},`moving hover/focus between two invokers for the same target does the right thing, ${description}`);
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/resources/invoker-utils.js b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/resources/invoker-utils.js
index f731ab7c..bc43e738c 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/resources/invoker-utils.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/the-button-element/interest-target/resources/invoker-utils.js
@@ -31,23 +31,41 @@
   await waitForRender();
 }
 function mouseOverAndRecord(t,element) {
-  let mouseMoveInfo;
-  t.add_cleanup(() => mouseMoveInfo?.controller.abort());
-  const controller = new AbortController();
-  mouseMoveInfo = {element, controller, moved: false, started: performance.now()};
-  document.addEventListener("mousemove", (e) => {mouseMoveInfo.moved = true;}, {signal: controller.signal});
+  let timingInfo = {element, started: performance.now()};
   return (new test_driver.Actions())
       .pointerMove(0, 0, {origin: element})
       .send()
-      .then(() => mouseMoveInfo);
+      .then(() => timingInfo);
+}
+function focusAndRecord(t,element) {
+  let timingInfo = {element, started: performance.now()};
+  element.focus();
+  return timingInfo;
+}
+async function hoverOrFocus(invokerMethod,element) {
+  if (invokerMethod === 'hover') {
+    await hoverOver(element);
+  } else {
+    assert_equals(invokerMethod,'focus');
+    element.focus();
+    await waitForRender();
+  }
+}
+async function mouseOverOrFocusAndRecord(t,invokerMethod,element) {
+  if (invokerMethod === 'hover') {
+    return await mouseOverAndRecord(t,element);
+  } else {
+    assert_equals(invokerMethod,'focus');
+    return focusAndRecord(t,element);
+  }
 }
 // Note that this may err on the side of being too large (reporting a number
 // that is larger than the actual time since the mouseover happened), due to how
-// `mousemoveInfo.started` is initialized, on first mouse move. However, this
+// `timingInfo.started` is initialized, on first mouse move. However, this
 // function is intended to be used as a detector for the test harness taking too
 // long for some tests, so it's ok to be conservative.
-function msSinceMouseOver(mouseMoveInfo) {
-  return performance.now() - mouseMoveInfo.started;
+function msSinceMouseOver(timingInfo) {
+  return performance.now() - timingInfo.started;
 }
 async function waitForHoverTime(hoverWaitTimeMs) {
   await new Promise(resolve => step_timeout(resolve,hoverWaitTimeMs));
@@ -56,10 +74,12 @@
 
 async function createPopoverAndInvokerForHoverTests(test, showdelayMs, hideDelayMs) {
   const unrelated = document.createElement('div');
+  unrelated.tabIndex = 0;
   document.body.appendChild(unrelated);
   unrelated.textContent = 'Unrelated';
   unrelated.setAttribute('style','position:fixed; top:0;');
-  // Ensure we never hover over an active interesttarget element.
+  // Ensure we never hover over or focus on an active interesttarget element.
+  unrelated.focus();
   await hoverOver(unrelated);
   const popover = document.createElement('div');
   popover.popover = 'auto';
@@ -82,11 +102,10 @@
   assert_equals(actualShowDelay,showdelayMs,'interest-target-show-delay is incorrect');
   const actualHideDelay = Number(getComputedStyle(invoker).interestTargetHideDelay.slice(0,-1))*1000;
   assert_equals(actualHideDelay,hideDelayMs,'interest-target-hide-delay is incorrect');
-  test.add_cleanup(async () => {
+  test.add_cleanup(() => {
     popover.remove();
     invoker.remove();
     unrelated.remove();
-    await waitForRender();
   });
   assert_false(popover.matches(':popover-open'),'The popover should start out closed');
   return {popover, invoker, unrelated};
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/event-loops/new-scroll-event-dispatched-at-next-updating-rendering-time.html b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/event-loops/new-scroll-event-dispatched-at-next-updating-rendering-time.html
new file mode 100644
index 0000000..a858c20
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/event-loops/new-scroll-event-dispatched-at-next-updating-rendering-time.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="help" href="https://html.spec.whatwg.org/#event-loop-processing-model">
+<link rel="help" href="https://issues.chromium.org/issues/397737222">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+</style>
+<iframe width="300" height="300" srcdoc="
+  <style>
+    html {
+      transition: color 1s step-start;
+    }
+    .scroller {
+      overflow: auto;
+      width: 100%;
+      height: 100px;
+    }
+    .spacer {
+      height: 500px;
+    }
+  </style>
+  <div class='scroller'>
+    <div class='spacer'></div>
+  </div>
+  <div class='scroller'>
+    <div class='spacer'></div>
+  </div>
+  "></iframe>
+<script>
+promise_test(async function() {
+  await new Promise(resolve => window.addEventListener("load", resolve, { once: true }));
+
+  const iframe = document.querySelector("iframe");
+  const mql = iframe.contentWindow.matchMedia("(max-width: 300px)");
+  assert_true(mql.matches, "");
+
+  // Set up a MQL change event listener to receive the event in between
+  // scroll and transitionrun events.
+  let timeOnMQLChange = null;
+  iframe.width = "400";
+  const mqlChangeEvent = new Promise(resolve => {
+    mql.addEventListener("change", () => {
+      timeOnMQLChange = performance.now();
+      resolve();
+    }, { once: true });
+  });
+
+  // There are two scroll containers, setup a scroll event listener for one
+  // of them.
+  const scrollers = iframe.contentDocument.querySelectorAll(".scroller");
+  let timeOnScrollEventOnAnotherScroller = null;
+  scrollers[1].addEventListener("scroll", () => {
+    timeOnScrollEventOnAnotherScroller = performance.now();
+  }, { once: true });
+
+  // Setup another scroll event listener for the other scroll container.
+  const scrollEventPromise = new Promise(resolve => {
+    scrollers[0].addEventListener("scroll", resolve, { once: true });
+  });
+  // And scroll the scroller.
+  scrollers[0].scrollTop = 10;
+
+  // Await the scroll event.
+  await scrollEventPromise;
+
+  const timeOnScrollEvent = performance.now();
+
+  // Scroll the other scroller.
+  scrollers[1].scrollTop = 10;
+
+  assert_equals(timeOnScrollEventOnAnotherScroller, null,
+    "The new scroll event should not yet have been dispatched");
+
+  // Trigger a CSS transition.
+  let timeOnTransitionRun = null;
+  const transitionrunEventPromise = new Promise(resolve => {
+    iframe.contentDocument.documentElement.addEventListener("transitionrun", () => {
+      timeOnTransitionRun = performance.now();
+      resolve();
+    }, { once: true });
+  });
+  iframe.contentDocument.documentElement.style.color = "blue";
+  getComputedStyle(iframe.contentDocument.documentElement).color;
+
+  // Now it's time to receive the MQL change event.
+  await mqlChangeEvent;
+  assert_less_than(timeOnScrollEvent, timeOnMQLChange,
+    "The MQL change event should have been dispatched after the first scroll event");
+  assert_equals(timeOnScrollEventOnAnotherScroller, null,
+    "The new scroll event should not yet have been dispatched");
+
+  // Await the transitionrun event.
+  await transitionrunEventPromise;
+
+  assert_less_than(timeOnScrollEvent, timeOnTransitionRun,
+    "The transitionrun event should have been dispatched after the first scroll event");
+  assert_equals(timeOnScrollEventOnAnotherScroller, null,
+    "The new scroll event should not yet have been dispatched");
+
+  // Await a requestAnimationFrame callback.
+  await new Promise(resolve => requestAnimationFrame(resolve));
+
+  assert_equals(timeOnScrollEventOnAnotherScroller, null,
+    "The new scroll event should not yet have been dispatched");
+
+  // Await one more requestAnimationFrame callback.
+  await new Promise(resolve => requestAnimationFrame(resolve));
+
+  assert_not_equals(timeOnScrollEventOnAnotherScroller, null,
+    "The new scroll event should now have been dispatched");
+  assert_less_than(timeOnTransitionRun, timeOnScrollEventOnAnotherScroller,
+    "The new scroll event should have been dispatched after the transitionrun event");
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/nav-tracking-mitigations/META.yml b/third_party/blink/web_tests/external/wpt/nav-tracking-mitigations/META.yml
index 00a8c7b..9e7ffe4 100644
--- a/third_party/blink/web_tests/external/wpt/nav-tracking-mitigations/META.yml
+++ b/third_party/blink/web_tests/external/wpt/nav-tracking-mitigations/META.yml
@@ -2,8 +2,9 @@
 suggested_reviewers:
   - amaliev
   - bvandersloot-mozilla
+  - g-ortuno
   - hoodjoshua
+  - MrPickles
   - njeunje
-  - rtarpine-google
+  - svendlarsen
   - Trikolon
-  - wanderview
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/reading-flow/tentative/carousel-grid-order.html b/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/reading-flow/tentative/carousel-grid-order.html
new file mode 100644
index 0000000..89b3f8d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/reading-flow/tentative/carousel-grid-order.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<title>CSS Display: reading-flow with value flex-flow on carousel container</title>
+<link rel="help" href="https://drafts.csswg.org/css-display-4/#reading-flow">
+<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-marker-next-focus">
+<link rel="author" title="Di Zhang" href="mailto:dizhangg@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src='../../resources/shadow-dom.js'></script>
+<script src="../../resources/focus-utils.js"></script>
+
+<style>
+  #scroller {
+    width: 120px;
+    height: 100px;
+    overflow-x: auto;
+    scroll-marker-group: before;
+    white-space: nowrap;
+    display: grid;
+    grid-auto-flow: column;
+    reading-flow: grid-order;
+  }
+
+  #scroller div {
+    display: inline-block;
+    width: 100px;
+    height: 100px;
+  }
+
+  #scroller div::scroll-marker {
+    content: "#";
+    background: white;
+  }
+
+</style>
+
+
+
+<div class="test-case" data-expect="scroller,C,A,B"
+      data-description="Grid items in carousel should follow grid-order reading flow">
+  <div id="scroller">
+    <div id="A" tabindex="0" style="order: 2; background: red"></div>
+    <div id="B" tabindex="0" style="order: 3; background: yellow"></div>
+    <div id="C" tabindex="0" style="order: 1; background: blue"></div>
+  </div>
+</div>
+
+<script>
+runFocusTestCases();
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/audio-data.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/audio-data.any.js
index c18606e..dd199c4 100644
--- a/third_party/blink/web_tests/external/wpt/webcodecs/audio-data.any.js
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/audio-data.any.js
@@ -88,6 +88,15 @@
 
 test(t => {
   let data = createDefaultAudioData();
+  data.close();
+  assert_equals(data.sampleRate, 0);
+  assert_equals(data.numberOfFrames, 0);
+  assert_equals(data.numberOfChannels, 0);
+  assert_equals(data.format, null);
+}, 'AudioData close');
+
+test(t => {
+  let data = createDefaultAudioData();
 
   let clone = data.clone();
 
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js
index 8e2d785..8f6f2246 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js
@@ -474,6 +474,90 @@
       }
     }
   },
+  {
+    'name': 'quantized transpose',
+    'graph': {
+      'inputs': {
+        'input': {
+          'data': [
+            0.6811466217041016, 0.0479511022567749, 0.33355462551116943,
+            0.19882695376873016, 0.41167140007019043, 0.07934240251779556,
+          ],
+          'descriptor': {shape: [1, 1, 2, 3], dataType: 'float32'},
+          'constant': false
+        },
+        'inputScale': {
+          'data': [0.003921568859368563],
+          'descriptor': {shape: [1], dataType: 'float32'},
+          'constant': true
+        },
+        'inputZeroPoint': {
+          'data': [-128],
+          'descriptor': {shape: [1], dataType: 'int8'},
+          'constant': true
+        },
+        'outputScale': {
+          'data': [0.003921568859368563],
+          'descriptor': {shape: [1], dataType: 'float32'},
+          'constant': true
+        },
+        'outputZeroPoint': {
+          'data': [-128],
+          'descriptor': {shape: [1], dataType: 'int8'},
+          'constant': true
+        },
+      },
+      'operators': [
+        {
+          'name': 'quantizeLinear',
+          'arguments': [
+            {'input': 'input'},
+            {'scale': 'inputScale', 'zeroPoint': 'inputZeroPoint'}
+          ],
+          'outputs': 'quantizedInput'
+        },
+        {
+          'name': 'dequantizeLinear',
+          'arguments': [
+            {'input': 'quantizedInput'},
+            {'scale': 'inputScale', 'zeroPoint': 'inputZeroPoint'}
+          ],
+          'outputs': 'dequantizedInput'
+        },
+        {
+          'name': 'transpose',
+          'arguments': [{'input': 'dequantizedInput'}],
+          'outputs': 'transposeOutput'
+        },
+        {
+          'name': 'quantizeLinear',
+          'arguments': [
+            {'input': 'transposeOutput'},
+            {'scale': 'outputScale', 'zeroPoint': 'outputZeroPoint'}
+          ],
+          'outputs': 'quantizedtransposeOutput'
+        },
+        {
+          'name': 'dequantizeLinear',
+          'arguments': [
+            {'input': 'quantizedtransposeOutput'},
+            {'scale': 'outputScale', 'zeroPoint': 'outputZeroPoint'}
+          ],
+          'outputs': 'output'
+        }
+      ],
+      'expectedOutputs': {
+        'output': {
+          'data': [
+            0.6823529601097107, 0.20000001788139343,
+            0.0470588281750679, 0.4117647409439087,
+            0.3333333432674408, 0.0784313753247261,
+          ],
+          'descriptor': {shape: [3, 2, 1, 1], dataType: 'float32'}
+        }
+      }
+    }
+  },
 ];
 
 if (navigator.ml) {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-metadata-transform.https.html b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-metadata-transform.https.html
index 11c88b4..10659387 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-metadata-transform.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-metadata-transform.https.html
@@ -271,10 +271,11 @@
     assert_equals(data.senderBeforeWrite.metadata.frameId,
       data.senderAfterWrite.metadata.frameId,
       'frameId matches (for sender before and after write)');
-    assert_equals(data.senderBeforeWrite.metadata.frameId,
-      data.receiverBeforeWrite.metadata.frameId,
+
+    assert_true(data.senderBeforeWrite.metadata.frameId == data.receiverBeforeWrite.metadata.frameId ||
+      data.receiverBeforeWrite.metadata.frameId == undefined,
       'frameId matches (for sender and receiver)');
-    assert_equals(data.senderBeforeWrite.metadata.frameId,
+    assert_equals(data.receiverBeforeWrite.metadata.frameId,
       data.receiverAfterWrite.metadata.frameId,
       'frameId matches (for receiver before and after write)');
 }, 'video metadata: frameId');
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https-expected.txt
new file mode 100644
index 0000000..8f074d1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] sendKeyFrameRequest does not reject when the receiver is negotiated inactive, and resumes succeeding when negotiated back to active
+  assert_equals: expected "success" but got "failure: InvalidStateError"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https.html b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https.html
index 51b797e..9bc75bd 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/script-transform-sendKeyFrameRequest.https.html
@@ -76,7 +76,7 @@
   await receiverPc.setLocalDescription();
   await senderPc.setRemoteDescription(receiverPc.localDescription);
 
-  assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'failure: InvalidStateError');
+  assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
 
   senderPc.getTransceivers()[0].direction = 'sendonly';
   await senderPc.setLocalDescription();
@@ -85,7 +85,7 @@
   await senderPc.setRemoteDescription(receiverPc.localDescription);
 
   assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
-}, 'sendKeyFrameRequest rejects when the receiver is negotiated inactive, and resumes succeeding when negotiated back to active');
+}, 'sendKeyFrameRequest does not reject when the receiver is negotiated inactive, and resumes succeeding when negotiated back to active');
 
 promise_test(async (test) => {
   const {sender, receiver, senderPc, receiverPc} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {video: true});
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/smooth-scroll/track-scroll.html b/third_party/blink/web_tests/fast/scroll-behavior/smooth-scroll/track-scroll.html
index 5790fa1..8d525fb12 100644
--- a/third_party/blink/web_tests/fast/scroll-behavior/smooth-scroll/track-scroll.html
+++ b/third_party/blink/web_tests/fast/scroll-behavior/smooth-scroll/track-scroll.html
@@ -11,9 +11,6 @@
   // Compute ScrollableArea::pageStep.
   var pageStep = innerHeight * 0.875;
   if (navigator.userAgent.indexOf("Mac OS X") >= 0) {
-      // TODO(crbug.com/40701909): the expectation is still broken on Mac since
-      // composited scrollbars implementation in ScrollbarController don't check
-      // for ScrollbarTheme::MaxOverlapBetweenPages() which is 40px on Mac.
       pageStep = Math.max(pageStep, innerHeight - 40);
   }
 
diff --git a/third_party/blink/web_tests/mhtml/.gitattributes b/third_party/blink/web_tests/mhtml/.gitattributes
index 6cefc2a..7b26976 100644
--- a/third_party/blink/web_tests/mhtml/.gitattributes
+++ b/third_party/blink/web_tests/mhtml/.gitattributes
@@ -6,8 +6,9 @@
 *original* binary
 
 # MHTML files in general should only have CRLF line endings
-# (see RFC2557, section 10).
-*.mht text eol=crlf
+# (see RFC2557, section 10). So treat them as binary as
+# GOB needs them as such.
+*.mht binary
 
 # While the overall structure of MHTML always uses CRLF, the MHTML parts
 # that use binary encoding will preserve their original line endings
diff --git a/third_party/blink/web_tests/mhtml/content_transfer_encoding_none.mht b/third_party/blink/web_tests/mhtml/content_transfer_encoding_none.mht
index 8c4d3348..fb83350b 100644
--- a/third_party/blink/web_tests/mhtml/content_transfer_encoding_none.mht
+++ b/third_party/blink/web_tests/mhtml/content_transfer_encoding_none.mht
@@ -1,36 +1,36 @@
-From: <Saved by UnMHT Ver.6.3.3 with manual conversion of first part into binary encoding>
-Subject: MHTML Tests
-Date: Wed, 14 Aug 2013 11:21:04 +0200
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_Part_ADD9911_9D32DCC.1376472064834";
-	type="text/html"
-
-------=_Part_ADD9911_9D32DCC.1376472064834
-Content-Location: http://localhost/content_transfer_encoding_none.html
-Content-Type: text/html;
-	charset="UTF-8"
-
-<!DOCTYPE html>
-<html lang='en'>
- <head>
-  <title>MHTML Content-Transfer-Encoding none test</title>
- </head>
- <body>
-  This is a red square:<br>
-  <img src="resources/red_square.png">
- </body>
-</html>
-
-------=_Part_ADD9911_9D32DCC.1376472064834
-Content-Location: http://localhost/resources/red_square.png
-Content-Transfer-Encoding: base64
-Content-Type: image/png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_Part_ADD9911_9D32DCC.1376472064834--
+From: <Saved by UnMHT Ver.6.3.3 with manual conversion of first part into binary encoding>

+Subject: MHTML Tests

+Date: Wed, 14 Aug 2013 11:21:04 +0200

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_Part_ADD9911_9D32DCC.1376472064834";

+	type="text/html"

+

+------=_Part_ADD9911_9D32DCC.1376472064834

+Content-Location: http://localhost/content_transfer_encoding_none.html

+Content-Type: text/html;

+	charset="UTF-8"

+

+<!DOCTYPE html>

+<html lang='en'>

+ <head>

+  <title>MHTML Content-Transfer-Encoding none test</title>

+ </head>

+ <body>

+  This is a red square:<br>

+  <img src="resources/red_square.png">

+ </body>

+</html>

+

+------=_Part_ADD9911_9D32DCC.1376472064834

+Content-Location: http://localhost/resources/red_square.png

+Content-Transfer-Encoding: base64

+Content-Type: image/png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_Part_ADD9911_9D32DCC.1376472064834--

diff --git a/third_party/blink/web_tests/mhtml/data-uri-font.mht b/third_party/blink/web_tests/mhtml/data-uri-font.mht
index 80c3812a..6606c30 100644
--- a/third_party/blink/web_tests/mhtml/data-uri-font.mht
+++ b/third_party/blink/web_tests/mhtml/data-uri-font.mht
@@ -1,254 +1,254 @@
-From: <Saved by UnMHT>
-Subject: The Google
-Date: Mon, Nov 21 2011 10:59:06 GMT-0800
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_0324C3DC.A3C79392";
-	type="text/html"
-
-------=_NextPart_000_0000_0324C3DC.A3C79392
-Content-Type: text/html; charset="UTF-8"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://www.google.com/
-
-<!doctype html>
-<html>
-<head>
-<title>Test for data URI font.</title>
-<style>
-.test {
-    border: solid 1px;
-}
-@font-face {
-    font-family: ahem-data;
-    src:url("data:font/ttf;base64,AAEAAAALAIAAAwAwT1MvMnhQSo0AAAE4AAAAYGNtY=
-XAP1hZGAAAFbAAABnJnYXNwABcACQAAMLAAAAAQZ2x5ZkmzdNoAAAvgAAAaZGhlYWTWok4cAAAA=
-vAAAADZoaGVhBwoEFgAAAPQAAAAkaG10eLkgAH0AAAGYAAAD1GxvY2EgdSciAAAmRAAAAextYXh=
-wAPgACQAAARgAAAAgbmFtZX4UjLgAACgwAAAGaHBvc3SN0B2KAAAumAAAAhgAAQAAAAEAQhIXUW=
-dfDzz1AAkD6AAAAACzb19ZAAAAAMAtq0kAAP84A+gDIAAAAAMAAgAAAAAAAAABAAADIP84AAAD6=
-AAAAAAD6AABAAAAAAAAAAAAAAAAAAAA9QABAAAA9QAIAAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAA=
-AAID6AGQAAUAAAK8AooAAACPArwCigAAAcUAMgEDAAACAAQJAAAAAAAAgAAArxAAIEgAAAAAAAA=
-AAFczQwAAQAAg8AIDIP84AAADIADIIAABEUAAAAADIAMgAAAAIAAAA+gAfQAAAAAD6AAAA+gAAA=
-PoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA=
-+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD=
-6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAP=
-oAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+=
-gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6=
-AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPo=
-AAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+g=
-AAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6A=
-AAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoA=
-AAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gA=
-AAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AA=
-AA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAA=
-AD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAA=
-APoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAA=
-A+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAA=
-D6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAA=
-PoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA=
-+gAAAPoAAAAAAADAAAAAwAABEwAAQAAAAAAHAADAAEAAAImAAYCCgAAAAABAAABAAAAAAAAAAAA=
-AAAAAAAAAQACAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAwA=
-EAAUABgAHAAgACQAAAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB=
-8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAO=
-wA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBX=
-AFgAWQBaAFsAXABdAF4AXwBgAAAAYQBiAGMAZABlAGYAZwBoAGkAagBrAGwAbQBuAG8AcABxAHI=
-AcwB0AHUAdgB3AHgAeQB6AHsAfAB9AH4AfwCAANsAgQCCAIMAhADdAIUAhgCHAIgA4wCJAIoA6g=
-CLAIwA6ACNAOsA7ACOAI8A5ADmAOUA1ADpAJAAkQDTAJIAkwCUAJUAlgDnANEA7QDSAJcAmADeA=
-AMAmgCbAJwAzgDPANUA1gDYANkAnQCeAJ8A7gCgANAA4gChAOAA4QAAAAAA3ACiANcA2gDfAKMA=
-pAClAKYApwCoAKkAqgCrAKwArQAAAK4ArwCwALEAsgCzALQAtQC2ALcAuAC5ALoAuwC8AAQCJgA=
-AAE4AQAAFAA4AJgB+AP8BMQFTAXgBkgLHAskC3QOUA6kDvAPAIBAgFCAaIB4gIiAmIDAgOiBEIS=
-IhJiICIgYiDyISIhoiHiIrIkgiYCJlIvIlyvAC//8AAAAgACgAoAExAVIBeAGSAsYCyQLYA5QDq=
-QO8A8AgECATIBggHCAgICYgMCA5IEQhIiEmIgIiBiIPIhEiGSIeIisiSCJgImQi8iXK8AD////j=
-/+IAAP+B/3z/WP8/AAD97AAA/T79KvzT/RTf/+DCAADgvOC74Ljgr+Cn4J7fwd+t3uLezN7WAAA=
-AAN7K3r7epd6K3ofd+9skEO8AAQAAAAAASgAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAP4AAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAOwA7gAAAAAAAAAAAAAAAAAAAAAAAACZAJUAggCDAKEAjgC9A=
-IQAigCIAJAAlwCWAMQAhwC1AIEAjQDHAMgAiQCPAIUAogC5AMYAkQCYAMoAyQDLAJQAmgClAKMA=
-mwBhAGIAiwBjAKcAZACkAKYAqwCoAKkAqgC+AGUArgCsAK0AnABmAMUAjACxAK8AsABnAMAAwgC=
-GAGkAaABqAGwAawBtAJIAbgBwAG8AcQByAHQAcwB1AHYAvwB3AHkAeAB6AHwAewCfAJMAfgB9AH=
-8AgADBAMMAoACzALwAtgC3ALgAuwC0ALoAnQCeANcA5gDEAKIA5wAEAiYAAABOAEAABQAOACYAf=
-gD/ATEBUwF4AZICxwLJAt0DlAOpA7wDwCAQIBQgGiAeICIgJiAwIDogRCEiISYiAiIGIg8iEiIa=
-Ih4iKyJIImAiZSLyJcrwAv//AAAAIAAoAKABMQFSAXgBkgLGAskC2AOUA6kDvAPAIBAgEyAYIBw=
-gICAmIDAgOSBEISIhJiICIgYiDyIRIhkiHiIrIkgiYCJkIvIlyvAA////4//iAAD/gf98/1j/Pw=
-AA/ewAAP0+/Sr80/0U3//gwgAA4Lzgu+C44K/gp+Ce38Hfrd7i3sze1gAAAADeyt6+3qXeit6H3=
-fvbJBDvAAEAAAAAAEoAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAAA=
-AAAAAAAAAADsAO4AAAAAAAAAAAAAAAAAAAAAAAAAmQCVAIIAgwChAI4AvQCEAIoAiACQAJcAlgD=
-EAIcAtQCBAI0AxwDIAIkAjwCFAKIAuQDGAJEAmADKAMkAywCUAJoApQCjAJsAYQBiAIsAYwCnAG=
-QApACmAKsAqACpAKoAvgBlAK4ArACtAJwAZgDFAIwAsQCvALAAZwDAAMIAhgBpAGgAagBsAGsAb=
-QCSAG4AcABvAHEAcgB0AHMAdQB2AL8AdwB5AHgAegB8AHsAnwCTAH4AfQB/AIAAwQDDAKAAswC8=
-ALYAtwC4ALsAtAC6AJ0AngDXAOYAxACiAOcAAAACAH0AAANrAyAAAwAHAAAzESERJSERIX0C7v2=
-PAfT+DAMg/OB9AiYAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIR=
-EhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhE=
-SED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESER=
-IQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIRE=
-hA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhES=
-ED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERI=
-QPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREh=
-A+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESE=
-D6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQ=
-Po/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA=
-+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED=
-6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQP=
-o/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+=
-j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6=
-PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo=
-/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j=
-8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6P=
-wYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/=
-BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8=
-GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6Pw=
-YAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/B=
-gDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8G=
-AMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwY=
-AyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/Bg=
-DIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GA=
-Mg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYA=
-yD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgD=
-IPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAM=
-g/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAy=
-D8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDI=
-PwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg=
-/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD=
-8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIP=
-wYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/=
-BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8=
-GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPw=
-YAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/B=
-gAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8G=
-AAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwY=
-AAAAAQAA/zgD6AAAAAMAADEhFSED6PwYyAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAE=
-AAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQ=
-AA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABA=
-AD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEA=
-AP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQA=
-A/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAA=
-D/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAA=
-P84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA=
-/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAA=
-AAAPoAyAAAwAAESERIQPo/BgDIPzgAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP=
-84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/=
-zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/=
-OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP8=
-4A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/z=
-gD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/O=
-APoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84=
-A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zg=
-D6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OA=
-PoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A=
-+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD=
-6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAP=
-oAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+=
-gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6=
-AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPo=
-AyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+g=
-DIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6A=
-MgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoA=
-yAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gD=
-IAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AM=
-gAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAy=
-AAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDI=
-AADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMg=
-AAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyA=
-AAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIA=
-ADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgA=
-AMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAA=
-AwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAA=
-DAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAA=
-MAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAA=
-wAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAAD=
-AAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAM=
-AABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAw=
-AAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADA=
-AARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMA=
-ABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwA=
-AESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAA=
-ARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAA=
-BEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAA=
-ESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAA=
-RIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAAB=
-EhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAE=
-SERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAAR=
-IREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABE=
-hESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAES=
-ERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARI=
-REhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEh=
-ESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESE=
-RIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIR=
-EhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhE=
-SED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESER=
-IQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIRE=
-hA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhES=
-ED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERI=
-QPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREh=
-A+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESE=
-D6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQ=
-Po/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA=
-+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED=
-6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQP=
-o/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+=
-j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6=
-PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo=
-/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j=
-8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6P=
-wYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/=
-BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8=
-GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6Pw=
-YAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/B=
-gDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8G=
-AMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwY=
-AyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAAAABQAFAAUABQAIgAwAD4ATABaAGg=
-AdgCEAJIAoACuALwAygDYAOYA9AECARABHgEsAToBSAFWAWQBcgGAAY4BnAGqAbgBxgHUAeIB8A=
-H+AgwCGgIoAjYCRAJSAmACbgJ8AooCmAKmArQCwgLQAt4C7AL6AwgDFgMkAzIDQANOA1wDagN4A=
-4YDlAOiA7ADvgPMA9oD6AP2BAQEEgQgBC4EPARKBFgEZARyBIAEjgScBKoEuATGBNQE4gTwBP4F=
-DAUaBSgFNgVEBVIFYAVuBXwFigWYBaYFtAXCBdAF3gXsBfoGCAYWBiQGMgZABk4GXAZqBngGhga=
-UBqIGsAa+BswG2gboBvYHBAcSByAHLgc8B0oHWAdmB3QHggeQB54HrAe6B8gH1gfkB/IIAAgOCB=
-wIKgg4CDgIRghUCGIIcAh+CIwImgioCLYIxAjSCOAI7gj8CQoJGAkmCTQJQglQCV4JbAl6CYgJl=
-gmkCbIJwAnOCdwJ6gn4CgYKFAoiCjAKPgpMCloKaAp2CoQKkgqgCq4KvArKCtgK5gr0CwILEAse=
-CywLOgtIC1YLZAtyC4ALjgucC6oLuAvGC9QL4gvwC/4MDAwaDCgMNgxEDFIMYAxuDHwMigyYDKY=
-MtAzCDNAM3gzsDPoNCA0WDSQNMgAAABsBSgAAAAAAAAAAAZ4AAAAAAAAAAAABAAgBngAAAAAAAA=
-ACAA4BpgAAAAAAAAADACABtAAAAAAAAAAEAAgB1AAAAAAAAAAFABYB3AAAAAAAAAAGAAgB8gABA=
-AAAAAAAAM8B+gABAAAAAAABAAQCyQABAAAAAAACAAcCzQABAAAAAAADABAC1AABAAAAAAAEAAQC=
-5AABAAAAAAAFAAsC6AABAAAAAAAGAAQC8wABAAAAAAAQAAQC9wABAAAAAAARAAcC+wABAAAAAAA=
-SAAQDAgADAAEECQAAAZ4DBgADAAEECQABAAgEpAADAAEECQACAA4ErAADAAEECQADACAEugADAA=
-EECQAEAAgE2gADAAEECQAFABYE4gADAAEECQAGAAgE+AADAAEECQAQAAgFAAADAAEECQARAA4FC=
-AADAAEECQASAAgFFgBNAG8AcwB0ACAAYwBoAGEAcgBhAGMAdABlAHIAcwAgAGEAcgBlACAAdABo=
-AGUAIABlAG0AIABzAHEAdQBhAHIAZQAsACAAZQB4AGMAZQBwAHQAIAAmAEUAQQBjAHUAdABlACA=
-AYQBuAGQAIAAiAHAAIgAsACAAdwBoAGkAYwBoACAAcwBoAG8AdwAgAGEAcwBjAGUAbgB0AC8AZA=
-BlAHMAYwBlAG4AdAAgAGYAcgBvAG0AIAB0AGgAZQAgAGIAYQBzAGUAbABpAG4AZQAuACAAVQBzA=
-GUAZgB1AGwAIABmAG8AcgAgAHQAZQBzAHQAaQBuAGcAIABjAG8AbQBwAG8AcwBpAHQAaQBvAG4A=
-IABzAHkAcwB0AGUAbQBzAC4AIABQAHIAbwBkAHUAYwBlAGQAIABiAHkAIABUAG8AZABkACAARgB=
-hAGgAcgBuAGUAcgAgAGYAbwByACAAdABoAGUAIABDAFMAUwAgAFMAYQBtAHUAcgBhAGkAJwBzAC=
-AAYgByAG8AdwBzAGUAcgAgAHQAZQBzAHQAaQBuAGcALgBBAGgAZQBtAFIAZQBnAHUAbABhAHIAV=
-gBlAHIAcwBpAG8AbgAgADEALgAxACAAQQBoAGUAbQBBAGgAZQBtAFYAZQByAHMAaQBvAG4AIAAx=
-AC4AMQBBAGgAZQBtTW9zdCBjaGFyYWN0ZXJzIGFyZSB0aGUgZW0gc3F1YXJlLCBleGNlcHQgJkV=
-BY3V0ZSBhbmQgInAiLCB3aGljaCBzaG93IGFzY2VudC9kZXNjZW50IGZyb20gdGhlIGJhc2VsaW=
-5lLiBVc2VmdWwgZm9yIHRlc3RpbmcgY29tcG9zaXRpb24gc3lzdGVtcy4gUHJvZHVjZWQgYnkgV=
-G9kZCBGYWhybmVyIGZvciB0aGUgQ1NTIFNhbXVyYWkncyBicm93c2VyIHRlc3RpbmcuQWhlbVJl=
-Z3VsYXJWZXJzaW9uIDEuMSBBaGVtQWhlbVZlcnNpb24gMS4xQWhlbUFoZW1SZWd1bGFyQWhlbQB=
-NAG8AcwB0ACAAYwBoAGEAcgBhAGMAdABlAHIAcwAgAGEAcgBlACAAdABoAGUAIABlAG0AIABzAH=
-EAdQBhAHIAZQAsACAAZQB4AGMAZQBwAHQAIAAmAEUAQQBjAHUAdABlACAAYQBuAGQAIAAiAHAAI=
-gAsACAAdwBoAGkAYwBoACAAcwBoAG8AdwAgAGEAcwBjAGUAbgB0AC8AZABlAHMAYwBlAG4AdAAg=
-AGYAcgBvAG0AIAB0AGgAZQAgAGIAYQBzAGUAbABpAG4AZQAuACAAVQBzAGUAZgB1AGwAIABmAG8=
-AcgAgAHQAZQBzAHQAaQBuAGcAIABjAG8AbQBwAG8AcwBpAHQAaQBvAG4AIABzAHkAcwB0AGUAbQ=
-BzAC4AIABQAHIAbwBkAHUAYwBlAGQAIABiAHkAIABUAG8AZABkACAARgBhAGgAcgBuAGUAcgAgA=
-GYAbwByACAAdABoAGUAIABDAFMAUwAgAFMAYQBtAHUAcgBhAGkAJwBzACAAYgByAG8AdwBzAGUA=
-cgAgAHQAZQBzAHQAaQBuAGcALgBBAGgAZQBtAFIAZQBnAHUAbABhAHIAVgBlAHIAcwBpAG8AbgA=
-gADEALgAxACAAQQBoAGUAbQBBAGgAZQBtAFYAZQByAHMAaQBvAG4AIAAxAC4AMQBBAGgAZQBtAE=
-EAaABlAG0AUgBlAGcAdQBsAGEAcgBBAGgAZQBtAAIAAAAAAAD/ewAUAAAAAQAAAAAAAAAAAAAAA=
-AAAAAAA9QAAAQIAAgADAAQABQAGAAcACAAJAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZ=
-ABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADU=
-ANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQ=
-BSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAGIAYwBkAGUAZgBnAGgAaQBqAGsAbABtA=
-G4AbwBwAHEAcgBzAHQAdQB2AHcAeAB5AHoAewB8AH0AfgB/AIAAgQCDAIQAhQCGAIgAiQCKAIsA=
-jQCOAJAAkQCTAJYAlwCdAJ4AoAChAKIAowCkAKkAqgCsAK0ArgCvALYAtwC4ALoAvQDDAMcAyAD=
-JAMoAywDMAM0AzgDPANAA0QDTANQA1QDWANcA2ADZANoA2wDcAN0A3gDfAOAA4QDoAOkA6gDrAO=
-wA7QDuAO8A8ADxAPIA8wD0APUA9gAAAAAAsACxALsApgCoAJ8AmwCyALMAxAC0ALUAxQCCAMIAh=
-wCrAMYAvgC/ALwAjACYAJoAmQClAJIAnACPAJQAlQCnALkA0gDAAMEBAwACAQQETlVMTAJIVANE=
-RUwAAAADAAgAAgAQAAH//wAD");
-}
-</style>
-</head>
-<span class=3D"test" id=3D"test0" style=3D"font-family:ahem-data, monospace=
-;">Should not be monospace.</span><br/>
-</body>
-</html>
-------=_NextPart_000_0000_0324C3DC.A3C79392--
+From: <Saved by UnMHT>

+Subject: The Google

+Date: Mon, Nov 21 2011 10:59:06 GMT-0800

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_0324C3DC.A3C79392";

+	type="text/html"

+

+------=_NextPart_000_0000_0324C3DC.A3C79392

+Content-Type: text/html; charset="UTF-8"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://www.google.com/

+

+<!doctype html>

+<html>

+<head>

+<title>Test for data URI font.</title>

+<style>

+.test {

+    border: solid 1px;

+}

+@font-face {

+    font-family: ahem-data;

+    src:url("data:font/ttf;base64,AAEAAAALAIAAAwAwT1MvMnhQSo0AAAE4AAAAYGNtY=

+XAP1hZGAAAFbAAABnJnYXNwABcACQAAMLAAAAAQZ2x5ZkmzdNoAAAvgAAAaZGhlYWTWok4cAAAA=

+vAAAADZoaGVhBwoEFgAAAPQAAAAkaG10eLkgAH0AAAGYAAAD1GxvY2EgdSciAAAmRAAAAextYXh=

+wAPgACQAAARgAAAAgbmFtZX4UjLgAACgwAAAGaHBvc3SN0B2KAAAumAAAAhgAAQAAAAEAQhIXUW=

+dfDzz1AAkD6AAAAACzb19ZAAAAAMAtq0kAAP84A+gDIAAAAAMAAgAAAAAAAAABAAADIP84AAAD6=

+AAAAAAD6AABAAAAAAAAAAAAAAAAAAAA9QABAAAA9QAIAAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAA=

+AAID6AGQAAUAAAK8AooAAACPArwCigAAAcUAMgEDAAACAAQJAAAAAAAAgAAArxAAIEgAAAAAAAA=

+AAFczQwAAQAAg8AIDIP84AAADIADIIAABEUAAAAADIAMgAAAAIAAAA+gAfQAAAAAD6AAAA+gAAA=

+PoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA=

++gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD=

+6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAP=

+oAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+=

+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6=

+AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPo=

+AAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+g=

+AAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6A=

+AAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoA=

+AAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gA=

+AAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AA=

+AA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAA=

+AD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAA=

+APoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAA=

+A+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAA=

+D6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAA=

+PoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA=

++gAAAPoAAAAAAADAAAAAwAABEwAAQAAAAAAHAADAAEAAAImAAYCCgAAAAABAAABAAAAAAAAAAAA=

+AAAAAAAAAQACAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAwA=

+EAAUABgAHAAgACQAAAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB=

+8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAO=

+wA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBX=

+AFgAWQBaAFsAXABdAF4AXwBgAAAAYQBiAGMAZABlAGYAZwBoAGkAagBrAGwAbQBuAG8AcABxAHI=

+AcwB0AHUAdgB3AHgAeQB6AHsAfAB9AH4AfwCAANsAgQCCAIMAhADdAIUAhgCHAIgA4wCJAIoA6g=

+CLAIwA6ACNAOsA7ACOAI8A5ADmAOUA1ADpAJAAkQDTAJIAkwCUAJUAlgDnANEA7QDSAJcAmADeA=

+AMAmgCbAJwAzgDPANUA1gDYANkAnQCeAJ8A7gCgANAA4gChAOAA4QAAAAAA3ACiANcA2gDfAKMA=

+pAClAKYApwCoAKkAqgCrAKwArQAAAK4ArwCwALEAsgCzALQAtQC2ALcAuAC5ALoAuwC8AAQCJgA=

+AAE4AQAAFAA4AJgB+AP8BMQFTAXgBkgLHAskC3QOUA6kDvAPAIBAgFCAaIB4gIiAmIDAgOiBEIS=

+IhJiICIgYiDyISIhoiHiIrIkgiYCJlIvIlyvAC//8AAAAgACgAoAExAVIBeAGSAsYCyQLYA5QDq=

+QO8A8AgECATIBggHCAgICYgMCA5IEQhIiEmIgIiBiIPIhEiGSIeIisiSCJgImQi8iXK8AD////j=

+/+IAAP+B/3z/WP8/AAD97AAA/T79KvzT/RTf/+DCAADgvOC74Ljgr+Cn4J7fwd+t3uLezN7WAAA=

+AAN7K3r7epd6K3ofd+9skEO8AAQAAAAAASgAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAP4AAA=

+AAAAAAAAAAAAAAAAAAAAAAAAAAAOwA7gAAAAAAAAAAAAAAAAAAAAAAAACZAJUAggCDAKEAjgC9A=

+IQAigCIAJAAlwCWAMQAhwC1AIEAjQDHAMgAiQCPAIUAogC5AMYAkQCYAMoAyQDLAJQAmgClAKMA=

+mwBhAGIAiwBjAKcAZACkAKYAqwCoAKkAqgC+AGUArgCsAK0AnABmAMUAjACxAK8AsABnAMAAwgC=

+GAGkAaABqAGwAawBtAJIAbgBwAG8AcQByAHQAcwB1AHYAvwB3AHkAeAB6AHwAewCfAJMAfgB9AH=

+8AgADBAMMAoACzALwAtgC3ALgAuwC0ALoAnQCeANcA5gDEAKIA5wAEAiYAAABOAEAABQAOACYAf=

+gD/ATEBUwF4AZICxwLJAt0DlAOpA7wDwCAQIBQgGiAeICIgJiAwIDogRCEiISYiAiIGIg8iEiIa=

+Ih4iKyJIImAiZSLyJcrwAv//AAAAIAAoAKABMQFSAXgBkgLGAskC2AOUA6kDvAPAIBAgEyAYIBw=

+gICAmIDAgOSBEISIhJiICIgYiDyIRIhkiHiIrIkgiYCJkIvIlyvAA////4//iAAD/gf98/1j/Pw=

+AA/ewAAP0+/Sr80/0U3//gwgAA4Lzgu+C44K/gp+Ce38Hfrd7i3sze1gAAAADeyt6+3qXeit6H3=

+fvbJBDvAAEAAAAAAEoAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAD+AAAAAAAAAAAAAAAAAAAA=

+AAAAAAAAAADsAO4AAAAAAAAAAAAAAAAAAAAAAAAAmQCVAIIAgwChAI4AvQCEAIoAiACQAJcAlgD=

+EAIcAtQCBAI0AxwDIAIkAjwCFAKIAuQDGAJEAmADKAMkAywCUAJoApQCjAJsAYQBiAIsAYwCnAG=

+QApACmAKsAqACpAKoAvgBlAK4ArACtAJwAZgDFAIwAsQCvALAAZwDAAMIAhgBpAGgAagBsAGsAb=

+QCSAG4AcABvAHEAcgB0AHMAdQB2AL8AdwB5AHgAegB8AHsAnwCTAH4AfQB/AIAAwQDDAKAAswC8=

+ALYAtwC4ALsAtAC6AJ0AngDXAOYAxACiAOcAAAACAH0AAANrAyAAAwAHAAAzESERJSERIX0C7v2=

+PAfT+DAMg/OB9AiYAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIR=

+EhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhE=

+SED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESER=

+IQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIRE=

+hA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhES=

+ED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERI=

+QPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREh=

+A+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESE=

+D6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQ=

+Po/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA=

++j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED=

+6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQP=

+o/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+=

+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6=

+PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo=

+/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j=

+8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6P=

+wYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/=

+BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8=

+GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6Pw=

+YAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/B=

+gDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8G=

+AMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwY=

+AyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/Bg=

+DIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GA=

+Mg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYA=

+yD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgD=

+IPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAM=

+g/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAy=

+D8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDI=

+PwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg=

+/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD=

+8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIP=

+wYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/=

+BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8=

+GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPw=

+YAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/B=

+gAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8G=

+AAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwY=

+AAAAAQAA/zgD6AAAAAMAADEhFSED6PwYyAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAE=

+AAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQ=

+AA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABA=

+AD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEA=

+AP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQA=

+A/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAA=

+D/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAA=

+P84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA=

+/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAA=

+AAAPoAyAAAwAAESERIQPo/BgDIPzgAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP=

+84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/=

+zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/=

+OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP8=

+4A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/z=

+gD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/O=

+APoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84=

+A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zg=

+D6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OA=

+PoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A=

++gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD=

+6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAP=

+oAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+=

+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6=

+AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPo=

+AyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+g=

+DIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6A=

+MgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoA=

+yAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gD=

+IAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AM=

+gAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAy=

+AAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDI=

+AADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMg=

+AAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyA=

+AAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIA=

+ADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgA=

+AMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAA=

+AwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAA=

+DAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAA=

+MAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAA=

+wAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAAD=

+AAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAM=

+AABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAw=

+AAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADA=

+AARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMA=

+ABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwA=

+AESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAA=

+ARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAA=

+BEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAA=

+ESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAA=

+RIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAAB=

+EhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAE=

+SERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAAR=

+IREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABE=

+hESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAES=

+ERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARI=

+REhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEh=

+ESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESE=

+RIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIR=

+EhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhE=

+SED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESER=

+IQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIRE=

+hA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhES=

+ED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERI=

+QPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREh=

+A+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESE=

+D6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQ=

+Po/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA=

++j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED=

+6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQP=

+o/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+=

+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6=

+PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo=

+/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j=

+8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6P=

+wYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/=

+BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8=

+GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6Pw=

+YAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/B=

+gDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwYAyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8G=

+AMg/BgAAAABAAD/OAPoAyAAAwAAESERIQPo/BgDIPwYAAAAAQAA/zgD6AMgAAMAABEhESED6PwY=

+AyD8GAAAAAEAAP84A+gDIAADAAARIREhA+j8GAMg/BgAAAAAABQAFAAUABQAIgAwAD4ATABaAGg=

+AdgCEAJIAoACuALwAygDYAOYA9AECARABHgEsAToBSAFWAWQBcgGAAY4BnAGqAbgBxgHUAeIB8A=

+H+AgwCGgIoAjYCRAJSAmACbgJ8AooCmAKmArQCwgLQAt4C7AL6AwgDFgMkAzIDQANOA1wDagN4A=

+4YDlAOiA7ADvgPMA9oD6AP2BAQEEgQgBC4EPARKBFgEZARyBIAEjgScBKoEuATGBNQE4gTwBP4F=

+DAUaBSgFNgVEBVIFYAVuBXwFigWYBaYFtAXCBdAF3gXsBfoGCAYWBiQGMgZABk4GXAZqBngGhga=

+UBqIGsAa+BswG2gboBvYHBAcSByAHLgc8B0oHWAdmB3QHggeQB54HrAe6B8gH1gfkB/IIAAgOCB=

+wIKgg4CDgIRghUCGIIcAh+CIwImgioCLYIxAjSCOAI7gj8CQoJGAkmCTQJQglQCV4JbAl6CYgJl=

+gmkCbIJwAnOCdwJ6gn4CgYKFAoiCjAKPgpMCloKaAp2CoQKkgqgCq4KvArKCtgK5gr0CwILEAse=

+CywLOgtIC1YLZAtyC4ALjgucC6oLuAvGC9QL4gvwC/4MDAwaDCgMNgxEDFIMYAxuDHwMigyYDKY=

+MtAzCDNAM3gzsDPoNCA0WDSQNMgAAABsBSgAAAAAAAAAAAZ4AAAAAAAAAAAABAAgBngAAAAAAAA=

+ACAA4BpgAAAAAAAAADACABtAAAAAAAAAAEAAgB1AAAAAAAAAAFABYB3AAAAAAAAAAGAAgB8gABA=

+AAAAAAAAM8B+gABAAAAAAABAAQCyQABAAAAAAACAAcCzQABAAAAAAADABAC1AABAAAAAAAEAAQC=

+5AABAAAAAAAFAAsC6AABAAAAAAAGAAQC8wABAAAAAAAQAAQC9wABAAAAAAARAAcC+wABAAAAAAA=

+SAAQDAgADAAEECQAAAZ4DBgADAAEECQABAAgEpAADAAEECQACAA4ErAADAAEECQADACAEugADAA=

+EECQAEAAgE2gADAAEECQAFABYE4gADAAEECQAGAAgE+AADAAEECQAQAAgFAAADAAEECQARAA4FC=

+AADAAEECQASAAgFFgBNAG8AcwB0ACAAYwBoAGEAcgBhAGMAdABlAHIAcwAgAGEAcgBlACAAdABo=

+AGUAIABlAG0AIABzAHEAdQBhAHIAZQAsACAAZQB4AGMAZQBwAHQAIAAmAEUAQQBjAHUAdABlACA=

+AYQBuAGQAIAAiAHAAIgAsACAAdwBoAGkAYwBoACAAcwBoAG8AdwAgAGEAcwBjAGUAbgB0AC8AZA=

+BlAHMAYwBlAG4AdAAgAGYAcgBvAG0AIAB0AGgAZQAgAGIAYQBzAGUAbABpAG4AZQAuACAAVQBzA=

+GUAZgB1AGwAIABmAG8AcgAgAHQAZQBzAHQAaQBuAGcAIABjAG8AbQBwAG8AcwBpAHQAaQBvAG4A=

+IABzAHkAcwB0AGUAbQBzAC4AIABQAHIAbwBkAHUAYwBlAGQAIABiAHkAIABUAG8AZABkACAARgB=

+hAGgAcgBuAGUAcgAgAGYAbwByACAAdABoAGUAIABDAFMAUwAgAFMAYQBtAHUAcgBhAGkAJwBzAC=

+AAYgByAG8AdwBzAGUAcgAgAHQAZQBzAHQAaQBuAGcALgBBAGgAZQBtAFIAZQBnAHUAbABhAHIAV=

+gBlAHIAcwBpAG8AbgAgADEALgAxACAAQQBoAGUAbQBBAGgAZQBtAFYAZQByAHMAaQBvAG4AIAAx=

+AC4AMQBBAGgAZQBtTW9zdCBjaGFyYWN0ZXJzIGFyZSB0aGUgZW0gc3F1YXJlLCBleGNlcHQgJkV=

+BY3V0ZSBhbmQgInAiLCB3aGljaCBzaG93IGFzY2VudC9kZXNjZW50IGZyb20gdGhlIGJhc2VsaW=

+5lLiBVc2VmdWwgZm9yIHRlc3RpbmcgY29tcG9zaXRpb24gc3lzdGVtcy4gUHJvZHVjZWQgYnkgV=

+G9kZCBGYWhybmVyIGZvciB0aGUgQ1NTIFNhbXVyYWkncyBicm93c2VyIHRlc3RpbmcuQWhlbVJl=

+Z3VsYXJWZXJzaW9uIDEuMSBBaGVtQWhlbVZlcnNpb24gMS4xQWhlbUFoZW1SZWd1bGFyQWhlbQB=

+NAG8AcwB0ACAAYwBoAGEAcgBhAGMAdABlAHIAcwAgAGEAcgBlACAAdABoAGUAIABlAG0AIABzAH=

+EAdQBhAHIAZQAsACAAZQB4AGMAZQBwAHQAIAAmAEUAQQBjAHUAdABlACAAYQBuAGQAIAAiAHAAI=

+gAsACAAdwBoAGkAYwBoACAAcwBoAG8AdwAgAGEAcwBjAGUAbgB0AC8AZABlAHMAYwBlAG4AdAAg=

+AGYAcgBvAG0AIAB0AGgAZQAgAGIAYQBzAGUAbABpAG4AZQAuACAAVQBzAGUAZgB1AGwAIABmAG8=

+AcgAgAHQAZQBzAHQAaQBuAGcAIABjAG8AbQBwAG8AcwBpAHQAaQBvAG4AIABzAHkAcwB0AGUAbQ=

+BzAC4AIABQAHIAbwBkAHUAYwBlAGQAIABiAHkAIABUAG8AZABkACAARgBhAGgAcgBuAGUAcgAgA=

+GYAbwByACAAdABoAGUAIABDAFMAUwAgAFMAYQBtAHUAcgBhAGkAJwBzACAAYgByAG8AdwBzAGUA=

+cgAgAHQAZQBzAHQAaQBuAGcALgBBAGgAZQBtAFIAZQBnAHUAbABhAHIAVgBlAHIAcwBpAG8AbgA=

+gADEALgAxACAAQQBoAGUAbQBBAGgAZQBtAFYAZQByAHMAaQBvAG4AIAAxAC4AMQBBAGgAZQBtAE=

+EAaABlAG0AUgBlAGcAdQBsAGEAcgBBAGgAZQBtAAIAAAAAAAD/ewAUAAAAAQAAAAAAAAAAAAAAA=

+AAAAAAA9QAAAQIAAgADAAQABQAGAAcACAAJAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZ=

+ABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADU=

+ANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQ=

+BSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAGIAYwBkAGUAZgBnAGgAaQBqAGsAbABtA=

+G4AbwBwAHEAcgBzAHQAdQB2AHcAeAB5AHoAewB8AH0AfgB/AIAAgQCDAIQAhQCGAIgAiQCKAIsA=

+jQCOAJAAkQCTAJYAlwCdAJ4AoAChAKIAowCkAKkAqgCsAK0ArgCvALYAtwC4ALoAvQDDAMcAyAD=

+JAMoAywDMAM0AzgDPANAA0QDTANQA1QDWANcA2ADZANoA2wDcAN0A3gDfAOAA4QDoAOkA6gDrAO=

+wA7QDuAO8A8ADxAPIA8wD0APUA9gAAAAAAsACxALsApgCoAJ8AmwCyALMAxAC0ALUAxQCCAMIAh=

+wCrAMYAvgC/ALwAjACYAJoAmQClAJIAnACPAJQAlQCnALkA0gDAAMEBAwACAQQETlVMTAJIVANE=

+RUwAAAADAAgAAgAQAAH//wAD");

+}

+</style>

+</head>

+<span class=3D"test" id=3D"test0" style=3D"font-family:ahem-data, monospace=

+;">Should not be monospace.</span><br/>

+</body>

+</html>

+------=_NextPart_000_0000_0324C3DC.A3C79392--

diff --git a/third_party/blink/web_tests/mhtml/image_document.mht b/third_party/blink/web_tests/mhtml/image_document.mht
index 6c97fb5..8eb756de 100644
--- a/third_party/blink/web_tests/mhtml/image_document.mht
+++ b/third_party/blink/web_tests/mhtml/image_document.mht
@@ -1,19 +1,19 @@
-From: <Saved by Blink>
-Subject: 128x128_png.png (128?128)
-Date: Fri, 13 Oct 2016 17:40:08 -0000
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----"
-
-------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F------
+From: <Saved by Blink>

+Subject: 128x128_png.png (128?128)

+Date: Fri, 13 Oct 2016 17:40:08 -0000

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----"

+

+------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F------

diff --git a/third_party/blink/web_tests/mhtml/invalid-bad-boundary.mht b/third_party/blink/web_tests/mhtml/invalid-bad-boundary.mht
index af611fa..292d6d1 100644
--- a/third_party/blink/web_tests/mhtml/invalid-bad-boundary.mht
+++ b/third_party/blink/web_tests/mhtml/invalid-bad-boundary.mht
@@ -1,18 +1,18 @@
-From: <Saved by WebKit>
-Subject: Google
-Date: Fri, 20 Jun 2013 14:36:21 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----=_NextPart_000_CA35_2BC72789.A73F63D7"
-
-BadBoundary------=_NextPart_000_CA35_2BC72789.A73F63D7
-Content-Type: text/html
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/invalid-bad-boundary.html
-
-<body>
-<script> if (window.testRunner) { testRunner.dumpAsText() } </script>
-This tests that we don't crash if the MHTML is invalid (bad boundary).
-</body>
-------=_NextPart_000_CA35_2BC72789.A73F63D7--
+From: <Saved by WebKit>

+Subject: Google

+Date: Fri, 20 Jun 2013 14:36:21 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----=_NextPart_000_CA35_2BC72789.A73F63D7"

+

+BadBoundary------=_NextPart_000_CA35_2BC72789.A73F63D7

+Content-Type: text/html

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/invalid-bad-boundary.html

+

+<body>

+<script> if (window.testRunner) { testRunner.dumpAsText() } </script>

+This tests that we don't crash if the MHTML is invalid (bad boundary).

+</body>

+------=_NextPart_000_CA35_2BC72789.A73F63D7--

diff --git a/third_party/blink/web_tests/mhtml/invalid-bad-boundary2.mht b/third_party/blink/web_tests/mhtml/invalid-bad-boundary2.mht
index dd3a2db6..fd9d657f 100644
--- a/third_party/blink/web_tests/mhtml/invalid-bad-boundary2.mht
+++ b/third_party/blink/web_tests/mhtml/invalid-bad-boundary2.mht
@@ -1,41 +1,41 @@
-From: <Saved by UnMHT Ver.6.3.3 with manual conversion of first part into binary encoding>
-Subject: MHTML Tests
-Date: Wed, 14 Aug 2013 11:21:04 +0200
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_Part_ADD9911_9D32DCC.1376472064834";
-	type="text/html"
-
------=_Part_ADD9911_9D32DCC.1376472064834
-Content-Location: http://localhost/content_transfer_encoding_none.html
-Content-Type: text/html;
-	charset="UTF-8"
-
-<!DOCTYPE html>
-<html lang='en'>
- <head>
-  <title>MHTML Content-Transfer-Encoding none test</title>
-  <script>
-   if (window.testRunner)
-     testRunner.dumpAsText();
-  </script>
- </head>
- <body>
-  This is a red square:<br>
-  <img src="resources/red_square.png" onerror="document.getElementById('error').innerHTML+='Failed to load image!'">
-  <div id="error"></div>
- </body>
-</html>
-
-------=_Part_ADD9911_9D32DCC.1376472064834
-Content-Location: http://localhost/resources/red_square.png
-Content-Transfer-Encoding: base64
-Content-Type: image/png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_Part_ADD9911_9D32DCC.1376472064834--
+From: <Saved by UnMHT Ver.6.3.3 with manual conversion of first part into binary encoding>

+Subject: MHTML Tests

+Date: Wed, 14 Aug 2013 11:21:04 +0200

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_Part_ADD9911_9D32DCC.1376472064834";

+	type="text/html"

+

+-----=_Part_ADD9911_9D32DCC.1376472064834

+Content-Location: http://localhost/content_transfer_encoding_none.html

+Content-Type: text/html;

+	charset="UTF-8"

+

+<!DOCTYPE html>

+<html lang='en'>

+ <head>

+  <title>MHTML Content-Transfer-Encoding none test</title>

+  <script>

+   if (window.testRunner)

+     testRunner.dumpAsText();

+  </script>

+ </head>

+ <body>

+  This is a red square:<br>

+  <img src="resources/red_square.png" onerror="document.getElementById('error').innerHTML+='Failed to load image!'">

+  <div id="error"></div>

+ </body>

+</html>

+

+------=_Part_ADD9911_9D32DCC.1376472064834

+Content-Location: http://localhost/resources/red_square.png

+Content-Transfer-Encoding: base64

+Content-Type: image/png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_Part_ADD9911_9D32DCC.1376472064834--

diff --git a/third_party/blink/web_tests/mhtml/malformed_mhtml_no_footer.mht b/third_party/blink/web_tests/mhtml/malformed_mhtml_no_footer.mht
index 9789d19..cb89d3f 100644
--- a/third_party/blink/web_tests/mhtml/malformed_mhtml_no_footer.mht
+++ b/third_party/blink/web_tests/mhtml/malformed_mhtml_no_footer.mht
@@ -1,18 +1,18 @@
-From: <Saved by Blink>
-Subject: 128x128_png.png (128?128)
-Date: Fri, 13 Oct 2016 17:40:08 -0000
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----"
-
-------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
+From: <Saved by Blink>

+Subject: 128x128_png.png (128?128)

+Date: Fri, 13 Oct 2016 17:40:08 -0000

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----"

+

+------MultipartBoundary--Xm93PP2BFJf8elJGRutH4cfnMaBMcK4sxf4o3u4L2F----

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

diff --git a/third_party/blink/web_tests/mhtml/mhtml-with-capital-mimetype-loading.mht b/third_party/blink/web_tests/mhtml/mhtml-with-capital-mimetype-loading.mht
index 233c4dfe4..a5e344c 100644
--- a/third_party/blink/web_tests/mhtml/mhtml-with-capital-mimetype-loading.mht
+++ b/third_party/blink/web_tests/mhtml/mhtml-with-capital-mimetype-loading.mht
@@ -1,22 +1,22 @@
-From: <Saved by WebKit>
-Subject: 
-Date: Mon, 5 Apr 2015 18:24:52 -0000
-MIME-Version: 1.0
-Content-Type: MULTIPART/RELATED;
-	type="text/html";
-	boundary="----=_NextPart_000_47B2_8E62210C.84C5CCF5"
-
-------=_NextPart_000_47B2_8E62210C.84C5CCF5
-Content-Type: text/html
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/mhtml-with-capital-mimetype-loading-expected.html
-
-<!DOCTYPE html><html><head><meta charset=3D"ISO-8859-1">
-</head>
-<body>
-<p> Archive page should be loaded irrespective of case sensitive mimetype</=
-p>
-
-
-</body></html>
-------=_NextPart_000_47B2_8E62210C.84C5CCF5--
+From: <Saved by WebKit>

+Subject: 

+Date: Mon, 5 Apr 2015 18:24:52 -0000

+MIME-Version: 1.0

+Content-Type: MULTIPART/RELATED;

+	type="text/html";

+	boundary="----=_NextPart_000_47B2_8E62210C.84C5CCF5"

+

+------=_NextPart_000_47B2_8E62210C.84C5CCF5

+Content-Type: text/html

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/mhtml-with-capital-mimetype-loading-expected.html

+

+<!DOCTYPE html><html><head><meta charset=3D"ISO-8859-1">

+</head>

+<body>

+<p> Archive page should be loaded irrespective of case sensitive mimetype</=

+p>

+

+

+</body></html>

+------=_NextPart_000_47B2_8E62210C.84C5CCF5--

diff --git a/third_party/blink/web_tests/mhtml/multi_frames_contentid.mht b/third_party/blink/web_tests/mhtml/multi_frames_contentid.mht
index 402b140e..3547f863 100644
--- a/third_party/blink/web_tests/mhtml/multi_frames_contentid.mht
+++ b/third_party/blink/web_tests/mhtml/multi_frames_contentid.mht
@@ -1,91 +1,91 @@
-From: <Manually edited from multi_frames_unmht.mht>
-Subject: =?iso-2022-jp?B?QSBwYWdlIHRoYXQgY29udGFpbnMgbXVsdGlwbGUgbmVzdGVkIGZyYW1lcw==?=
-Date: Wed, May 18 2011 15:20:34 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_58874EE0.2096A571";
-	type="text/html"
-
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/top_frame.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page that contains multiple nested frames</title>
-<base href=3D"http://localhost/"></base></head><body>
-This page contains several frames.<br>
-<iframe src=3D"cid:frame0@foo.bar"></iframe><br>
-<iframe src=3D"cid:frame1@foo.bar"></iframe><br>
-<iframe src=3D"cid:frame2@foo.bar"></iframe><br>
-<div style=3D"will-change:transform">And a red square:<br>
-<img src=3D"cid:redsquare@foo.bar"></div>
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-ID: <frame0@foo.bar>
-Content-Location: http://localhost/frame_0.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The first frame!
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-ID: <frame1@foo.bar>
-Content-Location: http://localhost/frame_1.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The second frame!
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-ID: <frame2@foo.bar>
-Content-Location: http://localhost/frame_2.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The third frame!<br>
-This one contains yet another frame. What a twist!<br>
-<iframe src=3D"cid:frame4@foo.bar"></iframe>
-
-
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-ID: <frame4@foo.bar>
-Content-Location: http://localhost/frame_4.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-This is frame 4!<br>
-<img src=3D"cid:redsquare@foo.bar">
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-ID: <redsquare@foo.bar>
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-------=_NextPart_000_0000_58874EE0.2096A571--
+From: <Manually edited from multi_frames_unmht.mht>

+Subject: =?iso-2022-jp?B?QSBwYWdlIHRoYXQgY29udGFpbnMgbXVsdGlwbGUgbmVzdGVkIGZyYW1lcw==?=

+Date: Wed, May 18 2011 15:20:34 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_58874EE0.2096A571";

+	type="text/html"

+

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/top_frame.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page that contains multiple nested frames</title>

+<base href=3D"http://localhost/"></base></head><body>

+This page contains several frames.<br>

+<iframe src=3D"cid:frame0@foo.bar"></iframe><br>

+<iframe src=3D"cid:frame1@foo.bar"></iframe><br>

+<iframe src=3D"cid:frame2@foo.bar"></iframe><br>

+<div style=3D"will-change:transform">And a red square:<br>

+<img src=3D"cid:redsquare@foo.bar"></div>

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-ID: <frame0@foo.bar>

+Content-Location: http://localhost/frame_0.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The first frame!

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-ID: <frame1@foo.bar>

+Content-Location: http://localhost/frame_1.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The second frame!

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-ID: <frame2@foo.bar>

+Content-Location: http://localhost/frame_2.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The third frame!<br>

+This one contains yet another frame. What a twist!<br>

+<iframe src=3D"cid:frame4@foo.bar"></iframe>

+

+

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-ID: <frame4@foo.bar>

+Content-Location: http://localhost/frame_4.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+This is frame 4!<br>

+<img src=3D"cid:redsquare@foo.bar">

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-ID: <redsquare@foo.bar>

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+------=_NextPart_000_0000_58874EE0.2096A571--

diff --git a/third_party/blink/web_tests/mhtml/multi_frames_ie.mht b/third_party/blink/web_tests/mhtml/multi_frames_ie.mht
index 8afe2cc..250f99c2b 100644
--- a/third_party/blink/web_tests/mhtml/multi_frames_ie.mht
+++ b/third_party/blink/web_tests/mhtml/multi_frames_ie.mht
@@ -1,104 +1,104 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject: A page that contains multiple nested frames
-Date: Wed, 18 May 2011 16:50:17 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="multipart/alternative";
-	boundary="----=_NextPart_000_0020_01CC157B.AAC3EF70"
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-This is a multi-part message in MIME format.
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70
-Content-Type: multipart/alternative;
-	boundary="----=_NextPart_001_0023_01CC157B.AAC41680"
-
-
-------=_NextPart_001_0023_01CC157B.AAC41680
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/top_frame.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD><TITLE>A page that contains multiple nested frames</TITLE>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>This page contains several frames.<BR><IFRAME=20
-src=3D"http://localhost/frame_0.html"></IFRAME><BR><IFRAME=20
-src=3D"http://localhost/frame_1.html"></IFRAME><BR><IFRAME=20
-src=3D"http://localhost/frame_2.html"></IFRAME><BR><DIV=20
-style=3D"will-change:transform">And a red =
-square:<BR><IMG=20
-src=3D"http://localhost/resources/red_square.png"></DIV>=20
-</BODY></HTML>
-
-------=_NextPart_001_0023_01CC157B.AAC41680
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: 7bit
-Content-Location: http://localhost/frame_0.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD>
-<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
-<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>
-<BODY>The first frame! </BODY></HTML>
-
-------=_NextPart_001_0023_01CC157B.AAC41680--
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: 7bit
-Content-Location: http://localhost/frame_1.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD>
-<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
-<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>
-<BODY>The second frame! </BODY></HTML>
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/frame_4.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>This is frame 4!<BR><IMG=20
- src=3D"http://localhost/resources/red_square.png">=20
-</BODY></HTML>
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: 7bit
-Content-Location: http://localhost/frame_2.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD>
-<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
-<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>
-<BODY>The third frame!<BR>This one contains yet another frame. What a 
-twist!<BR><IFRAME 
-src="http://localhost/frame_4.html"></IFRAME></BODY></HTML>
-
-------=_NextPart_000_0020_01CC157B.AAC3EF70--
+From: "Saved by Windows Internet Explorer 9"

+Subject: A page that contains multiple nested frames

+Date: Wed, 18 May 2011 16:50:17 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="multipart/alternative";

+	boundary="----=_NextPart_000_0020_01CC157B.AAC3EF70"

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+This is a multi-part message in MIME format.

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70

+Content-Type: multipart/alternative;

+	boundary="----=_NextPart_001_0023_01CC157B.AAC41680"

+

+

+------=_NextPart_001_0023_01CC157B.AAC41680

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/top_frame.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD><TITLE>A page that contains multiple nested frames</TITLE>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>This page contains several frames.<BR><IFRAME=20

+src=3D"http://localhost/frame_0.html"></IFRAME><BR><IFRAME=20

+src=3D"http://localhost/frame_1.html"></IFRAME><BR><IFRAME=20

+src=3D"http://localhost/frame_2.html"></IFRAME><BR><DIV=20

+style=3D"will-change:transform">And a red =

+square:<BR><IMG=20

+src=3D"http://localhost/resources/red_square.png"></DIV>=20

+</BODY></HTML>

+

+------=_NextPart_001_0023_01CC157B.AAC41680

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: 7bit

+Content-Location: http://localhost/frame_0.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD>

+<META content="text/html; charset=windows-1252" http-equiv=Content-Type>

+<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>

+<BODY>The first frame! </BODY></HTML>

+

+------=_NextPart_001_0023_01CC157B.AAC41680--

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: 7bit

+Content-Location: http://localhost/frame_1.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD>

+<META content="text/html; charset=windows-1252" http-equiv=Content-Type>

+<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>

+<BODY>The second frame! </BODY></HTML>

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/frame_4.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>This is frame 4!<BR><IMG=20

+ src=3D"http://localhost/resources/red_square.png">=20

+</BODY></HTML>

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: 7bit

+Content-Location: http://localhost/frame_2.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD>

+<META content="text/html; charset=windows-1252" http-equiv=Content-Type>

+<META name=GENERATOR content="MSHTML 9.00.8112.16421"></HEAD>

+<BODY>The third frame!<BR>This one contains yet another frame. What a 

+twist!<BR><IFRAME 

+src="http://localhost/frame_4.html"></IFRAME></BODY></HTML>

+

+------=_NextPart_000_0020_01CC157B.AAC3EF70--

diff --git a/third_party/blink/web_tests/mhtml/multi_frames_unmht.mht b/third_party/blink/web_tests/mhtml/multi_frames_unmht.mht
index 458a898..bf6a88f 100644
--- a/third_party/blink/web_tests/mhtml/multi_frames_unmht.mht
+++ b/third_party/blink/web_tests/mhtml/multi_frames_unmht.mht
@@ -1,86 +1,86 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?QSBwYWdlIHRoYXQgY29udGFpbnMgbXVsdGlwbGUgbmVzdGVkIGZyYW1lcw==?=
-Date: Wed, May 18 2011 15:20:34 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_58874EE0.2096A571";
-	type="text/html"
-
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/top_frame.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page that contains multiple nested frames</title>
-<base href=3D"http://localhost/"></base></head><body>
-This page contains several frames.<br>
-<iframe src=3D"http://localhost/frame_0.html"></iframe><br>
-<iframe src=3D"http://localhost/frame_1.html"></iframe><br>
-<iframe src=3D"http://localhost/frame_2.html"></iframe><br>
-<div style=3D"will-change:transform">And a red square:<br>
-<img src=3D"resources/red_square.png"></div>
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/frame_0.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The first frame!
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/frame_1.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The second frame!
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/frame_2.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-The third frame!<br>
-This one contains yet another frame. What a twist!<br>
-<iframe src=3D"http://localhost/frame_4.html"></iframe>
-
-
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/frame_4.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-<base href=3D"http://localhost/"></base></head><body>
-This is frame 4!<br>
-<img src=3D"resources/red_square.png">
-</body></html>
-------=_NextPart_000_0000_58874EE0.2096A571
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-------=_NextPart_000_0000_58874EE0.2096A571--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?QSBwYWdlIHRoYXQgY29udGFpbnMgbXVsdGlwbGUgbmVzdGVkIGZyYW1lcw==?=

+Date: Wed, May 18 2011 15:20:34 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_58874EE0.2096A571";

+	type="text/html"

+

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/top_frame.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page that contains multiple nested frames</title>

+<base href=3D"http://localhost/"></base></head><body>

+This page contains several frames.<br>

+<iframe src=3D"http://localhost/frame_0.html"></iframe><br>

+<iframe src=3D"http://localhost/frame_1.html"></iframe><br>

+<iframe src=3D"http://localhost/frame_2.html"></iframe><br>

+<div style=3D"will-change:transform">And a red square:<br>

+<img src=3D"resources/red_square.png"></div>

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/frame_0.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The first frame!

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/frame_1.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The second frame!

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/frame_2.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+The third frame!<br>

+This one contains yet another frame. What a twist!<br>

+<iframe src=3D"http://localhost/frame_4.html"></iframe>

+

+

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/frame_4.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+<base href=3D"http://localhost/"></base></head><body>

+This is frame 4!<br>

+<img src=3D"resources/red_square.png">

+</body></html>

+------=_NextPart_000_0000_58874EE0.2096A571

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+------=_NextPart_000_0000_58874EE0.2096A571--

diff --git a/third_party/blink/web_tests/mhtml/page_with_css_and_js_ie.mht b/third_party/blink/web_tests/mhtml/page_with_css_and_js_ie.mht
index 078834c..099de1a 100644
--- a/third_party/blink/web_tests/mhtml/page_with_css_and_js_ie.mht
+++ b/third_party/blink/web_tests/mhtml/page_with_css_and_js_ie.mht
@@ -1,75 +1,75 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject:
-Date: Wed, 18 May 2011 16:49:23 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----=_NextPart_000_0012_01CC157B.8AA06570"
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-This is a multi-part message in MIME format.
-
-------=_NextPart_000_0012_01CC157B.8AA06570
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_css_and_js.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type><LINK=20
-rel=3Dstylesheet type=3Dtext/css =
-href=3D"http://localhost/resources/hide_image.css">
-<SCRIPT type=3Dtext/javascript=20
-src=3D"http://localhost/resources/remove_image_script.js"></SCRIPT>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY onload=3DonLoad()>This page tests that CSS and JavaScript =
-resources are=20
-retrieved correctly for MHTML files.<BR><BR>There should be only 1 red =
-square=20
-below:=20
-<DIV id=3DfirstDiv><IMG=20
-src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV>
-<DIV id=3DsecondDiv>The red square below should be hidden by way of =
-CSS.<BR><IMG=20
-src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV>
-<DIV id=3DthirdDiv>The red square below should be hidden by way of=20
-JavaScript.<BR><IMG=20
-src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV></BODY><=
-/HTML>
-
-------=_NextPart_000_0012_01CC157B.8AA06570
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_NextPart_000_0012_01CC157B.8AA06570
-Content-Type: text/css;
-	charset="iso-8859-1"
-Content-Transfer-Encoding: 7bit
-Content-Location: http://localhost/resources/hide_image.css
-
-#secondDiv {
-	DISPLAY: none
-}
-
-------=_NextPart_000_0012_01CC157B.8AA06570
-Content-Type: application/octet-stream
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/resources/remove_image_script.js
-
-function onLoad() {=0A=
-    divToRemove =3D document.getElementById("thirdDiv");=0A=
-    divToRemove.parentNode.removeChild(divToRemove);=0A=
-    if (window.testRunner)=0A=
-      testRunner.notifyDone();=0A=
-}
-------=_NextPart_000_0012_01CC157B.8AA06570--
+From: "Saved by Windows Internet Explorer 9"

+Subject:

+Date: Wed, 18 May 2011 16:49:23 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----=_NextPart_000_0012_01CC157B.8AA06570"

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+This is a multi-part message in MIME format.

+

+------=_NextPart_000_0012_01CC157B.8AA06570

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_css_and_js.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type><LINK=20

+rel=3Dstylesheet type=3Dtext/css =

+href=3D"http://localhost/resources/hide_image.css">

+<SCRIPT type=3Dtext/javascript=20

+src=3D"http://localhost/resources/remove_image_script.js"></SCRIPT>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY onload=3DonLoad()>This page tests that CSS and JavaScript =

+resources are=20

+retrieved correctly for MHTML files.<BR><BR>There should be only 1 red =

+square=20

+below:=20

+<DIV id=3DfirstDiv><IMG=20

+src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV>

+<DIV id=3DsecondDiv>The red square below should be hidden by way of =

+CSS.<BR><IMG=20

+src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV>

+<DIV id=3DthirdDiv>The red square below should be hidden by way of=20

+JavaScript.<BR><IMG=20

+src=3D"http://localhost/resources/red_square.png"><BR><BR></DIV></BODY><=

+/HTML>

+

+------=_NextPart_000_0012_01CC157B.8AA06570

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_NextPart_000_0012_01CC157B.8AA06570

+Content-Type: text/css;

+	charset="iso-8859-1"

+Content-Transfer-Encoding: 7bit

+Content-Location: http://localhost/resources/hide_image.css

+

+#secondDiv {

+	DISPLAY: none

+}

+

+------=_NextPart_000_0012_01CC157B.8AA06570

+Content-Type: application/octet-stream

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/resources/remove_image_script.js

+

+function onLoad() {=0A=

+    divToRemove =3D document.getElementById("thirdDiv");=0A=

+    divToRemove.parentNode.removeChild(divToRemove);=0A=

+    if (window.testRunner)=0A=

+      testRunner.notifyDone();=0A=

+}

+------=_NextPart_000_0012_01CC157B.8AA06570--

diff --git a/third_party/blink/web_tests/mhtml/page_with_css_and_js_unmht.mht b/third_party/blink/web_tests/mhtml/page_with_css_and_js_unmht.mht
index a008ab7..a04608c 100644
--- a/third_party/blink/web_tests/mhtml/page_with_css_and_js_unmht.mht
+++ b/third_party/blink/web_tests/mhtml/page_with_css_and_js_unmht.mht
@@ -1,69 +1,69 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B??=
-Date: Wed, May 18 2011 15:21:05 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_C2ECC76E.5EC79255";
-	type="text/html"
-
-------=_NextPart_000_0000_C2ECC76E.5EC79255
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_css_and_js.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-  <link type=3D"text/css" rel=3D"stylesheet" href=3D"resources/hide_image.c=
-ss"></link>
-  =20
-  <script src=3D"resources/remove_image_script.js" type=3D"text/javascript"=
-></script>
-<base href=3D"http://localhost/"></base></head><body onload=3D"onLoad()">
-This page tests that CSS and JavaScript resources are retrieved correctly=
- for MHTML files.<br><br>
-There should be only 1 red square below:
-<div id=3D"firstDiv">
-<img src=3D"resources/red_square.png"><br><br>
-</div>
-<div id=3D"secondDiv">
-The red square below should be hidden by way of CSS.<br>
-<img src=3D"resources/red_square.png"><br><br>
-</div>
-<div id=3D"thirdDiv">
-The red square below should be hidden by way of JavaScript.<br>
-<img src=3D"resources/red_square.png"><br><br>
-</div>
-
- =20
-</body></html>
-------=_NextPart_000_0000_C2ECC76E.5EC79255
-Content-Type: text/css
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/resources/hide_image.css
-
-#secondDiv { display: none; }
-
-------=_NextPart_000_0000_C2ECC76E.5EC79255
-Content-Type: text/javascript
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/resources/remove_image_script.js
-
-function onLoad() {
-    divToRemove =3D document.getElementById("thirdDiv");
-    divToRemove.parentNode.removeChild(divToRemove);
-    if (window.testRunner)
-      testRunner.notifyDone();
-}
-------=_NextPart_000_0000_C2ECC76E.5EC79255
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-------=_NextPart_000_0000_C2ECC76E.5EC79255--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B??=

+Date: Wed, May 18 2011 15:21:05 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_C2ECC76E.5EC79255";

+	type="text/html"

+

+------=_NextPart_000_0000_C2ECC76E.5EC79255

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_css_and_js.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+  <link type=3D"text/css" rel=3D"stylesheet" href=3D"resources/hide_image.c=

+ss"></link>

+  =20

+  <script src=3D"resources/remove_image_script.js" type=3D"text/javascript"=

+></script>

+<base href=3D"http://localhost/"></base></head><body onload=3D"onLoad()">

+This page tests that CSS and JavaScript resources are retrieved correctly=

+ for MHTML files.<br><br>

+There should be only 1 red square below:

+<div id=3D"firstDiv">

+<img src=3D"resources/red_square.png"><br><br>

+</div>

+<div id=3D"secondDiv">

+The red square below should be hidden by way of CSS.<br>

+<img src=3D"resources/red_square.png"><br><br>

+</div>

+<div id=3D"thirdDiv">

+The red square below should be hidden by way of JavaScript.<br>

+<img src=3D"resources/red_square.png"><br><br>

+</div>

+

+ =20

+</body></html>

+------=_NextPart_000_0000_C2ECC76E.5EC79255

+Content-Type: text/css

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/resources/hide_image.css

+

+#secondDiv { display: none; }

+

+------=_NextPart_000_0000_C2ECC76E.5EC79255

+Content-Type: text/javascript

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/resources/remove_image_script.js

+

+function onLoad() {

+    divToRemove =3D document.getElementById("thirdDiv");

+    divToRemove.parentNode.removeChild(divToRemove);

+    if (window.testRunner)

+      testRunner.notifyDone();

+}

+------=_NextPart_000_0000_C2ECC76E.5EC79255

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+------=_NextPart_000_0000_C2ECC76E.5EC79255--

diff --git a/third_party/blink/web_tests/mhtml/page_with_image_ie.mht b/third_party/blink/web_tests/mhtml/page_with_image_ie.mht
index 306297b..812e55b 100644
--- a/third_party/blink/web_tests/mhtml/page_with_image_ie.mht
+++ b/third_party/blink/web_tests/mhtml/page_with_image_ie.mht
@@ -1,39 +1,39 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject: Page with square
-Date: Wed, 18 May 2011 16:49:44 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----=_NextPart_000_001B_01CC157B.96F808A0"
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-This is a multi-part message in MIME format.
-
-------=_NextPart_000_001B_01CC157B.96F808A0
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_image.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD><TITLE>Page with square</TITLE>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>This is a red square:<BR><IMG=20
-src=3D"http://localhost/resources/red_square.png">=20
-</BODY></HTML>
-
-------=_NextPart_000_001B_01CC157B.96F808A0
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_NextPart_000_001B_01CC157B.96F808A0--
+From: "Saved by Windows Internet Explorer 9"

+Subject: Page with square

+Date: Wed, 18 May 2011 16:49:44 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----=_NextPart_000_001B_01CC157B.96F808A0"

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+This is a multi-part message in MIME format.

+

+------=_NextPart_000_001B_01CC157B.96F808A0

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_image.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD><TITLE>Page with square</TITLE>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>This is a red square:<BR><IMG=20

+src=3D"http://localhost/resources/red_square.png">=20

+</BODY></HTML>

+

+------=_NextPart_000_001B_01CC157B.96F808A0

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_NextPart_000_001B_01CC157B.96F808A0--

diff --git a/third_party/blink/web_tests/mhtml/page_with_image_unmht.mht b/third_party/blink/web_tests/mhtml/page_with_image_unmht.mht
index ed29dfb8..d7e8ad5 100644
--- a/third_party/blink/web_tests/mhtml/page_with_image_unmht.mht
+++ b/third_party/blink/web_tests/mhtml/page_with_image_unmht.mht
@@ -1,33 +1,33 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?UGFnZSB3aXRoIHNxdWFyZQ==?=
-Date: Wed, May 18 2011 16:38:33 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_02C8A5EE.D896CA6B";
-	type="text/html"
-
-------=_NextPart_000_0000_02C8A5EE.D896CA6B
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_image.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>Page with square</title>
-<base href=3D"http://localhost/"></base></head><body>
-This is a red square:<br>
-<img src=3D"resources/red_square.png">
-</body></html>
-------=_NextPart_000_0000_02C8A5EE.D896CA6B
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-------=_NextPart_000_0000_02C8A5EE.D896CA6B--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?UGFnZSB3aXRoIHNxdWFyZQ==?=

+Date: Wed, May 18 2011 16:38:33 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_02C8A5EE.D896CA6B";

+	type="text/html"

+

+------=_NextPart_000_0000_02C8A5EE.D896CA6B

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_image.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>Page with square</title>

+<base href=3D"http://localhost/"></base></head><body>

+This is a red square:<br>

+<img src=3D"resources/red_square.png">

+</body></html>

+------=_NextPart_000_0000_02C8A5EE.D896CA6B

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+------=_NextPart_000_0000_02C8A5EE.D896CA6B--

diff --git a/third_party/blink/web_tests/mhtml/page_with_javascript.mht b/third_party/blink/web_tests/mhtml/page_with_javascript.mht
index 403f59b..c9aebcb6 100644
--- a/third_party/blink/web_tests/mhtml/page_with_javascript.mht
+++ b/third_party/blink/web_tests/mhtml/page_with_javascript.mht
@@ -1,29 +1,29 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=
-Date: Wed, May 11 2011 15:36:36 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_87206557.D2C008B0";
-	type="text/html"
-
-------=_NextPart_000_0000_87206557.D2C008B0
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_javascript.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A page with JavaScript</title>
-<h1>This page has content generated by JavaScript</h1>
-Javascript is not run, so that dynamic content should not show.
-<div id=3D"myDiv"></div>
-
-<script>
- document.getElementById('myDiv').innerHTML =3D
-      "JavaScript is in the house!";
-</script>
-
-</body></html>
-------=_NextPart_000_0000_87206557.D2C008B0--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=

+Date: Wed, May 11 2011 15:36:36 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_87206557.D2C008B0";

+	type="text/html"

+

+------=_NextPart_000_0000_87206557.D2C008B0

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_javascript.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A page with JavaScript</title>

+<h1>This page has content generated by JavaScript</h1>

+Javascript is not run, so that dynamic content should not show.

+<div id=3D"myDiv"></div>

+

+<script>

+ document.getElementById('myDiv').innerHTML =3D

+      "JavaScript is in the house!";

+</script>

+

+</body></html>

+------=_NextPart_000_0000_87206557.D2C008B0--

diff --git a/third_party/blink/web_tests/mhtml/prefetch-preload.mht b/third_party/blink/web_tests/mhtml/prefetch-preload.mht
index 3c31419e..82264e1 100644
--- a/third_party/blink/web_tests/mhtml/prefetch-preload.mht
+++ b/third_party/blink/web_tests/mhtml/prefetch-preload.mht
@@ -1,44 +1,44 @@
-Content-Type: multipart/related; boundary="===============2480310482194406143=="
-MIME-Version: 1.0
-Content-Location: http://localhost/prefetch-preload.mhtml_original
-
---===============2480310482194406143==
-Content-Type: text/html
-MIME-Version: 1.0
-Content-Location: http://localhost/prefetch-preload.mhtml_original
-Content-Transfer-Encoding: binary
-
-<html>
-<link rel="prefetch" href="http://localhost/resources/style1.css">
-<link rel="preload" as="style" href="http://localhost/resources/style2.css">
-<link rel="stylesheet" href="http://localhost/resources/style1.css">
-<link rel="stylesheet" href="http://localhost/resources/style2.css">
-<img class="foo" src="http://localhost/resources/red_square.png">
-</html>
---===============2480310482194406143==
-Content-Type: text/css
-MIME-Version: 1.0
-Content-Location: http://localhost/resources/style1.css
-Content-Transfer-Encoding: binary
-
-.foo { position: fixed; top: 30px; }
---===============2480310482194406143==
-Content-Type: text/css
-MIME-Version: 1.0
-Content-Location: http://localhost/resources/style2.css
-Content-Transfer-Encoding: binary
-
-.foo { position: fixed; left: 60px; }
---===============2480310482194406143==
-Content-Type: image/png
-MIME-Version: 1.0
-Content-Location: http://localhost/resources/red_square.png
-Content-Transfer-Encoding: base64
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
+Content-Type: multipart/related; boundary="===============2480310482194406143=="

+MIME-Version: 1.0

+Content-Location: http://localhost/prefetch-preload.mhtml_original

+

+--===============2480310482194406143==

+Content-Type: text/html

+MIME-Version: 1.0

+Content-Location: http://localhost/prefetch-preload.mhtml_original

+Content-Transfer-Encoding: binary

+

+<html>

+<link rel="prefetch" href="http://localhost/resources/style1.css">

+<link rel="preload" as="style" href="http://localhost/resources/style2.css">

+<link rel="stylesheet" href="http://localhost/resources/style1.css">

+<link rel="stylesheet" href="http://localhost/resources/style2.css">

+<img class="foo" src="http://localhost/resources/red_square.png">

+</html>

+--===============2480310482194406143==

+Content-Type: text/css

+MIME-Version: 1.0

+Content-Location: http://localhost/resources/style1.css

+Content-Transfer-Encoding: binary

+

+.foo { position: fixed; top: 30px; }

+--===============2480310482194406143==

+Content-Type: text/css

+MIME-Version: 1.0

+Content-Location: http://localhost/resources/style2.css

+Content-Transfer-Encoding: binary

+

+.foo { position: fixed; left: 60px; }

+--===============2480310482194406143==

+Content-Type: image/png

+MIME-Version: 1.0

+Content-Location: http://localhost/resources/red_square.png

+Content-Transfer-Encoding: base64

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

 --===============2480310482194406143==--
\ No newline at end of file
diff --git a/third_party/blink/web_tests/mhtml/relative_url.mht b/third_party/blink/web_tests/mhtml/relative_url.mht
index 3eac22c..c4a3f9a 100644
--- a/third_party/blink/web_tests/mhtml/relative_url.mht
+++ b/third_party/blink/web_tests/mhtml/relative_url.mht
@@ -1,42 +1,42 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject: Page with square
-Date: Wed, 18 May 2011 16:49:44 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----=_NextPart_000_001B_01CC157B.96F808A0"
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-This is a multi-part message in MIME format.
-
-------=_NextPart_000_001B_01CC157B.96F808A0
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/page_with_image.html
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD><TITLE>Page with square</TITLE>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>
-Image with an absolute URL:<BR><IMG=20
-src=3D"http://localhost/resources/red_square.png"/>=20
-<br>Image with a relative URL:<BR><IMG=20
-src=3D"resources/red_square.png"/>=20
-</BODY></HTML>
-
-------=_NextPart_000_001B_01CC157B.96F808A0
-Content-Type: image/png
-Content-Transfer-Encoding: base64
-Content-Location: http://localhost/resources/red_square.png
-
-iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
-jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV
-PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR
-V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA
-AAAASUVORK5CYII=
-
-------=_NextPart_000_001B_01CC157B.96F808A0--
+From: "Saved by Windows Internet Explorer 9"

+Subject: Page with square

+Date: Wed, 18 May 2011 16:49:44 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----=_NextPart_000_001B_01CC157B.96F808A0"

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+This is a multi-part message in MIME format.

+

+------=_NextPart_000_001B_01CC157B.96F808A0

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/page_with_image.html

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD><TITLE>Page with square</TITLE>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>

+Image with an absolute URL:<BR><IMG=20

+src=3D"http://localhost/resources/red_square.png"/>=20

+<br>Image with a relative URL:<BR><IMG=20

+src=3D"resources/red_square.png"/>=20

+</BODY></HTML>

+

+------=_NextPart_000_001B_01CC157B.96F808A0

+Content-Type: image/png

+Content-Transfer-Encoding: base64

+Content-Location: http://localhost/resources/red_square.png

+

+iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACx

+jwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACESURBVEhL7ZYxDoAwCEXB2LGTo46ewXj/zXgV

+PQKgexP/Ai6l889/6Stp4HtZjYKOiRCpEpfSEIYgJqxNMFTkFUjVXiZhT6qGirwCqdrLJOxJ1VCR

+V6A/1XxNc9jqQ6JkpjTU2rwQR+5c4769YCM5zn/BX4PY33Dljb0+JtiTqqEir8ADWEIY6dz7d1cA

+AAAASUVORK5CYII=

+

+------=_NextPart_000_001B_01CC157B.96F808A0--

diff --git a/third_party/blink/web_tests/mhtml/relaxed-content-type-parameters.mht b/third_party/blink/web_tests/mhtml/relaxed-content-type-parameters.mht
index 063b9fb..5946d197 100644
--- a/third_party/blink/web_tests/mhtml/relaxed-content-type-parameters.mht
+++ b/third_party/blink/web_tests/mhtml/relaxed-content-type-parameters.mht
@@ -1,24 +1,24 @@
-Content-Type: multipart/related; start=<op.mhtml.1234567891234.1234567890abcdef@1111:ffff:2222:ee:3333:dddd:4444:cccc>; boundary=----------LHWAs1iPsCI2GBNY69BX16
-Content-Location: file://localhost/relaxed-content-type-parameters.mhtml_original
-Subject: =?utf-8?Q?MHTML=20Tests?=
-MIME-Version: 1.0
-
-------------LHWAs1iPsCI2GBNY69BX16
-Content-Disposition: inline; filename=relaxed-content-type-parameters.mhtml_original
-Content-Type: text/html; name=relaxed-content-type-parameters.mhtml_original
-Content-ID: <op.mhtml.1234567891234.1234567890abcdef@1111:ffff:2222:ee:3333:dddd:4444:cccc>
-Content-Location: file://localhost/relaxed-content-type-parameters.mhtml_original
-Content-Transfer-Encoding: 7bit
-
-<!DOCTYPE html>
-<html lang='en'>
- <head>
-  <meta charset='utf-8'>
-  <title>MHTML Tests</title>
- </head>
- <body>
-  <h1>MHTML Relaxed Content-Type parameters test</h1>
- </body>
-</html>
-
-------------LHWAs1iPsCI2GBNY69BX16--
+Content-Type: multipart/related; start=<op.mhtml.1234567891234.1234567890abcdef@1111:ffff:2222:ee:3333:dddd:4444:cccc>; boundary=----------LHWAs1iPsCI2GBNY69BX16

+Content-Location: file://localhost/relaxed-content-type-parameters.mhtml_original

+Subject: =?utf-8?Q?MHTML=20Tests?=

+MIME-Version: 1.0

+

+------------LHWAs1iPsCI2GBNY69BX16

+Content-Disposition: inline; filename=relaxed-content-type-parameters.mhtml_original

+Content-Type: text/html; name=relaxed-content-type-parameters.mhtml_original

+Content-ID: <op.mhtml.1234567891234.1234567890abcdef@1111:ffff:2222:ee:3333:dddd:4444:cccc>

+Content-Location: file://localhost/relaxed-content-type-parameters.mhtml_original

+Content-Transfer-Encoding: 7bit

+

+<!DOCTYPE html>

+<html lang='en'>

+ <head>

+  <meta charset='utf-8'>

+  <title>MHTML Tests</title>

+ </head>

+ <body>

+  <h1>MHTML Relaxed Content-Type parameters test</h1>

+ </body>

+</html>

+

+------------LHWAs1iPsCI2GBNY69BX16--

diff --git a/third_party/blink/web_tests/mhtml/resource_not_found_in_archive.mht b/third_party/blink/web_tests/mhtml/resource_not_found_in_archive.mht
index fb5c425..ba641b5 100644
--- a/third_party/blink/web_tests/mhtml/resource_not_found_in_archive.mht
+++ b/third_party/blink/web_tests/mhtml/resource_not_found_in_archive.mht
@@ -1,22 +1,22 @@
-From: <Saved by WebKit>
-Subject: 
-Date: Mon, 5 Apr 2015 18:24:52 -0000
-MIME-Version: 1.0
-Content-Type: MULTIPART/RELATED;
-	type="text/html";
-	boundary="----=_NextPart_000_47B2_8E62210C.84C5CCF5"
-
-------=_NextPart_000_47B2_8E62210C.84C5CCF5
-Content-Type: text/html
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/resource_not_in_archive-expected.html
-
-<!DOCTYPE html><html><head><meta charset=3D"ISO-8859-1">
-</head>
-<body>
-
-<h1>Broken image should be shown.</h1>
-<img src="http://localhost/resources/red-square.png">
-
-</body></html>
-------=_NextPart_000_47B2_8E62210C.84C5CCF5--
+From: <Saved by WebKit>

+Subject: 

+Date: Mon, 5 Apr 2015 18:24:52 -0000

+MIME-Version: 1.0

+Content-Type: MULTIPART/RELATED;

+	type="text/html";

+	boundary="----=_NextPart_000_47B2_8E62210C.84C5CCF5"

+

+------=_NextPart_000_47B2_8E62210C.84C5CCF5

+Content-Type: text/html

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/resource_not_in_archive-expected.html

+

+<!DOCTYPE html><html><head><meta charset=3D"ISO-8859-1">

+</head>

+<body>

+

+<h1>Broken image should be shown.</h1>

+<img src="http://localhost/resources/red-square.png">

+

+</body></html>

+------=_NextPart_000_47B2_8E62210C.84C5CCF5--

diff --git a/third_party/blink/web_tests/mhtml/shared_buffer_bug.mht b/third_party/blink/web_tests/mhtml/shared_buffer_bug.mht
index 2fcc1c1..ad0300ed 100644
--- a/third_party/blink/web_tests/mhtml/shared_buffer_bug.mht
+++ b/third_party/blink/web_tests/mhtml/shared_buffer_bug.mht
@@ -1,171 +1,171 @@
-From: <Saved by WebKit>
-Subject:
-Date: Sat, 12 Oct 2012 10:15:17 -0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	type="text/html";
-	boundary="----=_NextPart_000_7387_D22A981E.ADD1887E"
-
-------=_NextPart_000_7387_D22A981E.ADD1887E
-Content-Type: text/html
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/sharred_buffer_bug.html
-
-<html><head><meta charset=3D"ISO-8859-1">
-<link rel=3D"stylesheet" type=3D"text/css" href=3D"http://localhost/resourc=
-es/style.css">
-
-</head>
-
-<body>
-  This is a test for a bug in SharedBuffer.
-  <h1>This text should not be shown</h1>
-
-
-
-</body></html>
-------=_NextPart_000_7387_D22A981E.ADD1887E
-Content-Type: text/css
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/resources/style.css
-
-/*
-The point is to reach a size of n * 4096 bytes (with n > 1)
-followed by a blank line to trigger a bug in SharredBuffer.
-
-Let's go:
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-012345678901234567890123456789012345678901234567890123456789
-*/
-
-
-h1 { visibility: hidden; }
-
-------=_NextPart_000_7387_D22A981E.ADD1887E--
+From: <Saved by WebKit>

+Subject:

+Date: Sat, 12 Oct 2012 10:15:17 -0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	type="text/html";

+	boundary="----=_NextPart_000_7387_D22A981E.ADD1887E"

+

+------=_NextPart_000_7387_D22A981E.ADD1887E

+Content-Type: text/html

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/sharred_buffer_bug.html

+

+<html><head><meta charset=3D"ISO-8859-1">

+<link rel=3D"stylesheet" type=3D"text/css" href=3D"http://localhost/resourc=

+es/style.css">

+

+</head>

+

+<body>

+  This is a test for a bug in SharedBuffer.

+  <h1>This text should not be shown</h1>

+

+

+

+</body></html>

+------=_NextPart_000_7387_D22A981E.ADD1887E

+Content-Type: text/css

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/resources/style.css

+

+/*

+The point is to reach a size of n * 4096 bytes (with n > 1)

+followed by a blank line to trigger a bug in SharredBuffer.

+

+Let's go:

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+012345678901234567890123456789012345678901234567890123456789

+*/

+

+

+h1 { visibility: hidden; }

+

+------=_NextPart_000_7387_D22A981E.ADD1887E--

diff --git a/third_party/blink/web_tests/mhtml/simple_page_ie.mht b/third_party/blink/web_tests/mhtml/simple_page_ie.mht
index f0afef3..cf0d82f 100644
--- a/third_party/blink/web_tests/mhtml/simple_page_ie.mht
+++ b/third_party/blink/web_tests/mhtml/simple_page_ie.mht
@@ -1,19 +1,19 @@
-From: "Saved by Windows Internet Explorer 9"
-Subject: A simple page
-Date: Wed, 18 May 2011 16:50:01 -0700
-MIME-Version: 1.0
-Content-Type: text/html;
-	charset="Windows-1252"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/simple_page.html
-X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML><HEAD><TITLE>A simple page</TITLE>
-<META content=3D"text/html; charset=3Dwindows-1252" =
-http-equiv=3DContent-Type>
-
-<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>
-<BODY>
-<H1>This is a very simple page</H1>Very <B>basic</B> page. =
-</BODY></HTML>
+From: "Saved by Windows Internet Explorer 9"

+Subject: A simple page

+Date: Wed, 18 May 2011 16:50:01 -0700

+MIME-Version: 1.0

+Content-Type: text/html;

+	charset="Windows-1252"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/simple_page.html

+X-MimeOLE: Produced By Microsoft MimeOLE V6.1.7600.16776

+

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

+<HTML><HEAD><TITLE>A simple page</TITLE>

+<META content=3D"text/html; charset=3Dwindows-1252" =

+http-equiv=3DContent-Type>

+

+<META name=3DGENERATOR content=3D"MSHTML 9.00.8112.16421"></HEAD>

+<BODY>

+<H1>This is a very simple page</H1>Very <B>basic</B> page. =

+</BODY></HTML>

diff --git a/third_party/blink/web_tests/mhtml/simple_page_unmht.mht b/third_party/blink/web_tests/mhtml/simple_page_unmht.mht
index f93adf6..93524ce 100644
--- a/third_party/blink/web_tests/mhtml/simple_page_unmht.mht
+++ b/third_party/blink/web_tests/mhtml/simple_page_unmht.mht
@@ -1,23 +1,23 @@
-From: <Saved by UnMHT>
-Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=
-Date: Wed, May 11 2011 15:36:36 GMT-0700
-MIME-Version: 1.0
-Content-Type: multipart/related;
-	boundary="----=_NextPart_000_0000_87206557.D2C008B0";
-	type="text/html"
-
-------=_NextPart_000_0000_87206557.D2C008B0
-Content-Type: text/html; charset="ISO-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Content-Location: http://localhost/simple_page.html
-
-<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
-=3Diso-8859-1">
-
-
-<title>A simple page</title>
-<base href=3D"http://localhost/"></base></head><body>
-<h1>This is a very simple page</h1>
-Very <b>basic</b> page.
-</body></html>
-------=_NextPart_000_0000_87206557.D2C008B0--
+From: <Saved by UnMHT>

+Subject: =?iso-2022-jp?B?QSBzaW1wbGUgcGFnZQ==?=

+Date: Wed, May 11 2011 15:36:36 GMT-0700

+MIME-Version: 1.0

+Content-Type: multipart/related;

+	boundary="----=_NextPart_000_0000_87206557.D2C008B0";

+	type="text/html"

+

+------=_NextPart_000_0000_87206557.D2C008B0

+Content-Type: text/html; charset="ISO-8859-1"

+Content-Transfer-Encoding: quoted-printable

+Content-Location: http://localhost/simple_page.html

+

+<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=

+=3Diso-8859-1">

+

+

+<title>A simple page</title>

+<base href=3D"http://localhost/"></base></head><body>

+<h1>This is a very simple page</h1>

+Very <b>basic</b> page.

+</body></html>

+------=_NextPart_000_0000_87206557.D2C008B0--

diff --git a/third_party/blink/web_tests/mhtml/transfer_encoding_7bit.mht b/third_party/blink/web_tests/mhtml/transfer_encoding_7bit.mht
index 20326d4e..099064c96 100644
--- a/third_party/blink/web_tests/mhtml/transfer_encoding_7bit.mht
+++ b/third_party/blink/web_tests/mhtml/transfer_encoding_7bit.mht
@@ -1,22 +1,22 @@
-Content-Type: multipart/related; boundary="===============6683215525243774815=="
-MIME-Version: 1.0
-Content-Location: transfer_encoding_7bit.html_original
-
---===============6683215525243774815==
-Content-Type: text/html
-MIME-Version: 1.0
-Content-Location: transfer_encoding_7bit.html_original
-Content-Transfer-Encoding: 7bit
-
-<!DOCTYPE html>
-<html lang='en'>
- <head>
-  <meta charset='utf-8'>
-  <title>MHTML Tests</title>
- </head>
- <body>
-  <h1>MHTML Content-Transfer-Encoding 7-bit test - ;)</h1>
- </body>
-</html>
-
---===============6683215525243774815==--
+Content-Type: multipart/related; boundary="===============6683215525243774815=="

+MIME-Version: 1.0

+Content-Location: transfer_encoding_7bit.html_original

+

+--===============6683215525243774815==

+Content-Type: text/html

+MIME-Version: 1.0

+Content-Location: transfer_encoding_7bit.html_original

+Content-Transfer-Encoding: 7bit

+

+<!DOCTYPE html>

+<html lang='en'>

+ <head>

+  <meta charset='utf-8'>

+  <title>MHTML Tests</title>

+ </head>

+ <body>

+  <h1>MHTML Content-Transfer-Encoding 7-bit test - ;)</h1>

+ </body>

+</html>

+

+--===============6683215525243774815==--

diff --git a/third_party/blink/web_tests/mhtml/transfer_encoding_8bit.mht b/third_party/blink/web_tests/mhtml/transfer_encoding_8bit.mht
index 1ce14d4..44094ffb 100644
--- a/third_party/blink/web_tests/mhtml/transfer_encoding_8bit.mht
+++ b/third_party/blink/web_tests/mhtml/transfer_encoding_8bit.mht
@@ -1,22 +1,22 @@
-Content-Type: multipart/related; boundary="===============0861565773462052241=="
-MIME-Version: 1.0
-Content-Location: transfer_encoding_8bit.html_original
-
---===============0861565773462052241==
-Content-Type: text/html
-MIME-Version: 1.0
-Content-Location: transfer_encoding_8bit.html_original
-Content-Transfer-Encoding: 8bit
-
-<!DOCTYPE html>
-<html lang='en'>
- <head>
-  <meta charset='utf-8'>
-  <title>MHTML Tests</title>
- </head>
- <body>
-  <h1>MHTML Content-Transfer-Encoding 8-bit test - 😉</h1>
- </body>
-</html>
-
---===============0861565773462052241==--
+Content-Type: multipart/related; boundary="===============0861565773462052241=="

+MIME-Version: 1.0

+Content-Location: transfer_encoding_8bit.html_original

+

+--===============0861565773462052241==

+Content-Type: text/html

+MIME-Version: 1.0

+Content-Location: transfer_encoding_8bit.html_original

+Content-Transfer-Encoding: 8bit

+

+<!DOCTYPE html>

+<html lang='en'>

+ <head>

+  <meta charset='utf-8'>

+  <title>MHTML Tests</title>

+ </head>

+ <body>

+  <h1>MHTML Content-Transfer-Encoding 8-bit test - 😉</h1>

+ </body>

+</html>

+

+--===============0861565773462052241==--

diff --git a/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative-expected.txt b/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative-expected.txt
index 9b9a3224d..c6f298c 100644
--- a/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative-expected.txt
+++ b/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-iterate-before-beginning.tentative-expected.txt
@@ -1,5 +1,7 @@
 This is a testharness.js-based test.
 [FAIL] Attempting to focus the previous option while focused on the first option should not crash.
   assert_equals: appearance:base-select must be supported in order to run this test. expected "base-select" but got "auto"
+[FAIL] Keyboard navigating backwards over an <hr> and <optgroup> should not crash.
+  assert_equals: appearance:base-select must be supported in order to run this test. expected "base-select" but got "auto"
 Harness: the test ran to completion.
 
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index cccf852..34492c8 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit cccf8525db8a57153d3cb3e22efed2db4b71a8ab
+Subproject commit 34492c89a8e381e0e856a686cc71b1eb5bd728db
diff --git a/third_party/dawn b/third_party/dawn
index 5e81513..a78978ef 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 5e815131e2179fa7ab3ceca4e0ad8f09ad04ca37
+Subproject commit a78978efe0b237a00be1d5879598cafa5d7bd4b4
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 4c5c7fd..0874945 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 4c5c7fd1931eaa285aa1ee7484a158529e32138a
+Subproject commit 0874945064c9c9b4b8a99db48bc097d7f48b8f6b
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 5d180803..0adf6c1 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-13-3-119-g1019b1c2b
-Revision: 1019b1c2b9f5faf75f4d12d938cc2f874be25a65
+Version: VER-2-13-3-120-g3467c2177
+Revision: 3467c2177cc90af3547c0b15e419e01976ebe71f
 CPEPrefix: cpe:/a:freetype:freetype:2.13.3
 License: FTL
 License File: src/docs/FTL.TXT
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 1019b1c..3467c21 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 1019b1c2b9f5faf75f4d12d938cc2f874be25a65
+Subproject commit 3467c2177cc90af3547c0b15e419e01976ebe71f
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src
index 64a6b82..ce21467 160000
--- a/third_party/llvm-libc/src
+++ b/third_party/llvm-libc/src
@@ -1 +1 @@
-Subproject commit 64a6b82928934c23e2d75ae78b7c3714907210f5
+Subproject commit ce2146789ec6ea882edee56c3d7b40dff851eb6b
diff --git a/third_party/perfetto b/third_party/perfetto
index 6acaf60..b9acf7f 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 6acaf607621ce5a117dc1a9773f27aa0d4c77b5b
+Subproject commit b9acf7ff3553f8cf7545dc5e2bfb1b1e1a4a7081
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock
index 552c483a..fff3449 100644
--- a/third_party/rust/chromium_crates_io/Cargo.lock
+++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -882,12 +882,12 @@
 
 [[package]]
 name = "libc"
-version = "0.2.171"
+version = "0.2.172"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libm"
-version = "0.2.11"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
diff --git a/third_party/rust/chromium_crates_io/patches/README.md b/third_party/rust/chromium_crates_io/patches/README.md
new file mode 100644
index 0000000..5d9aa2e7
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/patches/README.md
@@ -0,0 +1,87 @@
+# Patches for third-party Rust crates from crates.io
+
+This directory contains patches for third-party Rust crates.  The patches are
+applied when running the `tools/crates/run_gnrt.py vendor` tool which first
+downloads original crates into `//third_party/rust/chromium_crates_io/vendor`
+and then applies the patches from this directory.
+
+For broader context, please see `tools/crates/gnrt/README.md` and
+`docs/rust.md`.
+
+## Prefer upstream PRs instead of patches
+
+If possible, please avoid patches and instead submit PRs (pull requests) to the
+upstream repo of the crate.  This helps to avoid the small, but non-zero burden
+required to maintain the patches (they need to be refreshed when they eventually
+don't apply cleanly anymore).  Additionally, PRs also benefit the broader
+community of crates.io users.
+
+That said, patches may sometimes be required:
+
+* If upstream maintainers have accepted and merged a PR,
+  but didn't yet release a new version to crates.io,
+  then a short-lived, temporary patch may expedite adopting the PR in Chromium.
+* If patches are very Chromium-specific (and therefore are unlikely to be
+  accepted by upstream maintainers), then a long-lived patch may be the right
+  way forward.
+
+Note that in theory any crate file may be patched, but in practice patching
+`Cargo.toml` is quite tricky, because `tools/crates/run_gnrt.py vendor` builds
+Chromium's dependency graph based on original, unpatched crate versions, while
+`tools/crates/run_gnrt.py gen` uses the graph derived from the patched versions.
+This discrepancy can confuse other tools (e.g. `create_update_cl.py` may think
+that it adds a new crate, when in reality the new crate has no `BUILD.gn` and is
+effectively unused after patching).
+
+## Steps for creating new patches
+
+You may patch a crate in tree, but save any changes made into a diff file in
+a `//third_party/rust/chromium_crates_io/patches/` directory for the crate.
+The diff file should be generated by `git-format-patch`, with each new patch
+numbered consecutively so that they can be applied in order. For example, these
+files might exist if the "foo" crate was patched with a couple of changes:
+
+```
+//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Some-changes.diff
+//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
+```
+
+Patches are applied with `-p6 --directory
+third_party/rust/chromium_crates_io/vendor/<crate>-<epoch>`, effectively
+ignoring the version numbers in the patch files.
+
+The recommended procedure to create such patches is:
+
+1. Commit the plain new version of the crate to your local git branch
+2. Modify the crate as necessary
+3. Commit that modified version
+4. Use `git format-patch` to generate the patch files.  For example:
+
+    ```
+    git format-patch \
+        --start-number=101 \
+        --output-directory \
+            $CHROMIUM_SRC/third_party/rust/chromium_crates_io/patches/some-crate/ \
+        HEAD^
+    ```
+
+5. Add the patch files in a new, third, commit
+6. Squash them, or rely on `git cl upload` doing so
+
+## Recovering from patching errors
+
+If `gnrt vendor` fails to apply a patch for a crate, it will cancel the download of that
+crate rather than leave it in a broken state. To recreate patches, first get a pristine
+copy of the crate by using the `--no-patches` argument:
+
+1. Download the crate without applying patches:
+   * `vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>`
+2. Then recreate the patches as described in [Steps for creating new patches](
+   #steps-for-creating-new-patches).
+
+To verify the patches work, remove the vendored crate directory in
+`//third_party/rust/chromium_crates_io/vendor/`, named after the crate name
+and version. Then run the `vendor` action without `--no-patches` which will
+download the crate and apply the patches:
+   * `vpython3 ./tools/crates/run_gnrt.py vendor`
+
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 0d62191..4490be2 100644
--- a/third_party/rust/chromium_crates_io/supply-chain/config.toml
+++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -296,10 +296,10 @@
 [policy."lazy_static:1.5.0"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
-[policy."libc:0.2.171"]
+[policy."libc:0.2.172"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
-[policy."libm:0.2.11"]
+[policy."libm:0.2.13"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
 [policy."link-cplusplus:1.0.10"]
diff --git a/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/Cargo.toml
index ce84430..0ca5b7a 100644
--- a/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'bumpalo' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `bumpalo-3.17.0` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "bumpalo"
diff --git a/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/src/lib.rs
index a2a0636..0169052 100644
--- a/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/bumpalo-v3/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'bumpalo' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `bumpalo-3.17.0` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
index 16f13f7..a0d335f 100644
--- a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'cc' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `cc-1.2.19` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "cc"
diff --git a/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs
index be2fe19..4be94d1 100644
--- a/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'cc' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `cc-1.2.19` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/Cargo.toml
index 2035c26f..2a7e840 100644
--- a/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'iana-time-zone-haiku' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `iana-time-zone-haiku-0.1.2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "iana-time-zone-haiku"
diff --git a/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/src/lib.rs
index cde9032..0c959605 100644
--- a/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/iana-time-zone-haiku-v0_1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'iana-time-zone-haiku' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `iana-time-zone-haiku-0.1.2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/Cargo.toml
index d330889..f0b2c5f3 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_collator' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_collator-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_collator"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/src/lib.rs
index 636b97f..b922e50 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_collator-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_collator' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_collator-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/Cargo.toml
index e13f75f..0a8857af 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_collator_data' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_collator_data-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_collator_data"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/src/lib.rs
index f645d0e..6c8260b 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_collator_data-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_collator_data' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_collator_data-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/Cargo.toml
index e72fc824..844fbdc 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_datetime' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_datetime-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_datetime"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/src/lib.rs
index 745967f..b6a443c 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_datetime-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_datetime' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_datetime-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/Cargo.toml
index 7f34b857..b845862 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_datetime_data' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_datetime_data-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_datetime_data"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/src/lib.rs
index 191b478..267b089 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_datetime_data-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_datetime_data' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_datetime_data-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/Cargo.toml
index 80796f6..f2c00271 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_segmenter' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_segmenter-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_segmenter"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/src/lib.rs
index 7b1745332..130ec0aec 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_segmenter-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_segmenter' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_segmenter-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/Cargo.toml
index ab217cb..6dd5f118 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'icu_segmenter_data' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `icu_segmenter_data-2.0.0-beta2` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "icu_segmenter_data"
diff --git a/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/src/lib.rs
index 2c8d5c1..b0ef8b2 100644
--- a/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/icu_segmenter_data-v2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'icu_segmenter_data' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `icu_segmenter_data-2.0.0-beta2` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/Cargo.toml
index 3a678e18..3388457 100644
--- a/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'js-sys' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `js-sys-0.3.77` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "js-sys"
diff --git a/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/src/lib.rs
index b754e752..992e43b 100644
--- a/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/js-sys-v0_3/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'js-sys' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `js-sys-0.3.77` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/.cargo_vcs_info.json
index 4a18c27..af5afed 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/.cargo_vcs_info.json
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "78b0f8a7397e177ff487f1a70a22a67ae5638f72"
+    "sha1": "a5eab581f9c9c03f29e3edd4a4d4f850d748f2e9"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/CHANGELOG.md b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/CHANGELOG.md
index 502c8e1..82a37cf 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/CHANGELOG.md
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/CHANGELOG.md
@@ -1,6 +1,70 @@
 # Changelog
 
-## [Unreleased]
+## [0.2.172](https://github.com/rust-lang/libc/compare/0.2.171...0.2.172) - 2025-04-14
+
+### Added
+
+- Android: Add `getauxval` for 32-bit targets ([#4338](https://github.com/rust-lang/libc/pull/4338))
+- Android: Add `if_tun.h` ioctls ([#4379](https://github.com/rust-lang/libc/pull/4379))
+- Android: Define `SO_BINDTOIFINDEX` ([#4391](https://github.com/rust-lang/libc/pull/4391))
+- Cygwin: Add `posix_spawn_file_actions_add[f]chdir[_np]` ([#4387](https://github.com/rust-lang/libc/pull/4387))
+- Cygwin: Add new socket options ([#4350](https://github.com/rust-lang/libc/pull/4350))
+- Cygwin: Add statfs & fcntl ([#4321](https://github.com/rust-lang/libc/pull/4321))
+- FreeBSD: Add `filedesc` and `fdescenttbl` ([#4327](https://github.com/rust-lang/libc/pull/4327))
+- Glibc: Add unstable support for _FILE_OFFSET_BITS=64 ([#4345](https://github.com/rust-lang/libc/pull/4345))
+- Hermit: Add `AF_UNSPEC` ([#4344](https://github.com/rust-lang/libc/pull/4344))
+- Hermit: Add `AF_VSOCK` ([#4344](https://github.com/rust-lang/libc/pull/4344))
+- Illumos, NetBSD: Add `timerfd` APIs ([#4333](https://github.com/rust-lang/libc/pull/4333))
+- Linux: Add `_IO`, `_IOW`, `_IOR`, `_IOWR` to the exported API ([#4325](https://github.com/rust-lang/libc/pull/4325))
+- Linux: Add `tcp_info` to uClibc bindings ([#4347](https://github.com/rust-lang/libc/pull/4347))
+- Linux: Add further BPF program flags ([#4356](https://github.com/rust-lang/libc/pull/4356))
+- Linux: Add missing INPUT_PROP_XXX flags from `input-event-codes.h` ([#4326](https://github.com/rust-lang/libc/pull/4326))
+- Linux: Add missing TLS bindings ([#4296](https://github.com/rust-lang/libc/pull/4296))
+- Linux: Add more constants from `seccomp.h` ([#4330](https://github.com/rust-lang/libc/pull/4330))
+- Linux: Add more glibc `ptrace_sud_config` and related `PTRACE_*ET_SYSCALL_USER_DISPATCH_CONFIG`. ([#4386](https://github.com/rust-lang/libc/pull/4386))
+- Linux: Add new netlink flags ([#4288](https://github.com/rust-lang/libc/pull/4288))
+- Linux: Define ioctl codes on more architectures ([#4382](https://github.com/rust-lang/libc/pull/4382))
+- Linux: Add missing `pthread_attr_setstack` ([#4349](https://github.com/rust-lang/libc/pull/4349))
+- Musl: Add missing `utmpx` API ([#4332](https://github.com/rust-lang/libc/pull/4332))
+- Musl: Enable `getrandom` on all platforms ([#4346](https://github.com/rust-lang/libc/pull/4346))
+- NuttX: Add more signal constants ([#4353](https://github.com/rust-lang/libc/pull/4353))
+- QNX: Add QNX 7.1-iosock and 8.0 to list of additional cfgs ([#4169](https://github.com/rust-lang/libc/pull/4169))
+- QNX: Add support for alternative Neutrino network stack `io-sock` ([#4169](https://github.com/rust-lang/libc/pull/4169))
+- Redox: Add more `sys/socket.h` and `sys/uio.h` definitions ([#4388](https://github.com/rust-lang/libc/pull/4388))
+- Solaris: Temporarily define `O_DIRECT` and `SIGINFO` ([#4348](https://github.com/rust-lang/libc/pull/4348))
+- Solarish: Add `secure_getenv` ([#4342](https://github.com/rust-lang/libc/pull/4342))
+- VxWorks: Add missing `d_type` member to `dirent` ([#4352](https://github.com/rust-lang/libc/pull/4352))
+- VxWorks: Add missing signal-related constsants ([#4352](https://github.com/rust-lang/libc/pull/4352))
+- VxWorks: Add more error codes ([#4337](https://github.com/rust-lang/libc/pull/4337))
+
+### Deprecated
+
+- FreeBSD: Deprecate `TCP_PCAP_OUT` and `TCP_PCAP_IN` ([#4381](https://github.com/rust-lang/libc/pull/4381))
+
+### Fixed
+
+- Cygwin: Fix member types of `statfs` ([#4324](https://github.com/rust-lang/libc/pull/4324))
+- Cygwin: Fix tests  ([#4357](https://github.com/rust-lang/libc/pull/4357))
+- Hermit: Make `AF_INET = 3` ([#4344](https://github.com/rust-lang/libc/pull/4344))
+- Musl: Fix the syscall table on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335))
+- Musl: Fix the value of `SA_ONSTACK` on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335))
+- VxWorks: Fix a typo in the `waitpid` parameter name ([#4334](https://github.com/rust-lang/libc/pull/4334))
+
+### Removed
+
+- Musl: Remove `O_FSYNC` on RISC-V-32 (use `O_SYNC` instead) ([#4335](https://github.com/rust-lang/libc/pull/4335))
+- Musl: Remove `RTLD_DEEPBIND` on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335))
+
+### Other
+
+- CI: Add matrix env variables to the environment ([#4345](https://github.com/rust-lang/libc/pull/4345))
+- CI: Always deny warnings ([#4363](https://github.com/rust-lang/libc/pull/4363))
+- CI: Always upload successfully created artifacts ([#4345](https://github.com/rust-lang/libc/pull/4345))
+- CI: Install musl from source for loongarch64 ([#4320](https://github.com/rust-lang/libc/pull/4320))
+- CI: Revert "Also skip `MFD_EXEC` and `MFD_NOEXEC_SEAL` on sparc64" ([#]())
+- CI: Use `$PWD` instead of `$(pwd)` in run-docker ([#4345](https://github.com/rust-lang/libc/pull/4345))
+- Solarish: Restrict `openpty` and `forkpty` polyfills to Illumos, replace Solaris implementation with bindings ([#4329](https://github.com/rust-lang/libc/pull/4329))
+- Testing: Ensure the makedev test does not emit unused errors ([#4363](https://github.com/rust-lang/libc/pull/4363))
 
 ## [0.2.171](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171) - 2025-03-11
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.lock
index 70ad047..833de34 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.lock
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.lock
@@ -4,7 +4,7 @@
 
 [[package]]
 name = "libc"
-version = "0.2.171"
+version = "0.2.172"
 dependencies = [
  "rustc-std-workspace-core",
 ]
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml
index e816e90..946d700e 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2021"
 rust-version = "1.63"
 name = "libc"
-version = "0.2.171"
+version = "0.2.172"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
 exclude = [
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml.orig
index c90e201..cabbc52 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml.orig
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "libc"
-version = "0.2.171"
+version = "0.2.172"
 authors = ["The Rust Project Developers"]
 license = "MIT OR Apache-2.0"
 readme = "README.md"
@@ -151,4 +151,7 @@
 use_std = ['std']
 
 [workspace]
-members = ["libc-test"]
+members = [
+    "ctest",
+    "libc-test",
+]
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/build.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/build.rs
index a09826fe8..bf5277a9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/build.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/build.rs
@@ -13,6 +13,8 @@
     "freebsd13",
     "freebsd14",
     "freebsd15",
+    // Corresponds to `_FILE_OFFSET_BITS=64` in glibc
+    "gnu_file_offset_bits64",
     // FIXME(ctest): this config shouldn't be needed but ctest can't parse `const extern fn`
     "libc_const_extern_fn",
     "libc_deny_warnings",
@@ -30,7 +32,10 @@
             "switch", "aix", "ohos", "hurd", "rtems", "visionos", "nuttx", "cygwin",
         ],
     ),
-    ("target_env", &["illumos", "wasi", "aix", "ohos"]),
+    (
+        "target_env",
+        &["illumos", "wasi", "aix", "ohos", "nto71_iosock", "nto80"],
+    ),
     (
         "target_arch",
         &["loongarch64", "mips32r6", "mips64r6", "csky"],
@@ -44,6 +49,10 @@
     let (rustc_minor_ver, _is_nightly) = rustc_minor_nightly();
     let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
     let libc_ci = env::var("LIBC_CI").is_ok();
+    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
+    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
+    let target_ptr_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap_or_default();
+    let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
 
     // The ABI of libc used by std is backward compatible with FreeBSD 12.
     // The ABI of libc from crates.io is backward compatible with FreeBSD 11.
@@ -85,6 +94,23 @@
     if linux_time_bits64 {
         set_cfg("linux_time_bits64");
     }
+    println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS");
+    match env::var("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS") {
+        Ok(val) if val == "64" => {
+            if target_env == "gnu"
+                && target_os == "linux"
+                && target_ptr_width == "32"
+                && target_arch != "riscv32"
+                && target_arch != "x86_64"
+            {
+                set_cfg("gnu_file_offset_bits64");
+            }
+        }
+        Ok(val) if val != "32" => {
+            panic!("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS may only be set to '32' or '64'")
+        }
+        _ => {}
+    }
 
     // On CI: deny all warnings
     if libc_ci {
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/hermit.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/hermit.rs
index db51ee9..b96be6b0 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/hermit.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/hermit.rs
@@ -114,8 +114,10 @@
     }
 }
 
-pub const AF_INET: i32 = 0;
+pub const AF_UNSPEC: i32 = 0;
+pub const AF_INET: i32 = 3;
 pub const AF_INET6: i32 = 1;
+pub const AF_VSOCK: i32 = 2;
 
 pub const CLOCK_REALTIME: clockid_t = 1;
 pub const CLOCK_MONOTONIC: clockid_t = 4;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
index 87ddbcc..5846447 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
@@ -51,9 +51,8 @@
         // This is normally "struct vnode".
         /// Pointer to executable file.
         pub ki_textvp: *mut c_void,
-        // This is normally "struct filedesc".
         /// Pointer to open file info.
-        pub ki_fd: *mut c_void,
+        pub ki_fd: *mut crate::filedesc,
         // This is normally "struct vmspace".
         /// Pointer to kernel vmspace struct.
         pub ki_vmspace: *mut c_void,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
index 6c2f58619..21062e5 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
@@ -59,9 +59,8 @@
         // This is normally "struct vnode".
         /// Pointer to executable file.
         pub ki_textvp: *mut c_void,
-        // This is normally "struct filedesc".
         /// Pointer to open file info.
-        pub ki_fd: *mut c_void,
+        pub ki_fd: *mut crate::filedesc,
         // This is normally "struct vmspace".
         /// Pointer to kernel vmspace struct.
         pub ki_vmspace: *mut c_void,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
index cf507e66..505d2d1 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
@@ -69,9 +69,8 @@
         // This is normally "struct vnode".
         /// Pointer to executable file.
         pub ki_textvp: *mut c_void,
-        // This is normally "struct filedesc".
         /// Pointer to open file info.
-        pub ki_fd: *mut c_void,
+        pub ki_fd: *mut crate::filedesc,
         // This is normally "struct vmspace".
         /// Pointer to kernel vmspace struct.
         pub ki_vmspace: *mut c_void,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
index 0a05ca9..44a3656 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
@@ -69,9 +69,8 @@
         // This is normally "struct vnode".
         /// Pointer to executable file.
         pub ki_textvp: *mut c_void,
-        // This is normally "struct filedesc".
         /// Pointer to open file info.
-        pub ki_fd: *mut c_void,
+        pub ki_fd: *mut crate::filedesc,
         // This is normally "struct vmspace".
         /// Pointer to kernel vmspace struct.
         pub ki_vmspace: *mut c_void,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs
index 2fe39a3..29c9c0c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs
@@ -69,9 +69,8 @@
         // This is normally "struct vnode".
         /// Pointer to executable file.
         pub ki_textvp: *mut c_void,
-        // This is normally "struct filedesc".
         /// Pointer to open file info.
-        pub ki_fd: *mut c_void,
+        pub ki_fd: *mut crate::filedesc,
         // This is normally "struct vmspace".
         /// Pointer to kernel vmspace struct.
         pub ki_vmspace: *mut c_void,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/mod.rs
index ff096e51..11830db 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/freebsdlike/freebsd/mod.rs
@@ -1357,6 +1357,47 @@
         pub strchange_instrms: u16,
         pub strchange_outstrms: u16,
     }
+
+    pub struct filedesc {
+        pub fd_files: *mut fdescenttbl,
+        pub fd_map: *mut c_ulong,
+        pub fd_freefile: c_int,
+        pub fd_refcnt: c_int,
+        pub fd_holdcnt: c_int,
+        fd_sx: sx,
+        fd_kqlist: kqlist,
+        pub fd_holdleaderscount: c_int,
+        pub fd_holdleaderswakeup: c_int,
+    }
+
+    pub struct fdescenttbl {
+        pub fdt_nfiles: c_int,
+        fdt_ofiles: [*mut c_void; 0],
+    }
+
+    // FIXME: Should be private.
+    #[doc(hidden)]
+    pub struct sx {
+        lock_object: lock_object,
+        sx_lock: crate::uintptr_t,
+    }
+
+    // FIXME: Should be private.
+    #[doc(hidden)]
+    pub struct lock_object {
+        lo_name: *const c_char,
+        lo_flags: c_uint,
+        lo_data: c_uint,
+        // This is normally `struct  witness`.
+        lo_witness: *mut c_void,
+    }
+
+    // FIXME: Should be private.
+    #[doc(hidden)]
+    pub struct kqlist {
+        tqh_first: *mut c_void,
+        tqh_last: *mut *mut c_void,
+    }
 }
 
 s_no_extra_traits! {
@@ -3771,7 +3812,9 @@
 pub const TCP_LRD: c_int = 79;
 pub const TCP_KEEPINIT: c_int = 128;
 pub const TCP_FASTOPEN: c_int = 1025;
+#[deprecated(since = "0.2.171", note = "removed in FreeBSD 15")]
 pub const TCP_PCAP_OUT: c_int = 2048;
+#[deprecated(since = "0.2.171", note = "removed in FreeBSD 15")]
 pub const TCP_PCAP_IN: c_int = 4096;
 pub const TCP_FUNCTION_BLK: c_int = 8192;
 pub const TCP_FUNCTION_ALIAS: c_int = 8193;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/netbsdlike/netbsd/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/netbsdlike/netbsd/mod.rs
index 8ede2b6..9f44907 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -2409,6 +2409,12 @@
 pub const RTAX_TAG: c_int = 8;
 pub const RTAX_MAX: c_int = 9;
 
+// sys/timerfd.h
+pub const TFD_CLOEXEC: i32 = crate::O_CLOEXEC;
+pub const TFD_NONBLOCK: i32 = crate::O_NONBLOCK;
+pub const TFD_TIMER_ABSTIME: i32 = crate::O_WRONLY;
+pub const TFD_TIMER_CANCEL_ON_SET: i32 = crate::O_RDWR;
+
 const_fn! {
     {const} fn _ALIGN(p: usize) -> usize {
         (p + _ALIGNBYTES) & !_ALIGNBYTES
@@ -2853,6 +2859,16 @@
     #[link_name = "__getmntinfo13"]
     pub fn getmntinfo(mntbufp: *mut *mut crate::statvfs, flags: c_int) -> c_int;
     pub fn getvfsstat(buf: *mut statvfs, bufsize: size_t, flags: c_int) -> c_int;
+
+    // Added in `NetBSD` 10.0
+    pub fn timerfd_create(clockid: crate::clockid_t, flags: c_int) -> c_int;
+    pub fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int;
+    pub fn timerfd_settime(
+        fd: c_int,
+        flags: c_int,
+        new_value: *const itimerspec,
+        old_value: *mut itimerspec,
+    ) -> c_int;
 }
 
 #[link(name = "rt")]
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/cygwin/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/cygwin/mod.rs
index 4bfdde3..c2fda67 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/cygwin/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/cygwin/mod.rs
@@ -435,6 +435,19 @@
         pub f_flag: c_ulong,
         pub f_namemax: c_ulong,
     }
+
+    pub struct statfs {
+        pub f_type: c_long,
+        pub f_bsize: c_long,
+        pub f_blocks: c_long,
+        pub f_bfree: c_long,
+        pub f_bavail: c_long,
+        pub f_files: c_long,
+        pub f_ffree: c_long,
+        pub f_fsid: c_long,
+        pub f_namelen: c_long,
+        pub f_spare: [c_long; 6],
+    }
 }
 
 s_no_extra_traits! {
@@ -498,7 +511,7 @@
     }
 
     pub struct utsname {
-        pub sysname: [c_char; 65],
+        pub sysname: [c_char; 66],
         pub nodename: [c_char; 65],
         pub release: [c_char; 65],
         pub version: [c_char; 65],
@@ -961,6 +974,8 @@
 pub const IPTOS_LOWDELAY: u8 = 0x10;
 pub const IPTOS_THROUGHPUT: u8 = 0x08;
 pub const IPTOS_RELIABILITY: u8 = 0x04;
+pub const IPTOS_LOWCOST: u8 = 0x02;
+pub const IPTOS_MINCOST: u8 = IPTOS_LOWCOST;
 pub const IP_DEFAULT_MULTICAST_TTL: c_int = 1;
 pub const IP_DEFAULT_MULTICAST_LOOP: c_int = 1;
 pub const IP_OPTIONS: c_int = 1;
@@ -977,8 +992,18 @@
 pub const IP_BLOCK_SOURCE: c_int = 17;
 pub const IP_UNBLOCK_SOURCE: c_int = 18;
 pub const IP_PKTINFO: c_int = 19;
+pub const IP_RECVTTL: c_int = 21;
 pub const IP_UNICAST_IF: c_int = 31;
+pub const IP_RECVTOS: c_int = 40;
+pub const IP_MTU_DISCOVER: c_int = 71;
+pub const IP_MTU: c_int = 73;
+pub const IP_RECVERR: c_int = 75;
+pub const IP_PMTUDISC_WANT: c_int = 0;
+pub const IP_PMTUDISC_DO: c_int = 1;
+pub const IP_PMTUDISC_DONT: c_int = 2;
+pub const IP_PMTUDISC_PROBE: c_int = 3;
 pub const IPV6_HOPOPTS: c_int = 1;
+pub const IPV6_HDRINCL: c_int = 2;
 pub const IPV6_UNICAST_HOPS: c_int = 4;
 pub const IPV6_MULTICAST_IF: c_int = 9;
 pub const IPV6_MULTICAST_HOPS: c_int = 10;
@@ -997,6 +1022,13 @@
 pub const IPV6_RECVRTHDR: c_int = 38;
 pub const IPV6_TCLASS: c_int = 39;
 pub const IPV6_RECVTCLASS: c_int = 40;
+pub const IPV6_MTU_DISCOVER: c_int = 71;
+pub const IPV6_MTU: c_int = 72;
+pub const IPV6_RECVERR: c_int = 75;
+pub const IPV6_PMTUDISC_WANT: c_int = 0;
+pub const IPV6_PMTUDISC_DO: c_int = 1;
+pub const IPV6_PMTUDISC_DONT: c_int = 2;
+pub const IPV6_PMTUDISC_PROBE: c_int = 3;
 pub const MCAST_JOIN_GROUP: c_int = 41;
 pub const MCAST_LEAVE_GROUP: c_int = 42;
 pub const MCAST_BLOCK_SOURCE: c_int = 43;
@@ -1786,6 +1818,20 @@
 pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x10;
 pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x20;
 
+pub const POSIX_FADV_NORMAL: c_int = 0;
+pub const POSIX_FADV_SEQUENTIAL: c_int = 1;
+pub const POSIX_FADV_RANDOM: c_int = 2;
+pub const POSIX_FADV_WILLNEED: c_int = 3;
+pub const POSIX_FADV_DONTNEED: c_int = 4;
+pub const POSIX_FADV_NOREUSE: c_int = 5;
+
+pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x0001;
+pub const FALLOC_FL_ZERO_RANGE: c_int = 0x0002;
+pub const FALLOC_FL_UNSHARE_RANGE: c_int = 0x0004;
+pub const FALLOC_FL_COLLAPSE_RANGE: c_int = 0x0008;
+pub const FALLOC_FL_INSERT_RANGE: c_int = 0x0010;
+pub const FALLOC_FL_KEEP_SIZE: c_int = 0x1000;
+
 f! {
     pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () {
         let fd = fd as usize;
@@ -1865,14 +1911,6 @@
         set1.bits == set2.bits
     }
 
-    pub fn major(dev: dev_t) -> c_uint {
-        ((dev >> 16) & 0xffff) as c_uint
-    }
-
-    pub fn minor(dev: dev_t) -> c_uint {
-        (dev & 0xffff) as c_uint
-    }
-
     pub fn CMSG_LEN(length: c_uint) -> c_uint {
         CMSG_ALIGN(::core::mem::size_of::<cmsghdr>()) as c_uint + length
     }
@@ -1911,6 +1949,14 @@
         (ma << 16) | (mi & 0xffff)
     }
 
+    pub {const} fn major(dev: dev_t) -> c_uint {
+        ((dev >> 16) & 0xffff) as c_uint
+    }
+
+    pub {const} fn minor(dev: dev_t) -> c_uint {
+        (dev & 0xffff) as c_uint
+    }
+
     pub {const} fn WIFEXITED(status: c_int) -> bool {
         (status & 0xff) == 0
     }
@@ -2157,8 +2203,6 @@
     pub fn timingsafe_bcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int;
     pub fn timingsafe_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int;
 
-    pub fn memccpy(dest: *mut c_void, src: *const c_void, c: c_int, count: size_t) -> *mut c_void;
-
     pub fn memmem(
         haystack: *const c_void,
         haystacklen: size_t,
@@ -2178,17 +2222,16 @@
     pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int;
     pub fn eaccess(pathname: *const c_char, mode: c_int) -> c_int;
     pub fn euidaccess(pathname: *const c_char, mode: c_int) -> c_int;
-    // pub fn execlpe(path: *const c_char, arg0: *const c_char, ...) -> c_int;
 
     pub fn execvpe(
         file: *const c_char,
-        argv: *const *const c_char,
-        envp: *const *const c_char,
+        argv: *const *mut c_char,
+        envp: *const *mut c_char,
     ) -> c_int;
 
     pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int;
 
-    pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int;
+    pub fn fexecve(fd: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
 
     pub fn fdatasync(fd: c_int) -> c_int;
     pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int;
@@ -2349,7 +2392,7 @@
     ) -> c_int;
 
     pub fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> c_int;
-    pub fn pthread_sigqueue(thread: *mut pthread_t, sig: c_int, value: sigval) -> c_int;
+    pub fn pthread_sigqueue(thread: pthread_t, sig: c_int, value: sigval) -> c_int;
 
     pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int;
 
@@ -2436,6 +2479,22 @@
         fd: c_int,
         newfd: c_int,
     ) -> c_int;
+    pub fn posix_spawn_file_actions_addchdir(
+        actions: *mut crate::posix_spawn_file_actions_t,
+        path: *const c_char,
+    ) -> c_int;
+    pub fn posix_spawn_file_actions_addfchdir(
+        actions: *mut crate::posix_spawn_file_actions_t,
+        fd: c_int,
+    ) -> c_int;
+    pub fn posix_spawn_file_actions_addchdir_np(
+        actions: *mut crate::posix_spawn_file_actions_t,
+        path: *const c_char,
+    ) -> c_int;
+    pub fn posix_spawn_file_actions_addfchdir_np(
+        actions: *mut crate::posix_spawn_file_actions_t,
+        fd: c_int,
+    ) -> c_int;
 
     pub fn forkpty(
         amaster: *mut c_int,
@@ -2472,4 +2531,11 @@
         result: *mut *mut crate::group,
     ) -> c_int;
     pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int;
+
+    pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int;
+    pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int;
+
+    pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int;
+    pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int;
+    pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int;
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/b64/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/b64/mod.rs
index cc407e1..b507dac 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/b64/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/b64/mod.rs
@@ -305,7 +305,6 @@
 }
 
 extern "C" {
-    pub fn getauxval(type_: c_ulong) -> c_ulong;
     pub fn __system_property_wait(
         pi: *const crate::prop_info,
         __old_serial: u32,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/mod.rs
index 330438fe..c5875f29 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/android/mod.rs
@@ -1555,6 +1555,7 @@
 pub const SO_BUSY_POLL: c_int = 46;
 pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 54;
 pub const SCM_TIMESTAMPING_PKTINFO: c_int = 58;
+pub const SO_BINDTOIFINDEX: c_int = 62;
 pub const SO_TIMESTAMP_NEW: c_int = 63;
 pub const SO_TIMESTAMPNS_NEW: c_int = 64;
 pub const SO_TIMESTAMPING_NEW: c_int = 65;
@@ -1985,6 +1986,12 @@
 pub const NLM_F_CREATE: c_int = 0x400;
 pub const NLM_F_APPEND: c_int = 0x800;
 
+pub const NLM_F_NONREC: c_int = 0x100;
+pub const NLM_F_BULK: c_int = 0x200;
+
+pub const NLM_F_CAPPED: c_int = 0x100;
+pub const NLM_F_ACK_TLVS: c_int = 0x200;
+
 pub const NLMSG_NOOP: c_int = 0x1;
 pub const NLMSG_ERROR: c_int = 0x2;
 pub const NLMSG_DONE: c_int = 0x3;
@@ -2194,18 +2201,22 @@
 pub const GRND_RANDOM: c_uint = 0x0002;
 pub const GRND_INSECURE: c_uint = 0x0004;
 
+// <linux/seccomp.h>
 pub const SECCOMP_MODE_DISABLED: c_uint = 0;
 pub const SECCOMP_MODE_STRICT: c_uint = 1;
 pub const SECCOMP_MODE_FILTER: c_uint = 2;
 
-pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1;
-pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 2;
-pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 4;
-pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 8;
+pub const SECCOMP_SET_MODE_STRICT: c_uint = 0;
+pub const SECCOMP_SET_MODE_FILTER: c_uint = 1;
+pub const SECCOMP_GET_ACTION_AVAIL: c_uint = 2;
+pub const SECCOMP_GET_NOTIF_SIZES: c_uint = 3;
 
-pub const SECCOMP_RET_ACTION_FULL: c_uint = 0xffff0000;
-pub const SECCOMP_RET_ACTION: c_uint = 0x7fff0000;
-pub const SECCOMP_RET_DATA: c_uint = 0x0000ffff;
+pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1 << 0;
+pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 1 << 1;
+pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 1 << 2;
+pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 1 << 3;
+pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: c_ulong = 1 << 4;
+pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: c_ulong = 1 << 5;
 
 pub const SECCOMP_RET_KILL_PROCESS: c_uint = 0x80000000;
 pub const SECCOMP_RET_KILL_THREAD: c_uint = 0x00000000;
@@ -2217,6 +2228,15 @@
 pub const SECCOMP_RET_LOG: c_uint = 0x7ffc0000;
 pub const SECCOMP_RET_ALLOW: c_uint = 0x7fff0000;
 
+pub const SECCOMP_RET_ACTION_FULL: c_uint = 0xffff0000;
+pub const SECCOMP_RET_ACTION: c_uint = 0x7fff0000;
+pub const SECCOMP_RET_DATA: c_uint = 0x0000ffff;
+
+pub const SECCOMP_USER_NOTIF_FLAG_CONTINUE: c_ulong = 1;
+
+pub const SECCOMP_ADDFD_FLAG_SETFD: c_ulong = 1;
+pub const SECCOMP_ADDFD_FLAG_SEND: c_ulong = 2;
+
 pub const NLA_F_NESTED: c_int = 1 << 15;
 pub const NLA_F_NET_BYTEORDER: c_int = 1 << 14;
 pub const NLA_TYPE_MASK: c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER);
@@ -2661,6 +2681,7 @@
 pub const IFF_DETACH_QUEUE: c_int = 0x0400;
 pub const IFF_PERSIST: c_int = 0x0800;
 pub const IFF_NOFILTER: c_int = 0x1000;
+pub const TUN_TX_TIMESTAMP: c_int = 1;
 // Features for GSO (TUNSETOFFLOAD)
 pub const TUN_F_CSUM: c_uint = 0x01;
 pub const TUN_F_TSO4: c_uint = 0x02;
@@ -2669,6 +2690,40 @@
 pub const TUN_F_UFO: c_uint = 0x10;
 pub const TUN_F_USO4: c_uint = 0x20;
 pub const TUN_F_USO6: c_uint = 0x40;
+// Protocol info prepended to the packets (when IFF_NO_PI is not set)
+pub const TUN_PKT_STRIP: c_int = 0x0001;
+// Accept all multicast packets
+pub const TUN_FLT_ALLMULTI: c_int = 0x0001;
+// Ioctl operation codes
+const T_TYPE: u32 = b'T' as u32;
+pub const TUNSETNOCSUM: c_int = _IOW::<c_int>(T_TYPE, 200);
+pub const TUNSETDEBUG: c_int = _IOW::<c_int>(T_TYPE, 201);
+pub const TUNSETIFF: c_int = _IOW::<c_int>(T_TYPE, 202);
+pub const TUNSETPERSIST: c_int = _IOW::<c_int>(T_TYPE, 203);
+pub const TUNSETOWNER: c_int = _IOW::<c_int>(T_TYPE, 204);
+pub const TUNSETLINK: c_int = _IOW::<c_int>(T_TYPE, 205);
+pub const TUNSETGROUP: c_int = _IOW::<c_int>(T_TYPE, 206);
+pub const TUNGETFEATURES: c_int = _IOR::<c_int>(T_TYPE, 207);
+pub const TUNSETOFFLOAD: c_int = _IOW::<c_int>(T_TYPE, 208);
+pub const TUNSETTXFILTER: c_int = _IOW::<c_int>(T_TYPE, 209);
+pub const TUNGETIFF: c_int = _IOR::<c_int>(T_TYPE, 210);
+pub const TUNGETSNDBUF: c_int = _IOR::<c_int>(T_TYPE, 211);
+pub const TUNSETSNDBUF: c_int = _IOW::<c_int>(T_TYPE, 212);
+pub const TUNATTACHFILTER: c_int =  _IOW::<sock_fprog>(T_TYPE, 213);
+pub const TUNDETACHFILTER: c_int = _IOW::<sock_fprog>(T_TYPE, 214);
+pub const TUNGETVNETHDRSZ: c_int = _IOR::<c_int>(T_TYPE, 215);
+pub const TUNSETVNETHDRSZ: c_int = _IOW::<c_int>(T_TYPE, 216);
+pub const TUNSETQUEUE: c_int = _IOW::<c_int>(T_TYPE, 217);
+pub const TUNSETIFINDEX: c_int = _IOW::<c_int>(T_TYPE, 218);
+pub const TUNGETFILTER: c_int = _IOR::<sock_fprog>(T_TYPE, 219);
+pub const TUNSETVNETLE: c_int = _IOW::<c_int>(T_TYPE, 220);
+pub const TUNGETVNETLE: c_int = _IOR::<c_int>(T_TYPE, 221);
+pub const TUNSETVNETBE: c_int = _IOW::<c_int>(T_TYPE, 222);
+pub const TUNGETVNETBE: c_int = _IOR::<c_int>(T_TYPE, 223);
+pub const TUNSETSTEERINGEBPF: c_int = _IOR::<c_int>(T_TYPE, 224);
+pub const TUNSETFILTEREBPF: c_int = _IOR::<c_int>(T_TYPE, 225);
+pub const TUNSETCARRIER: c_int = _IOW::<c_int>(T_TYPE, 226);
+pub const TUNGETDEVNETNS: c_int = _IO(T_TYPE, 227);
 
 // start android/platform/bionic/libc/kernel/uapi/linux/if_ether.h
 // from https://android.googlesource.com/platform/bionic/+/HEAD/libc/kernel/uapi/linux/if_ether.h
@@ -4066,6 +4121,8 @@
 
     pub fn gettid() -> crate::pid_t;
 
+    pub fn getauxval(type_: c_ulong) -> c_ulong;
+
     /// Only available in API Version 28+
     pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
     pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int;
@@ -4242,3 +4299,23 @@
         self.sifields().sigchld.si_stime
     }
 }
+
+/// Build an ioctl number for an argumentless ioctl.
+pub const fn _IO(ty: u32, nr: u32) -> c_int {
+    super::_IOC(super::_IOC_NONE, ty, nr, 0) as c_int
+}
+
+/// Build an ioctl number for an read-only ioctl.
+pub const fn _IOR<T>(ty: u32, nr: u32) -> c_int {
+    super::_IOC(super::_IOC_READ, ty, nr, mem::size_of::<T>())  as c_int
+}
+
+/// Build an ioctl number for an write-only ioctl.
+pub const fn _IOW<T>(ty: u32, nr: u32) -> c_int {
+    super::_IOC(super::_IOC_WRITE, ty, nr, mem::size_of::<T>())  as c_int
+}
+
+/// Build an ioctl number for a read-write ioctl.
+pub const fn _IOWR<T>(ty: u32, nr: u32) -> c_int {
+    super::_IOC(super::_IOC_READ | super::_IOC_WRITE, ty, nr, mem::size_of::<T>())  as c_int
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/generic/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/generic/mod.rs
index 61d2e3f..ec3179b 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/generic/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/generic/mod.rs
@@ -1,5 +1,5 @@
 use crate::prelude::*;
-use crate::Ioctl;
+use crate::{Ioctl, _IOR, _IOW};
 
 s! {
     pub struct termios2 {
@@ -158,21 +158,8 @@
 pub const SO_DEVMEM_DMABUF: c_int = 79;
 pub const SO_DEVMEM_DONTNEED: c_int = 80;
 
-cfg_if! {
-    if #[cfg(any(
-        target_arch = "x86",
-        target_arch = "x86_64",
-        target_arch = "arm",
-        target_arch = "aarch64",
-        target_arch = "riscv64",
-        target_arch = "s390x",
-        target_arch = "csky",
-        target_arch = "loongarch64"
-    ))] {
-        pub const FICLONE: c_ulong = 0x40049409;
-        pub const FICLONERANGE: c_ulong = 0x4020940D;
-    }
-}
+pub const FICLONE: Ioctl = _IOW::<c_int>(0x94, 9) as Ioctl;
+pub const FICLONERANGE: Ioctl = _IOW::<crate::file_clone_range>(0x94, 13) as Ioctl;
 
 // Defined in unix/linux_like/mod.rs
 // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP;
@@ -293,50 +280,18 @@
 pub const TUNSETSTEERINGEBPF: Ioctl = 0x800454e0;
 pub const TUNSETFILTEREBPF: Ioctl = 0x800454e1;
 
-cfg_if! {
-    // Those type are constructed using the _IOC macro
-    // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN
-    // where D stands for direction (either None (00), Read (01) or Write (11))
-    // where S stands for size (int, long, struct...)
-    // where T stands for type ('f','v','X'...)
-    // where N stands for NR (NumbeR)
-    if #[cfg(any(
-        target_arch = "x86",
-        target_arch = "arm",
-        target_arch = "csky"
-    ))] {
-        pub const FS_IOC_GETFLAGS: Ioctl = 0x80046601;
-        pub const FS_IOC_SETFLAGS: Ioctl = 0x40046602;
-        pub const FS_IOC_GETVERSION: Ioctl = 0x80047601;
-        pub const FS_IOC_SETVERSION: Ioctl = 0x40047602;
-        pub const FS_IOC32_GETFLAGS: Ioctl = 0x80046601;
-        pub const FS_IOC32_SETFLAGS: Ioctl = 0x40046602;
-        pub const FS_IOC32_GETVERSION: Ioctl = 0x80047601;
-        pub const FS_IOC32_SETVERSION: Ioctl = 0x40047602;
-        pub const TUNATTACHFILTER: Ioctl = 0x400854d5;
-        pub const TUNDETACHFILTER: Ioctl = 0x400854d6;
-        pub const TUNGETFILTER: Ioctl = 0x800854db;
-    } else if #[cfg(any(
-        target_arch = "x86_64",
-        target_arch = "riscv64",
-        target_arch = "aarch64",
-        target_arch = "s390x",
-        target_arch = "loongarch64",
-        target_arch = "wasm32"
-    ))] {
-        pub const FS_IOC_GETFLAGS: Ioctl = 0x80086601;
-        pub const FS_IOC_SETFLAGS: Ioctl = 0x40086602;
-        pub const FS_IOC_GETVERSION: Ioctl = 0x80087601;
-        pub const FS_IOC_SETVERSION: Ioctl = 0x40087602;
-        pub const FS_IOC32_GETFLAGS: Ioctl = 0x80046601;
-        pub const FS_IOC32_SETFLAGS: Ioctl = 0x40046602;
-        pub const FS_IOC32_GETVERSION: Ioctl = 0x80047601;
-        pub const FS_IOC32_SETVERSION: Ioctl = 0x40047602;
-        pub const TUNATTACHFILTER: Ioctl = 0x401054d5;
-        pub const TUNDETACHFILTER: Ioctl = 0x401054d6;
-        pub const TUNGETFILTER: Ioctl = 0x801054db;
-    }
-}
+pub const FS_IOC_GETFLAGS: Ioctl = _IOR::<c_long>('f' as u32, 1) as Ioctl;
+pub const FS_IOC_SETFLAGS: Ioctl = _IOW::<c_long>('f' as u32, 2) as Ioctl;
+pub const FS_IOC_GETVERSION: Ioctl = _IOR::<c_long>('v' as u32, 1) as Ioctl;
+pub const FS_IOC_SETVERSION: Ioctl = _IOW::<c_long>('v' as u32, 2) as Ioctl;
+pub const FS_IOC32_GETFLAGS: Ioctl = _IOR::<c_int>('f' as u32, 1) as Ioctl;
+pub const FS_IOC32_SETFLAGS: Ioctl = _IOW::<c_int>('f' as u32, 2) as Ioctl;
+pub const FS_IOC32_GETVERSION: Ioctl = _IOR::<c_int>('v' as u32, 1) as Ioctl;
+pub const FS_IOC32_SETVERSION: Ioctl = _IOW::<c_int>('v' as u32, 2) as Ioctl;
+
+pub const TUNATTACHFILTER: Ioctl = _IOW::<crate::sock_fprog>('T' as u32, 213) as Ioctl;
+pub const TUNDETACHFILTER: Ioctl = _IOW::<crate::sock_fprog>('T' as u32, 214) as Ioctl;
+pub const TUNGETFILTER: Ioctl = _IOR::<crate::sock_fprog>('T' as u32, 219) as Ioctl;
 
 cfg_if! {
     if #[cfg(any(target_arch = "arm", target_arch = "s390x"))] {
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/mips/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/mips/mod.rs
index 1e12a109..eee7cc8 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/mips/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/arch/mips/mod.rs
@@ -379,8 +379,13 @@
 cfg_if! {
     if #[cfg(all(
         any(target_arch = "mips", target_arch = "mips32r6"),
-        any(target_env = "uclibc", target_env = "gnu"),
-        linux_time_bits64
+        any(
+            all(target_env = "uclibc", linux_time_bits64),
+            all(
+                target_env = "gnu",
+                any(linux_time_bits64, gnu_file_offset_bits64)
+            )
+        )
     ))] {
         pub const RLIM_INFINITY: crate::rlim_t = !0;
     } else if #[cfg(all(
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/arm/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
index 28514c0..2dd4a88 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
@@ -61,7 +61,7 @@
     pub struct stat64 {
         pub st_dev: crate::dev_t,
         __pad1: c_uint,
-        __st_ino: crate::ino_t,
+        __st_ino: c_ulong,
         pub st_mode: crate::mode_t,
         pub st_nlink: crate::nlink_t,
         pub st_uid: crate::uid_t,
@@ -397,7 +397,13 @@
 pub const POLLWRNORM: c_short = 0x100;
 pub const POLLWRBAND: c_short = 0x200;
 
-pub const F_GETLK: c_int = 5;
+cfg_if! {
+    if #[cfg(gnu_file_offset_bits64)] {
+        pub const F_GETLK: c_int = 12;
+    } else {
+        pub const F_GETLK: c_int = 5;
+    }
+}
 pub const F_GETOWN: c_int = 9;
 pub const F_SETOWN: c_int = 8;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mips/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
index cc9ebf2e..649a8e0 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
@@ -8,22 +8,36 @@
         pub st_dev: c_ulong,
 
         st_pad1: [c_long; 3],
+
         pub st_ino: crate::ino_t,
+
         pub st_mode: crate::mode_t,
         pub st_nlink: crate::nlink_t,
         pub st_uid: crate::uid_t,
         pub st_gid: crate::gid_t,
+
         pub st_rdev: c_ulong,
+
+        #[cfg(not(gnu_file_offset_bits64))]
         st_pad2: [c_long; 2],
+        #[cfg(gnu_file_offset_bits64)]
+        st_pad2: [c_long; 3],
+
         pub st_size: off_t,
+
+        #[cfg(not(gnu_file_offset_bits64))]
         st_pad3: c_long,
+
         pub st_atime: crate::time_t,
         pub st_atime_nsec: c_long,
         pub st_mtime: crate::time_t,
         pub st_mtime_nsec: c_long,
         pub st_ctime: crate::time_t,
         pub st_ctime_nsec: c_long,
+
         pub st_blksize: crate::blksize_t,
+        #[cfg(gnu_file_offset_bits64)]
+        st_pad4: c_long,
         pub st_blocks: crate::blkcnt_t,
         st_pad5: [c_long; 14],
     }
@@ -37,7 +51,7 @@
         pub st_uid: crate::uid_t,
         pub st_gid: crate::gid_t,
         pub st_rdev: c_ulong,
-        st_pad2: [c_long; 2],
+        st_pad2: [c_long; 3],
         pub st_size: off64_t,
         pub st_atime: crate::time_t,
         pub st_atime_nsec: c_long,
@@ -176,9 +190,11 @@
         pub l_whence: c_short,
         pub l_start: off_t,
         pub l_len: off_t,
+        #[cfg(not(gnu_file_offset_bits64))]
         pub l_sysid: c_long,
         pub l_pid: crate::pid_t,
-        pad: [c_long; 4],
+        #[cfg(not(gnu_file_offset_bits64))]
+        __glibc_reserved0: [c_long; 4],
     }
 }
 
@@ -745,7 +761,13 @@
 
 pub const EFD_NONBLOCK: c_int = 0x80;
 
-pub const F_GETLK: c_int = 14;
+cfg_if! {
+    if #[cfg(gnu_file_offset_bits64)] {
+        pub const F_GETLK: c_int = 33;
+    } else {
+        pub const F_GETLK: c_int = 14;
+    }
+}
 pub const F_GETOWN: c_int = 23;
 pub const F_SETOWN: c_int = 24;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mod.rs
index 134bfb0..e9a9584 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/mod.rs
@@ -20,17 +20,33 @@
     if #[cfg(target_arch = "riscv32")] {
         pub type time_t = i64;
         pub type suseconds_t = i64;
-        pub type ino_t = u64;
+        type __ino_t = c_ulong;
+        type __ino64_t = u64;
+        pub type ino_t = __ino64_t;
         pub type off_t = i64;
         pub type blkcnt_t = i64;
         pub type fsblkcnt_t = u64;
         pub type fsfilcnt_t = u64;
         pub type rlim_t = u64;
         pub type blksize_t = i64;
+    } else if #[cfg(gnu_file_offset_bits64)] {
+        pub type time_t = i32;
+        pub type suseconds_t = i32;
+        type __ino_t = c_ulong;
+        type __ino64_t = u64;
+        pub type ino_t = __ino64_t;
+        pub type off_t = i64;
+        pub type blkcnt_t = i64;
+        pub type fsblkcnt_t = u64;
+        pub type fsfilcnt_t = u64;
+        pub type rlim_t = u64;
+        pub type blksize_t = i32;
     } else {
         pub type time_t = i32;
         pub type suseconds_t = i32;
-        pub type ino_t = u32;
+        type __ino_t = c_ulong;
+        type __ino64_t = u64;
+        pub type ino_t = __ino_t;
         pub type off_t = i32;
         pub type blkcnt_t = i32;
         pub type fsblkcnt_t = c_ulong;
@@ -41,30 +57,50 @@
 }
 
 cfg_if! {
-    if #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] {
+    if #[cfg(not(any(
+        target_arch = "mips",
+        target_arch = "mips32r6",
+        target_arch = "powerpc",
+        target_arch = "sparc"
+    )))] {
         s! {
             pub struct stat {
                 pub st_dev: crate::dev_t,
 
-                __pad1: c_short,
+                __pad1: c_uint,
+
+                #[cfg(not(gnu_file_offset_bits64))]
                 pub st_ino: crate::ino_t,
+                #[cfg(all(gnu_file_offset_bits64))]
+                __st_ino: __ino_t,
+
                 pub st_mode: crate::mode_t,
                 pub st_nlink: crate::nlink_t,
                 pub st_uid: crate::uid_t,
                 pub st_gid: crate::gid_t,
+
                 pub st_rdev: crate::dev_t,
-                __pad2: c_short,
+
+                __pad2: c_uint,
+
                 pub st_size: off_t,
+
                 pub st_blksize: crate::blksize_t,
                 pub st_blocks: crate::blkcnt_t,
+
                 pub st_atime: crate::time_t,
                 pub st_atime_nsec: c_long,
                 pub st_mtime: crate::time_t,
                 pub st_mtime_nsec: c_long,
                 pub st_ctime: crate::time_t,
                 pub st_ctime_nsec: c_long,
-                __unused4: c_long,
-                __unused5: c_long,
+
+                #[cfg(not(gnu_file_offset_bits64))]
+                __glibc_reserved4: c_long,
+                #[cfg(not(gnu_file_offset_bits64))]
+                __glibc_reserved5: c_long,
+                #[cfg(gnu_file_offset_bits64)]
+                pub st_ino: crate::ino_t,
             }
         }
     }
@@ -167,9 +203,6 @@
 
         pub const PTRACE_DETACH: c_uint = 11;
 
-        pub const F_SETLK: c_int = 8;
-        pub const F_SETLKW: c_int = 9;
-
         pub const F_RDLCK: c_int = 1;
         pub const F_WRLCK: c_int = 2;
         pub const F_UNLCK: c_int = 3;
@@ -213,9 +246,6 @@
 
         pub const PTRACE_DETACH: c_uint = 17;
 
-        pub const F_SETLK: c_int = 6;
-        pub const F_SETLKW: c_int = 7;
-
         pub const F_RDLCK: c_int = 0;
         pub const F_WRLCK: c_int = 1;
         pub const F_UNLCK: c_int = 2;
@@ -251,6 +281,24 @@
         pub const EFD_CLOEXEC: c_int = 0x80000;
     }
 }
+cfg_if! {
+    if #[cfg(target_arch = "sparc")] {
+        pub const F_SETLK: c_int = 8;
+        pub const F_SETLKW: c_int = 9;
+    } else if #[cfg(all(
+        gnu_file_offset_bits64,
+        any(target_arch = "mips", target_arch = "mips32r6")
+    ))] {
+        pub const F_SETLK: c_int = 34;
+        pub const F_SETLKW: c_int = 35;
+    } else if #[cfg(gnu_file_offset_bits64)] {
+        pub const F_SETLK: c_int = 13;
+        pub const F_SETLKW: c_int = 14;
+    } else {
+        pub const F_SETLK: c_int = 6;
+        pub const F_SETLKW: c_int = 7;
+    }
+}
 
 #[cfg(target_endian = "little")]
 pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t {
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/powerpc.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/powerpc.rs
index b789a86..36da977 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/powerpc.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/powerpc.rs
@@ -57,6 +57,30 @@
         __glibc_reserved2: u64,
     }
 
+    pub struct stat {
+        pub st_dev: crate::dev_t,
+        #[cfg(not(gnu_file_offset_bits64))]
+        __pad1: c_ushort,
+        pub st_ino: crate::ino_t,
+        pub st_mode: crate::mode_t,
+        pub st_nlink: crate::nlink_t,
+        pub st_uid: crate::uid_t,
+        pub st_gid: crate::gid_t,
+        pub st_rdev: crate::dev_t,
+        __pad2: c_ushort,
+        pub st_size: off_t,
+        pub st_blksize: crate::blksize_t,
+        pub st_blocks: crate::blkcnt_t,
+        pub st_atime: crate::time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: crate::time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: crate::time_t,
+        pub st_ctime_nsec: c_long,
+        __glibc_reserved4: c_ulong,
+        __glibc_reserved5: c_ulong,
+    }
+
     pub struct stat64 {
         pub st_dev: crate::dev_t,
         pub st_ino: crate::ino64_t,
@@ -301,7 +325,13 @@
 pub const POLLWRNORM: c_short = 0x100;
 pub const POLLWRBAND: c_short = 0x200;
 
-pub const F_GETLK: c_int = 5;
+cfg_if! {
+    if #[cfg(gnu_file_offset_bits64)] {
+        pub const F_GETLK: c_int = 12;
+    } else {
+        pub const F_GETLK: c_int = 5;
+    }
+}
 pub const F_GETOWN: c_int = 9;
 pub const F_SETOWN: c_int = 8;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
index 968cf77..7533ad6 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
@@ -26,7 +26,8 @@
 
         pub f_namelen: crate::__fsword_t,
         pub f_frsize: crate::__fsword_t,
-        f_spare: [crate::__fsword_t; 5],
+        pub f_flags: crate::__fsword_t,
+        f_spare: [crate::__fsword_t; 4],
     }
 
     pub struct siginfo_t {
@@ -60,6 +61,30 @@
         pub ss_size: size_t,
     }
 
+    pub struct stat {
+        pub st_dev: crate::dev_t,
+        #[cfg(not(gnu_file_offset_bits64))]
+        __pad1: c_ushort,
+        pub st_ino: crate::ino_t,
+        pub st_mode: crate::mode_t,
+        pub st_nlink: crate::nlink_t,
+        pub st_uid: crate::uid_t,
+        pub st_gid: crate::gid_t,
+        pub st_rdev: crate::dev_t,
+        __pad2: c_ushort,
+        pub st_size: off_t,
+        pub st_blksize: crate::blksize_t,
+        pub st_blocks: crate::blkcnt_t,
+        pub st_atime: crate::time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: crate::time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: crate::time_t,
+        pub st_ctime_nsec: c_long,
+        __glibc_reserved4: c_ulong,
+        __glibc_reserved5: c_ulong,
+    }
+
     pub struct stat64 {
         pub st_dev: crate::dev_t,
         pub st_ino: crate::ino64_t,
@@ -78,7 +103,8 @@
         pub st_mtime_nsec: c_long,
         pub st_ctime: crate::time_t,
         pub st_ctime_nsec: c_long,
-        __reserved: [c_long; 2],
+        __glibc_reserved4: c_ulong,
+        __glibc_reserved5: c_ulong,
     }
 
     pub struct statfs64 {
@@ -106,6 +132,7 @@
         pub f_ffree: u64,
         pub f_favail: u64,
         pub f_fsid: c_ulong,
+        __f_unused: c_int,
         pub f_flag: c_ulong,
         pub f_namemax: c_ulong,
         __f_spare: [c_int; 6],
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/x86/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
index 2ec8692..c0eb9e8 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
@@ -135,7 +135,7 @@
     pub struct stat64 {
         pub st_dev: crate::dev_t,
         __pad1: c_uint,
-        __st_ino: crate::ino_t,
+        __st_ino: c_ulong,
         pub st_mode: crate::mode_t,
         pub st_nlink: crate::nlink_t,
         pub st_uid: crate::uid_t,
@@ -499,7 +499,13 @@
 pub const SOCK_STREAM: c_int = 1;
 pub const SOCK_DGRAM: c_int = 2;
 
-pub const F_GETLK: c_int = 5;
+cfg_if! {
+    if #[cfg(gnu_file_offset_bits64)] {
+        pub const F_GETLK: c_int = 12;
+    } else {
+        pub const F_GETLK: c_int = 5;
+    }
+}
 pub const F_GETOWN: c_int = 9;
 pub const F_SETOWN: c_int = 8;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/mod.rs
index 0272166e..823f495 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/gnu/mod.rs
@@ -32,7 +32,11 @@
         __error_code: c_int,
         __return_value: ssize_t,
         pub aio_offset: off_t,
-        #[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
+        #[cfg(all(
+            not(gnu_file_offset_bits64),
+            not(target_arch = "x86_64"),
+            target_pointer_width = "32"
+        ))]
         __unused1: [c_char; 4],
         __glibc_reserved: [c_char; 32],
     }
@@ -328,6 +332,13 @@
         pub u: __c_anonymous_ptrace_syscall_info_data,
     }
 
+    pub struct ptrace_sud_config {
+        pub mode: crate::__u64,
+        pub selector: crate::__u64,
+        pub offset: crate::__u64,
+        pub len: crate::__u64,
+    }
+
     pub struct iocb {
         pub aio_data: crate::__u64,
         #[cfg(target_endian = "little")]
@@ -407,6 +418,24 @@
         #[cfg(target_pointer_width = "64")]
         __size: [c_char; 32],
     }
+
+    pub struct mbstate_t {
+        __count: c_int,
+        __wchb: [c_char; 4],
+    }
+
+    pub struct fpos64_t {
+        __pos: off64_t,
+        __state: crate::mbstate_t,
+    }
+
+    pub struct fpos_t {
+        #[cfg(not(gnu_file_offset_bits64))]
+        __pos: off_t,
+        #[cfg(gnu_file_offset_bits64)]
+        __pos: off64_t,
+        __state: crate::mbstate_t,
+    }
 }
 
 impl siginfo_t {
@@ -911,6 +940,8 @@
 pub const PTRACE_SYSCALL_INFO_ENTRY: crate::__u8 = 1;
 pub const PTRACE_SYSCALL_INFO_EXIT: crate::__u8 = 2;
 pub const PTRACE_SYSCALL_INFO_SECCOMP: crate::__u8 = 3;
+pub const PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG: crate::__u8 = 0x4210;
+pub const PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG: crate::__u8 = 0x4211;
 
 // linux/fs.h
 
@@ -1200,8 +1231,11 @@
     pub fn getrlimit64(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit64) -> c_int;
     pub fn setrlimit64(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit64)
         -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "getrlimit64")]
     pub fn getrlimit(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "setrlimit64")]
     pub fn setrlimit(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "prlimit64")]
     pub fn prlimit(
         pid: crate::pid_t,
         resource: crate::__rlimit_resource_t,
@@ -1242,6 +1276,7 @@
         dirfd: c_int,
         path: *const c_char,
     ) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "preadv64v2")]
     pub fn preadv2(
         fd: c_int,
         iov: *const crate::iovec,
@@ -1249,6 +1284,7 @@
         offset: off_t,
         flags: c_int,
     ) -> ssize_t;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "pwritev64v2")]
     pub fn pwritev2(
         fd: c_int,
         iov: *const crate::iovec,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/mod.rs
index c2737f8..5be701be 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/mod.rs
@@ -74,9 +74,14 @@
 pub type sctp_assoc_t = __s32;
 
 pub type eventfd_t = u64;
-missing! {
-    #[cfg_attr(feature = "extra_traits", derive(Debug))]
-    pub enum fpos64_t {} // FIXME(linux): fill this out with a struct
+
+cfg_if! {
+    if #[cfg(not(target_env = "gnu"))] {
+        missing! {
+            #[cfg_attr(feature = "extra_traits", derive(Debug))]
+            pub enum fpos64_t {} // FIXME(linux): fill this out with a struct
+        }
+    }
 }
 
 e! {
@@ -966,6 +971,14 @@
         pub rec_seq: [c_uchar; TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE],
     }
 
+    pub struct tls12_crypto_info_aes_ccm_128 {
+        pub info: tls_crypto_info,
+        pub iv: [c_uchar; TLS_CIPHER_AES_CCM_128_IV_SIZE],
+        pub key: [c_uchar; TLS_CIPHER_AES_CCM_128_KEY_SIZE],
+        pub salt: [c_uchar; TLS_CIPHER_AES_CCM_128_SALT_SIZE],
+        pub rec_seq: [c_uchar; TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE],
+    }
+
     pub struct tls12_crypto_info_chacha20_poly1305 {
         pub info: tls_crypto_info,
         pub iv: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE],
@@ -974,6 +987,38 @@
         pub rec_seq: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE],
     }
 
+    pub struct tls12_crypto_info_sm4_gcm {
+        pub info: tls_crypto_info,
+        pub iv: [c_uchar; TLS_CIPHER_SM4_GCM_IV_SIZE],
+        pub key: [c_uchar; TLS_CIPHER_SM4_GCM_KEY_SIZE],
+        pub salt: [c_uchar; TLS_CIPHER_SM4_GCM_SALT_SIZE],
+        pub rec_seq: [c_uchar; TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE],
+    }
+
+    pub struct tls12_crypto_info_sm4_ccm {
+        pub info: tls_crypto_info,
+        pub iv: [c_uchar; TLS_CIPHER_SM4_CCM_IV_SIZE],
+        pub key: [c_uchar; TLS_CIPHER_SM4_CCM_KEY_SIZE],
+        pub salt: [c_uchar; TLS_CIPHER_SM4_CCM_SALT_SIZE],
+        pub rec_seq: [c_uchar; TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE],
+    }
+
+    pub struct tls12_crypto_info_aria_gcm_128 {
+        pub info: tls_crypto_info,
+        pub iv: [c_uchar; TLS_CIPHER_ARIA_GCM_128_IV_SIZE],
+        pub key: [c_uchar; TLS_CIPHER_ARIA_GCM_128_KEY_SIZE],
+        pub salt: [c_uchar; TLS_CIPHER_ARIA_GCM_128_SALT_SIZE],
+        pub rec_seq: [c_uchar; TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE],
+    }
+
+    pub struct tls12_crypto_info_aria_gcm_256 {
+        pub info: tls_crypto_info,
+        pub iv: [c_uchar; TLS_CIPHER_ARIA_GCM_256_IV_SIZE],
+        pub key: [c_uchar; TLS_CIPHER_ARIA_GCM_256_KEY_SIZE],
+        pub salt: [c_uchar; TLS_CIPHER_ARIA_GCM_256_SALT_SIZE],
+        pub rec_seq: [c_uchar; TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE],
+    }
+
     // linux/wireless.h
 
     pub struct iw_param {
@@ -3285,18 +3330,19 @@
 pub const SECCOMP_GET_ACTION_AVAIL: c_uint = 2;
 pub const SECCOMP_GET_NOTIF_SIZES: c_uint = 3;
 
-pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1;
-pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 2;
-pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 4;
-pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 8;
-pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: c_ulong = 16;
-pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: c_ulong = 32;
+pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1 << 0;
+pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 1 << 1;
+pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 1 << 2;
+pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 1 << 3;
+pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: c_ulong = 1 << 4;
+pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: c_ulong = 1 << 5;
 
 pub const SECCOMP_RET_KILL_PROCESS: c_uint = 0x80000000;
 pub const SECCOMP_RET_KILL_THREAD: c_uint = 0x00000000;
 pub const SECCOMP_RET_KILL: c_uint = SECCOMP_RET_KILL_THREAD;
 pub const SECCOMP_RET_TRAP: c_uint = 0x00030000;
 pub const SECCOMP_RET_ERRNO: c_uint = 0x00050000;
+pub const SECCOMP_RET_USER_NOTIF: c_uint = 0x7fc00000;
 pub const SECCOMP_RET_TRACE: c_uint = 0x7ff00000;
 pub const SECCOMP_RET_LOG: c_uint = 0x7ffc0000;
 pub const SECCOMP_RET_ALLOW: c_uint = 0x7fff0000;
@@ -3451,6 +3497,12 @@
 pub const BPF_K: __u32 = 0x00;
 pub const BPF_X: __u32 = 0x08;
 
+// linux/filter.h
+
+pub const BPF_A: __u32 = 0x10;
+pub const BPF_TAX: __u32 = 0x00;
+pub const BPF_TXA: __u32 = 0x80;
+
 // linux/openat2.h
 pub const RESOLVE_NO_XDEV: crate::__u64 = 0x01;
 pub const RESOLVE_NO_MAGICLINKS: crate::__u64 = 0x02;
@@ -4419,6 +4471,12 @@
 pub const NLM_F_CREATE: c_int = 0x400;
 pub const NLM_F_APPEND: c_int = 0x800;
 
+pub const NLM_F_NONREC: c_int = 0x100;
+pub const NLM_F_BULK: c_int = 0x200;
+
+pub const NLM_F_CAPPED: c_int = 0x100;
+pub const NLM_F_ACK_TLVS: c_int = 0x200;
+
 pub const NETLINK_ADD_MEMBERSHIP: c_int = 1;
 pub const NETLINK_DROP_MEMBERSHIP: c_int = 2;
 pub const NETLINK_PKTINFO: c_int = 3;
@@ -4714,6 +4772,9 @@
 pub const TLS_TX: c_int = 1;
 pub const TLS_RX: c_int = 2;
 
+pub const TLS_TX_ZEROCOPY_RO: c_int = 3;
+pub const TLS_RX_EXPECT_NO_PAD: c_int = 4;
+
 pub const TLS_1_2_VERSION_MAJOR: __u8 = 0x3;
 pub const TLS_1_2_VERSION_MINOR: __u8 = 0x3;
 pub const TLS_1_2_VERSION: __u16 =
@@ -4738,6 +4799,13 @@
 pub const TLS_CIPHER_AES_GCM_256_TAG_SIZE: usize = 16;
 pub const TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE: usize = 8;
 
+pub const TLS_CIPHER_AES_CCM_128: __u16 = 53;
+pub const TLS_CIPHER_AES_CCM_128_IV_SIZE: usize = 8;
+pub const TLS_CIPHER_AES_CCM_128_KEY_SIZE: usize = 16;
+pub const TLS_CIPHER_AES_CCM_128_SALT_SIZE: usize = 4;
+pub const TLS_CIPHER_AES_CCM_128_TAG_SIZE: usize = 16;
+pub const TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE: usize = 8;
+
 pub const TLS_CIPHER_CHACHA20_POLY1305: __u16 = 54;
 pub const TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE: usize = 12;
 pub const TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE: usize = 32;
@@ -4745,11 +4813,53 @@
 pub const TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE: usize = 16;
 pub const TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE: usize = 8;
 
+pub const TLS_CIPHER_SM4_GCM: __u16 = 55;
+pub const TLS_CIPHER_SM4_GCM_IV_SIZE: usize = 8;
+pub const TLS_CIPHER_SM4_GCM_KEY_SIZE: usize = 16;
+pub const TLS_CIPHER_SM4_GCM_SALT_SIZE: usize = 4;
+pub const TLS_CIPHER_SM4_GCM_TAG_SIZE: usize = 16;
+pub const TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE: usize = 8;
+
+pub const TLS_CIPHER_SM4_CCM: __u16 = 56;
+pub const TLS_CIPHER_SM4_CCM_IV_SIZE: usize = 8;
+pub const TLS_CIPHER_SM4_CCM_KEY_SIZE: usize = 16;
+pub const TLS_CIPHER_SM4_CCM_SALT_SIZE: usize = 4;
+pub const TLS_CIPHER_SM4_CCM_TAG_SIZE: usize = 16;
+pub const TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE: usize = 8;
+
+pub const TLS_CIPHER_ARIA_GCM_128: __u16 = 57;
+pub const TLS_CIPHER_ARIA_GCM_128_IV_SIZE: usize = 8;
+pub const TLS_CIPHER_ARIA_GCM_128_KEY_SIZE: usize = 16;
+pub const TLS_CIPHER_ARIA_GCM_128_SALT_SIZE: usize = 4;
+pub const TLS_CIPHER_ARIA_GCM_128_TAG_SIZE: usize = 16;
+pub const TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE: usize = 8;
+
+pub const TLS_CIPHER_ARIA_GCM_256: __u16 = 58;
+pub const TLS_CIPHER_ARIA_GCM_256_IV_SIZE: usize = 8;
+pub const TLS_CIPHER_ARIA_GCM_256_KEY_SIZE: usize = 32;
+pub const TLS_CIPHER_ARIA_GCM_256_SALT_SIZE: usize = 4;
+pub const TLS_CIPHER_ARIA_GCM_256_TAG_SIZE: usize = 16;
+pub const TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE: usize = 8;
+
 pub const TLS_SET_RECORD_TYPE: c_int = 1;
 pub const TLS_GET_RECORD_TYPE: c_int = 2;
 
 pub const SOL_TLS: c_int = 282;
 
+// enum
+pub const TLS_INFO_UNSPEC: c_int = 0x00;
+pub const TLS_INFO_VERSION: c_int = 0x01;
+pub const TLS_INFO_CIPHER: c_int = 0x02;
+pub const TLS_INFO_TXCONF: c_int = 0x03;
+pub const TLS_INFO_RXCONF: c_int = 0x04;
+pub const TLS_INFO_ZC_RO_TX: c_int = 0x05;
+pub const TLS_INFO_RX_NO_PAD: c_int = 0x06;
+
+pub const TLS_CONF_BASE: c_int = 1;
+pub const TLS_CONF_SW: c_int = 2;
+pub const TLS_CONF_HW: c_int = 3;
+pub const TLS_CONF_HW_RECORD: c_int = 4;
+
 // linux/if_alg.h
 pub const ALG_SET_KEY: c_int = 1;
 pub const ALG_SET_IV: c_int = 2;
@@ -5092,6 +5202,13 @@
 pub const FF_CNT: usize = FF_MAX as usize + 1;
 
 // linux/input-event-codes.h
+pub const INPUT_PROP_POINTER: __u16 = 0x00;
+pub const INPUT_PROP_DIRECT: __u16 = 0x01;
+pub const INPUT_PROP_BUTTONPAD: __u16 = 0x02;
+pub const INPUT_PROP_SEMI_MT: __u16 = 0x03;
+pub const INPUT_PROP_TOPBUTTONPAD: __u16 = 0x04;
+pub const INPUT_PROP_POINTING_STICK: __u16 = 0x05;
+pub const INPUT_PROP_ACCELEROMETER: __u16 = 0x06;
 pub const INPUT_PROP_MAX: __u16 = 0x1f;
 pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1;
 pub const EV_MAX: __u16 = 0x1f;
@@ -5868,88 +5985,28 @@
 pub const EPIOCSPARAMS: Ioctl = 0x40088a01;
 pub const EPIOCGPARAMS: Ioctl = 0x80088a02;
 
-const _IOC_NRBITS: u32 = 8;
-const _IOC_TYPEBITS: u32 = 8;
-
 // siginfo.h
 pub const SI_DETHREAD: c_int = -7;
 pub const TRAP_PERF: c_int = 6;
 
-// https://github.com/search?q=repo%3Atorvalds%2Flinux+%22%23define+_IOC_NONE%22&type=code
-cfg_if! {
-    if #[cfg(any(
-        any(target_arch = "powerpc", target_arch = "powerpc64"),
-        any(target_arch = "sparc", target_arch = "sparc64"),
-        any(target_arch = "mips", target_arch = "mips64"),
-    ))] {
-        // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/powerpc/include/uapi/asm/ioctl.h
-        // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/sparc/include/uapi/asm/ioctl.h
-        // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/mips/include/uapi/asm/ioctl.h
-
-        const _IOC_SIZEBITS: u32 = 13;
-        const _IOC_DIRBITS: u32 = 3;
-
-        const _IOC_NONE: u32 = 1;
-        const _IOC_READ: u32 = 2;
-        const _IOC_WRITE: u32 = 4;
-    } else {
-        // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/include/uapi/asm-generic/ioctl.h
-
-        const _IOC_SIZEBITS: u32 = 14;
-        const _IOC_DIRBITS: u32 = 2;
-
-        const _IOC_NONE: u32 = 0;
-        const _IOC_WRITE: u32 = 1;
-        const _IOC_READ: u32 = 2;
-    }
-}
-
-const _IOC_NRMASK: u32 = (1 << _IOC_NRBITS) - 1;
-const _IOC_TYPEMASK: u32 = (1 << _IOC_TYPEBITS) - 1;
-const _IOC_SIZEMASK: u32 = (1 << _IOC_SIZEBITS) - 1;
-const _IOC_DIRMASK: u32 = (1 << _IOC_DIRBITS) - 1;
-
-const _IOC_NRSHIFT: u32 = 0;
-const _IOC_TYPESHIFT: u32 = _IOC_NRSHIFT + _IOC_NRBITS;
-const _IOC_SIZESHIFT: u32 = _IOC_TYPESHIFT + _IOC_TYPEBITS;
-const _IOC_DIRSHIFT: u32 = _IOC_SIZESHIFT + _IOC_SIZEBITS;
-
-// adapted from https://github.com/torvalds/linux/blob/8a696a29c6905594e4abf78eaafcb62165ac61f1/rust/kernel/ioctl.rs
-
-/// Build an ioctl number, analogous to the C macro of the same name.
-const fn _IOC(dir: u32, ty: u32, nr: u32, size: usize) -> u32 {
-    // FIXME(ctest) the `garando_syntax` crate (used by ctest2 in the CI test suite)
-    // cannot currently parse these `debug_assert!`s
-    //
-    // debug_assert!(dir <= _IOC_DIRMASK);
-    // debug_assert!(ty <= _IOC_TYPEMASK);
-    // debug_assert!(nr <= _IOC_NRMASK);
-    // debug_assert!(size <= (_IOC_SIZEMASK as usize));
-
-    (dir << _IOC_DIRSHIFT)
-        | (ty << _IOC_TYPESHIFT)
-        | (nr << _IOC_NRSHIFT)
-        | ((size as u32) << _IOC_SIZESHIFT)
-}
-
 /// Build an ioctl number for an argumentless ioctl.
-pub(crate) const fn _IO(ty: u32, nr: u32) -> u32 {
-    _IOC(_IOC_NONE, ty, nr, 0)
+pub const fn _IO(ty: u32, nr: u32) -> u32 {
+    super::_IOC(super::_IOC_NONE, ty, nr, 0)
 }
 
 /// Build an ioctl number for an read-only ioctl.
-pub(crate) const fn _IOR<T>(ty: u32, nr: u32) -> u32 {
-    _IOC(_IOC_READ, ty, nr, size_of::<T>())
+pub const fn _IOR<T>(ty: u32, nr: u32) -> u32 {
+    super::_IOC(super::_IOC_READ, ty, nr, size_of::<T>())
 }
 
 /// Build an ioctl number for an write-only ioctl.
-pub(crate) const fn _IOW<T>(ty: u32, nr: u32) -> u32 {
-    _IOC(_IOC_WRITE, ty, nr, size_of::<T>())
+pub const fn _IOW<T>(ty: u32, nr: u32) -> u32 {
+    super::_IOC(super::_IOC_WRITE, ty, nr, size_of::<T>())
 }
 
 /// Build an ioctl number for a read-write ioctl.
-pub(crate) const fn _IOWR<T>(ty: u32, nr: u32) -> u32 {
-    _IOC(_IOC_READ | _IOC_WRITE, ty, nr, size_of::<T>())
+pub const fn _IOWR<T>(ty: u32, nr: u32) -> u32 {
+    super::_IOC(super::_IOC_READ | super::_IOC_WRITE, ty, nr, size_of::<T>())
 }
 
 f! {
@@ -6063,6 +6120,26 @@
         (x + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1)
     }
 
+    pub fn BPF_CLASS(code: __u32) -> __u32 {
+        code & 0x07
+    }
+
+    pub fn BPF_SIZE(code: __u32) -> __u32 {
+        code & 0x18
+    }
+
+    pub fn BPF_MODE(code: __u32) -> __u32 {
+        code & 0xe0
+    }
+
+    pub fn BPF_OP(code: __u32) -> __u32 {
+        code & 0xf0
+    }
+
+    pub fn BPF_SRC(code: __u32) -> __u32 {
+        code & 0x08
+    }
+
     pub fn BPF_RVAL(code: __u32) -> __u32 {
         code & 0x18
     }
@@ -6168,17 +6245,23 @@
 cfg_if! {
     if #[cfg(all(not(target_env = "uclibc"), not(target_env = "ohos")))] {
         extern "C" {
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_read64")]
             pub fn aio_read(aiocbp: *mut aiocb) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_write64")]
             pub fn aio_write(aiocbp: *mut aiocb) -> c_int;
             pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_error64")]
             pub fn aio_error(aiocbp: *const aiocb) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_return64")]
             pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t;
             pub fn aio_suspend(
                 aiocb_list: *const *const aiocb,
                 nitems: c_int,
                 timeout: *const crate::timespec,
             ) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_cancel64")]
             pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "lio_listio64")]
             pub fn lio_listio(
                 mode: c_int,
                 aiocb_list: *const *mut aiocb,
@@ -6192,12 +6275,14 @@
 cfg_if! {
     if #[cfg(not(target_env = "uclibc"))] {
         extern "C" {
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "pwritev64")]
             pub fn pwritev(
                 fd: c_int,
                 iov: *const crate::iovec,
                 iovcnt: c_int,
                 offset: off_t,
             ) -> ssize_t;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "preadv64")]
             pub fn preadv(
                 fd: c_int,
                 iov: *const crate::iovec,
@@ -6362,7 +6447,9 @@
     pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int;
     pub fn __errno_location() -> *mut c_int;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fallocate64")]
     pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "posix_fallocate64")]
     pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int;
     pub fn readahead(fd: c_int, offset: off64_t, count: size_t) -> ssize_t;
     pub fn getxattr(
@@ -6469,12 +6556,14 @@
         ...
     ) -> *mut c_void;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "glob64")]
     pub fn glob(
         pattern: *const c_char,
         flags: c_int,
         errfunc: Option<extern "C" fn(epath: *const c_char, errno: c_int) -> c_int>,
         pglob: *mut crate::glob_t,
     ) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "globfree64")]
     pub fn globfree(pglob: *mut crate::glob_t);
 
     pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
@@ -6500,6 +6589,7 @@
         addr: *mut crate::sockaddr,
         addrlen: *mut crate::socklen_t,
     ) -> ssize_t;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "mkstemps64")]
     pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int;
 
     pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char;
@@ -6664,6 +6754,7 @@
         policy: c_int,
         param: *const crate::sched_param,
     ) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "sendfile64")]
     pub fn sendfile(out_fd: c_int, in_fd: c_int, offset: *mut off_t, count: size_t) -> ssize_t;
     pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int;
     pub fn getgrgid_r(
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/arm/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/arm/mod.rs
index ad74ecfc..292585fc 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/arm/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/arm/mod.rs
@@ -795,7 +795,3 @@
 pub const SYS_futex_waitv: c_long = 449;
 pub const SYS_set_mempolicy_home_node: c_long = 450;
 pub const SYS_mseal: c_long = 462;
-
-extern "C" {
-    pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/powerpc.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/powerpc.rs
index 7d7124a..0de40b1 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/powerpc.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/powerpc.rs
@@ -745,7 +745,3 @@
 pub const SYS_futex_waitv: c_long = 449;
 pub const SYS_set_mempolicy_home_node: c_long = 450;
 pub const SYS_mseal: c_long = 462;
-
-extern "C" {
-    pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
index 1a4ab1c6..9c0525c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
@@ -111,7 +111,6 @@
 
 //pub const RLIM_INFINITY: crate::rlim_t = !0;
 pub const VEOF: usize = 4;
-pub const RTLD_DEEPBIND: c_int = 0x8;
 //pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5;
 //pub const RLIMIT_AS: crate::__rlimit_resource_t = 9;
 //pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 8;
@@ -125,7 +124,6 @@
 pub const O_SYNC: c_int = 1052672;
 pub const O_RSYNC: c_int = 1052672;
 pub const O_DSYNC: c_int = 4096;
-pub const O_FSYNC: c_int = 1052672;
 pub const MAP_GROWSDOWN: c_int = 256;
 pub const EDEADLK: c_int = 35;
 pub const ENAMETOOLONG: c_int = 36;
@@ -209,7 +207,7 @@
 
 pub const SOCK_STREAM: c_int = 1;
 pub const SOCK_DGRAM: c_int = 2;
-pub const SA_ONSTACK: c_int = 8;
+pub const SA_ONSTACK: c_int = 0x08000000;
 pub const SA_SIGINFO: c_int = 4;
 pub const SA_NOCLDWAIT: c_int = 2;
 pub const SIGTTIN: c_int = 21;
@@ -346,7 +344,7 @@
 pub const SYS_read: c_long = 63;
 pub const SYS_write: c_long = 64;
 pub const SYS_close: c_long = 57;
-pub const SYS_fstat: c_long = 80;
+// RISC-V don't have SYS_fstat, use statx instead.
 pub const SYS_lseek: c_long = 62;
 pub const SYS_mmap: c_long = 222;
 pub const SYS_mprotect: c_long = 226;
@@ -369,7 +367,6 @@
 pub const SYS_shmat: c_long = 196;
 pub const SYS_shmctl: c_long = 195;
 pub const SYS_dup: c_long = 23;
-pub const SYS_nanosleep: c_long = 101;
 pub const SYS_getitimer: c_long = 102;
 pub const SYS_setitimer: c_long = 103;
 pub const SYS_getpid: c_long = 172;
@@ -392,7 +389,7 @@
 pub const SYS_clone: c_long = 220;
 pub const SYS_execve: c_long = 221;
 pub const SYS_exit: c_long = 93;
-pub const SYS_wait4: c_long = 260;
+// RISC-V don't have wait4, use waitid instead.
 pub const SYS_kill: c_long = 129;
 pub const SYS_uname: c_long = 160;
 pub const SYS_semget: c_long = 190;
@@ -415,8 +412,8 @@
 pub const SYS_fchmod: c_long = 52;
 pub const SYS_fchown: c_long = 55;
 pub const SYS_umask: c_long = 166;
-pub const SYS_gettimeofday: c_long = 169;
-pub const SYS_getrlimit: c_long = 163;
+// RISC-V don't have gettimeofday, use clock_gettime64 instead.
+// RISC-V don't have getrlimit, use prlimit64 instead.
 pub const SYS_getrusage: c_long = 165;
 pub const SYS_sysinfo: c_long = 179;
 pub const SYS_times: c_long = 153;
@@ -446,7 +443,7 @@
 pub const SYS_capget: c_long = 90;
 pub const SYS_capset: c_long = 91;
 pub const SYS_rt_sigpending: c_long = 136;
-pub const SYS_rt_sigtimedwait: c_long = 137;
+pub const SYS_rt_sigtimedwait_time64: c_long = 421;
 pub const SYS_rt_sigqueueinfo: c_long = 138;
 pub const SYS_rt_sigsuspend: c_long = 133;
 pub const SYS_sigaltstack: c_long = 132;
@@ -461,7 +458,7 @@
 pub const SYS_sched_getscheduler: c_long = 120;
 pub const SYS_sched_get_priority_max: c_long = 125;
 pub const SYS_sched_get_priority_min: c_long = 126;
-pub const SYS_sched_rr_get_interval: c_long = 127;
+pub const SYS_sched_rr_get_interval_time64: c_long = 423;
 pub const SYS_mlock: c_long = 228;
 pub const SYS_munlock: c_long = 229;
 pub const SYS_mlockall: c_long = 230;
@@ -469,12 +466,11 @@
 pub const SYS_vhangup: c_long = 58;
 pub const SYS_pivot_root: c_long = 41;
 pub const SYS_prctl: c_long = 167;
-pub const SYS_adjtimex: c_long = 171;
-pub const SYS_setrlimit: c_long = 164;
+// RISC-V don't have setrlimit, use prlimit64 instead.
 pub const SYS_chroot: c_long = 51;
 pub const SYS_sync: c_long = 81;
 pub const SYS_acct: c_long = 89;
-pub const SYS_settimeofday: c_long = 170;
+// RISC-V don't have settimeofday, use clock_settime64 instead.
 pub const SYS_mount: c_long = 40;
 pub const SYS_umount2: c_long = 39;
 pub const SYS_swapon: c_long = 224;
@@ -501,12 +497,12 @@
 pub const SYS_lremovexattr: c_long = 15;
 pub const SYS_fremovexattr: c_long = 16;
 pub const SYS_tkill: c_long = 130;
-pub const SYS_futex: c_long = 98;
+pub const SYS_futex_time64: c_long = 422;
 pub const SYS_sched_setaffinity: c_long = 122;
 pub const SYS_sched_getaffinity: c_long = 123;
 pub const SYS_io_setup: c_long = 0;
 pub const SYS_io_destroy: c_long = 1;
-pub const SYS_io_getevents: c_long = 4;
+pub const SYS_io_pgetevents_time64: c_long = 416;
 pub const SYS_io_submit: c_long = 2;
 pub const SYS_io_cancel: c_long = 3;
 pub const SYS_lookup_dcookie: c_long = 18;
@@ -514,17 +510,17 @@
 pub const SYS_getdents64: c_long = 61;
 pub const SYS_set_tid_address: c_long = 96;
 pub const SYS_restart_syscall: c_long = 128;
-pub const SYS_semtimedop: c_long = 192;
+pub const SYS_semtimedop_time64: c_long = 420;
 pub const SYS_fadvise64: c_long = 223;
 pub const SYS_timer_create: c_long = 107;
-pub const SYS_timer_settime: c_long = 110;
-pub const SYS_timer_gettime: c_long = 108;
+pub const SYS_timer_settime64: c_long = 409;
+pub const SYS_timer_gettime64: c_long = 408;
 pub const SYS_timer_getoverrun: c_long = 109;
 pub const SYS_timer_delete: c_long = 111;
-pub const SYS_clock_settime: c_long = 112;
-pub const SYS_clock_gettime: c_long = 113;
-pub const SYS_clock_getres: c_long = 114;
-pub const SYS_clock_nanosleep: c_long = 115;
+pub const SYS_clock_settime64: c_long = 404;
+pub const SYS_clock_gettime64: c_long = 403;
+pub const SYS_clock_getres_time64: c_long = 406;
+pub const SYS_clock_nanosleep_time64: c_long = 407;
 pub const SYS_exit_group: c_long = 94;
 pub const SYS_epoll_ctl: c_long = 21;
 pub const SYS_tgkill: c_long = 131;
@@ -533,8 +529,8 @@
 pub const SYS_get_mempolicy: c_long = 236;
 pub const SYS_mq_open: c_long = 180;
 pub const SYS_mq_unlink: c_long = 181;
-pub const SYS_mq_timedsend: c_long = 182;
-pub const SYS_mq_timedreceive: c_long = 183;
+pub const SYS_mq_timedsend_time64: c_long = 418;
+pub const SYS_mq_timedreceive_time64: c_long = 419;
 pub const SYS_mq_notify: c_long = 184;
 pub const SYS_mq_getsetattr: c_long = 185;
 pub const SYS_kexec_load: c_long = 104;
@@ -551,15 +547,15 @@
 pub const SYS_mkdirat: c_long = 34;
 pub const SYS_mknodat: c_long = 33;
 pub const SYS_fchownat: c_long = 54;
-pub const SYS_newfstatat: c_long = 79;
+// RISC-V don't have newfstatat, use statx instead.
 pub const SYS_unlinkat: c_long = 35;
 pub const SYS_linkat: c_long = 37;
 pub const SYS_symlinkat: c_long = 36;
 pub const SYS_readlinkat: c_long = 78;
 pub const SYS_fchmodat: c_long = 53;
 pub const SYS_faccessat: c_long = 48;
-pub const SYS_pselect6: c_long = 72;
-pub const SYS_ppoll: c_long = 73;
+pub const SYS_pselect6_time64: c_long = 413;
+pub const SYS_ppoll_time64: c_long = 414;
 pub const SYS_unshare: c_long = 97;
 pub const SYS_set_robust_list: c_long = 99;
 pub const SYS_get_robust_list: c_long = 100;
@@ -568,12 +564,12 @@
 pub const SYS_sync_file_range: c_long = 84;
 pub const SYS_vmsplice: c_long = 75;
 pub const SYS_move_pages: c_long = 239;
-pub const SYS_utimensat: c_long = 88;
+pub const SYS_utimensat_time64: c_long = 412;
 pub const SYS_epoll_pwait: c_long = 22;
 pub const SYS_timerfd_create: c_long = 85;
 pub const SYS_fallocate: c_long = 47;
-pub const SYS_timerfd_settime: c_long = 86;
-pub const SYS_timerfd_gettime: c_long = 87;
+pub const SYS_timerfd_settime64: c_long = 411;
+pub const SYS_timerfd_gettime64: c_long = 410;
 pub const SYS_accept4: c_long = 242;
 pub const SYS_signalfd4: c_long = 74;
 pub const SYS_eventfd2: c_long = 19;
@@ -585,13 +581,13 @@
 pub const SYS_pwritev: c_long = 70;
 pub const SYS_rt_tgsigqueueinfo: c_long = 240;
 pub const SYS_perf_event_open: c_long = 241;
-pub const SYS_recvmmsg: c_long = 243;
+pub const SYS_recvmmsg_time64: c_long = 417;
 pub const SYS_fanotify_init: c_long = 262;
 pub const SYS_fanotify_mark: c_long = 263;
 pub const SYS_prlimit64: c_long = 261;
 pub const SYS_name_to_handle_at: c_long = 264;
 pub const SYS_open_by_handle_at: c_long = 265;
-pub const SYS_clock_adjtime: c_long = 266;
+pub const SYS_clock_adjtime64: c_long = 405;
 pub const SYS_syncfs: c_long = 267;
 pub const SYS_sendmmsg: c_long = 269;
 pub const SYS_setns: c_long = 268;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/x86/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/x86/mod.rs
index a01dca67..22befbb0 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/x86/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b32/x86/mod.rs
@@ -913,7 +913,3 @@
 pub const EFL: c_int = 14;
 pub const UESP: c_int = 15;
 pub const SS: c_int = 16;
-
-extern "C" {
-    pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b64/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b64/mod.rs
index 6ae3c39..6b6761b 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b64/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/b64/mod.rs
@@ -81,10 +81,6 @@
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32;
 
-extern "C" {
-    pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
-}
-
 cfg_if! {
     if #[cfg(target_arch = "aarch64")] {
         mod aarch64;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/mod.rs
index 57109e92..f850849 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/musl/mod.rs
@@ -654,7 +654,7 @@
 pub const LOGIN_PROCESS: c_short = 6;
 pub const USER_PROCESS: c_short = 7;
 pub const DEAD_PROCESS: c_short = 8;
-// musl does not define ACCOUNTING
+pub const ACCOUNTING: c_short = 9;
 
 pub const SFD_CLOEXEC: c_int = 0x080000;
 
@@ -886,6 +886,10 @@
 
 pub const CLONE_NEWTIME: c_int = 0x80;
 
+pub const UT_HOSTSIZE: usize = 256;
+pub const UT_LINESIZE: usize = 32;
+pub const UT_NAMESIZE: usize = 32;
+
 cfg_if! {
     if #[cfg(target_arch = "s390x")] {
         pub const POSIX_FADV_DONTNEED: c_int = 6;
@@ -971,6 +975,9 @@
     pub fn dirname(path: *mut c_char) -> *mut c_char;
     pub fn basename(path: *mut c_char) -> *mut c_char;
 
+    // Addded in `musl` 1.1.20
+    pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t;
+
     // Added in `musl` 1.1.24
     pub fn posix_spawn_file_actions_addchdir_np(
         actions: *mut crate::posix_spawn_file_actions_t,
@@ -982,12 +989,41 @@
         fd: c_int,
     ) -> c_int;
 
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn getutxent() -> *mut utmpx;
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn getutxid(ut: *const utmpx) -> *mut utmpx;
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn getutxline(ut: *const utmpx) -> *mut utmpx;
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn pututxline(ut: *const utmpx) -> *mut utmpx;
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn setutxent();
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
     pub fn endutxent();
+    #[deprecated(
+        since = "0.2.172",
+        note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html"
+    )]
+    pub fn utmpxname(file: *const c_char) -> c_int;
 }
 
 // Alias <foo> to <foo>64 to mimic glibc's LFS64 support
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/uclibc/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/uclibc/mod.rs
index 272f3c4..b7a34dd 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/uclibc/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/linux/uclibc/mod.rs
@@ -114,6 +114,42 @@
     pub struct pthread_condattr_t {
         size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T],
     }
+
+    pub struct tcp_info {
+        pub tcpi_state: u8,
+        pub tcpi_ca_state: u8,
+        pub tcpi_retransmits: u8,
+        pub tcpi_probes: u8,
+        pub tcpi_backoff: u8,
+        pub tcpi_options: u8,
+        /// This contains the bitfields `tcpi_snd_wscale` and `tcpi_rcv_wscale`.
+        /// Each is 4 bits.
+        pub tcpi_snd_rcv_wscale: u8,
+        pub tcpi_rto: u32,
+        pub tcpi_ato: u32,
+        pub tcpi_snd_mss: u32,
+        pub tcpi_rcv_mss: u32,
+        pub tcpi_unacked: u32,
+        pub tcpi_sacked: u32,
+        pub tcpi_lost: u32,
+        pub tcpi_retrans: u32,
+        pub tcpi_fackets: u32,
+        pub tcpi_last_data_sent: u32,
+        pub tcpi_last_ack_sent: u32,
+        pub tcpi_last_data_recv: u32,
+        pub tcpi_last_ack_recv: u32,
+        pub tcpi_pmtu: u32,
+        pub tcpi_rcv_ssthresh: u32,
+        pub tcpi_rtt: u32,
+        pub tcpi_rttvar: u32,
+        pub tcpi_snd_ssthresh: u32,
+        pub tcpi_snd_cwnd: u32,
+        pub tcpi_advmss: u32,
+        pub tcpi_reordering: u32,
+        pub tcpi_rcv_rtt: u32,
+        pub tcpi_rcv_space: u32,
+        pub tcpi_total_retrans: u32,
+    }
 }
 
 impl siginfo_t {
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/mod.rs
index b3e6281..64481a67 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/linux_like/mod.rs
@@ -1631,6 +1631,73 @@
     }
 }
 
+// https://github.com/search?q=repo%3Atorvalds%2Flinux+%22%23define+_IOC_NONE%22&type=code
+cfg_if! {
+    if #[cfg(any(
+        target_os = "linux",
+        target_os = "android",
+        target_os = "l4re"
+    ))] {
+        const _IOC_NRBITS: u32 = 8;
+        const _IOC_TYPEBITS: u32 = 8;
+
+        cfg_if! {
+            if #[cfg(any(
+                any(target_arch = "powerpc", target_arch = "powerpc64"),
+                any(target_arch = "sparc", target_arch = "sparc64"),
+                any(target_arch = "mips", target_arch = "mips64"),
+            ))] {
+                // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/powerpc/include/uapi/asm/ioctl.h
+                // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/sparc/include/uapi/asm/ioctl.h
+                // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/mips/include/uapi/asm/ioctl.h
+
+                const _IOC_SIZEBITS: u32 = 13;
+                const _IOC_DIRBITS: u32 = 3;
+
+                const _IOC_NONE: u32 = 1;
+                const _IOC_READ: u32 = 2;
+                const _IOC_WRITE: u32 = 4;
+            } else {
+                // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/include/uapi/asm-generic/ioctl.h
+
+                const _IOC_SIZEBITS: u32 = 14;
+                const _IOC_DIRBITS: u32 = 2;
+
+                const _IOC_NONE: u32 = 0;
+                const _IOC_WRITE: u32 = 1;
+                const _IOC_READ: u32 = 2;
+            }
+        }
+        const _IOC_NRMASK: u32 = (1 << _IOC_NRBITS) - 1;
+        const _IOC_TYPEMASK: u32 = (1 << _IOC_TYPEBITS) - 1;
+        const _IOC_SIZEMASK: u32 = (1 << _IOC_SIZEBITS) - 1;
+        const _IOC_DIRMASK: u32 = (1 << _IOC_DIRBITS) - 1;
+
+        const _IOC_NRSHIFT: u32 = 0;
+        const _IOC_TYPESHIFT: u32 = _IOC_NRSHIFT + _IOC_NRBITS;
+        const _IOC_SIZESHIFT: u32 = _IOC_TYPESHIFT + _IOC_TYPEBITS;
+        const _IOC_DIRSHIFT: u32 = _IOC_SIZESHIFT + _IOC_SIZEBITS;
+
+        // adapted from https://github.com/torvalds/linux/blob/8a696a29c6905594e4abf78eaafcb62165ac61f1/rust/kernel/ioctl.rs
+
+        /// Build an ioctl number, analogous to the C macro of the same name.
+        const fn _IOC(dir: u32, ty: u32, nr: u32, size: usize) -> u32 {
+            // FIXME(ctest) the `garando_syntax` crate (used by ctest in the CI test suite)
+            // cannot currently parse these `debug_assert!`s
+            //
+            // debug_assert!(dir <= _IOC_DIRMASK);
+            // debug_assert!(ty <= _IOC_TYPEMASK);
+            // debug_assert!(nr <= _IOC_NRMASK);
+            // debug_assert!(size <= (_IOC_SIZEMASK as usize));
+
+            (dir << _IOC_DIRSHIFT)
+                | (ty << _IOC_TYPESHIFT)
+                | (nr << _IOC_NRSHIFT)
+                | ((size as u32) << _IOC_SIZESHIFT)
+        }
+    }
+}
+
 const_fn! {
     {const} fn CMSG_ALIGN(len: usize) -> usize {
         len + mem::size_of::<usize>() - 1 & !(mem::size_of::<usize>() - 1)
@@ -1784,12 +1851,20 @@
         stackaddr: *mut *mut c_void,
         stacksize: *mut size_t,
     ) -> c_int;
+    pub fn pthread_attr_setstack(
+        attr: *mut crate::pthread_attr_t,
+        stackaddr: *mut c_void,
+        stacksize: size_t,
+    ) -> c_int;
     pub fn memalign(align: size_t, size: size_t) -> *mut c_void;
     pub fn setgroups(ngroups: size_t, ptr: *const crate::gid_t) -> c_int;
     pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "statfs64")]
     pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatfs64")]
     pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int;
     pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "posix_fadvise64")]
     pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int;
     pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int;
     pub fn utimensat(
@@ -1895,7 +1970,9 @@
     ) -> size_t;
     pub fn strptime(s: *const c_char, format: *const c_char, tm: *mut crate::tm) -> *mut c_char;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "mkostemp64")]
     pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "mkostemps64")]
     pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int;
 
     pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/mod.rs
index b2de87e..433eeec9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/mod.rs
@@ -334,7 +334,13 @@
 pub const ATF_PUBL: c_int = 0x08;
 pub const ATF_USETRAILERS: c_int = 0x10;
 
-pub const FNM_PERIOD: c_int = 1 << 2;
+cfg_if! {
+    if #[cfg(target_os = "nto")] {
+        pub const FNM_PERIOD: c_int = 1 << 1;
+    } else {
+        pub const FNM_PERIOD: c_int = 1 << 2;
+    }
+}
 pub const FNM_NOMATCH: c_int = 1;
 
 cfg_if! {
@@ -351,11 +357,25 @@
         target_os = "freebsd",
         target_os = "android",
         target_os = "openbsd",
+        target_os = "cygwin",
     ))] {
         pub const FNM_PATHNAME: c_int = 1 << 1;
-        pub const FNM_NOESCAPE: c_int = 1 << 0;
     } else {
         pub const FNM_PATHNAME: c_int = 1 << 0;
+    }
+}
+
+cfg_if! {
+    if #[cfg(any(
+        target_os = "macos",
+        target_os = "freebsd",
+        target_os = "android",
+        target_os = "openbsd",
+    ))] {
+        pub const FNM_NOESCAPE: c_int = 1 << 0;
+    } else if #[cfg(target_os = "nto")] {
+        pub const FNM_NOESCAPE: c_int = 1 << 2;
+    } else {
         pub const FNM_NOESCAPE: c_int = 1 << 1;
     }
 }
@@ -538,11 +558,18 @@
     }
 }
 
+cfg_if! {
+    if #[cfg(not(target_env = "gnu"))] {
+        missing! {
+            #[cfg_attr(feature = "extra_traits", derive(Debug))]
+            pub enum fpos_t {} // FIXME(unix): fill this out with a struct
+        }
+    }
+}
+
 missing! {
     #[cfg_attr(feature = "extra_traits", derive(Debug))]
     pub enum FILE {}
-    #[cfg_attr(feature = "extra_traits", derive(Debug))]
-    pub enum fpos_t {} // FIXME(unix): fill this out with a struct
 }
 
 extern "C" {
@@ -577,17 +604,20 @@
         all(target_os = "macos", target_arch = "x86"),
         link_name = "fopen$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fopen64")]
     pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
         link_name = "freopen$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "freopen64")]
     pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE;
 
     pub fn fflush(file: *mut FILE) -> c_int;
     pub fn fclose(file: *mut FILE) -> c_int;
     pub fn remove(filename: *const c_char) -> c_int;
     pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "tmpfile64")]
     pub fn tmpfile() -> *mut FILE;
     pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int;
     pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
@@ -613,8 +643,10 @@
     pub fn ftell(stream: *mut FILE) -> c_long;
     pub fn rewind(stream: *mut FILE);
     #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fgetpos64")]
     pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int;
     #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fsetpos64")]
     pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int;
     pub fn feof(stream: *mut FILE) -> c_int;
     pub fn ferror(stream: *mut FILE) -> c_int;
@@ -826,6 +858,7 @@
         all(target_os = "freebsd", any(freebsd11, freebsd10)),
         link_name = "fstat@FBSD_1.0"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fstat64")]
     pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
 
     pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int;
@@ -839,6 +872,7 @@
         all(target_os = "freebsd", any(freebsd11, freebsd10)),
         link_name = "stat@FBSD_1.0"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "stat64")]
     pub fn stat(path: *const c_char, buf: *mut stat) -> c_int;
 
     pub fn pclose(stream: *mut crate::FILE) -> c_int;
@@ -853,16 +887,19 @@
         all(target_os = "macos", target_arch = "x86"),
         link_name = "open$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "open64")]
     pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
         link_name = "creat$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "creat64")]
     pub fn creat(path: *const c_char, mode: mode_t) -> c_int;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
         link_name = "fcntl$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "__fcntl_time64")]
     pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int;
 
     #[cfg_attr(
@@ -885,6 +922,7 @@
         all(target_os = "freebsd", any(freebsd11, freebsd10)),
         link_name = "readdir@FBSD_1.0"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "readdir64")]
     pub fn readdir(dirp: *mut crate::DIR) -> *mut crate::dirent;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
@@ -923,6 +961,7 @@
         all(target_os = "freebsd", any(freebsd11, freebsd10)),
         link_name = "fstatat@FBSD_1.1"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatat64")]
     pub fn fstatat(dirfd: c_int, pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int;
     pub fn linkat(
         olddirfd: c_int,
@@ -997,6 +1036,7 @@
     pub fn isatty(fd: c_int) -> c_int;
     #[cfg_attr(target_os = "solaris", link_name = "__link_xpg4")]
     pub fn link(src: *const c_char, dst: *const c_char) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "lseek64")]
     pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
     pub fn pathconf(path: *const c_char, name: c_int) -> c_long;
     pub fn pipe(fds: *mut c_int) -> c_int;
@@ -1059,11 +1099,13 @@
         all(target_os = "macos", target_arch = "x86"),
         link_name = "pread$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "pread64")]
     pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
         link_name = "pwrite$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "pwrite64")]
     pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t;
     pub fn umask(mask: mode_t) -> mode_t;
 
@@ -1090,6 +1132,7 @@
         all(target_os = "macos", target_arch = "x86"),
         link_name = "mmap$UNIX2003"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "mmap64")]
     pub fn mmap(
         addr: *mut c_void,
         len: size_t,
@@ -1116,6 +1159,7 @@
         all(target_os = "freebsd", any(freebsd11, freebsd10)),
         link_name = "lstat@FBSD_1.0"
     )]
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "lstat64")]
     pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int;
 
     #[cfg_attr(
@@ -1138,7 +1182,9 @@
 
     pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "truncate64")]
     pub fn truncate(path: *const c_char, length: off_t) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "ftruncate64")]
     pub fn ftruncate(fd: c_int, length: off_t) -> c_int;
 
     pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t;
@@ -1443,7 +1489,9 @@
     pub fn sem_wait(sem: *mut sem_t) -> c_int;
     pub fn sem_trywait(sem: *mut sem_t) -> c_int;
     pub fn sem_post(sem: *mut sem_t) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "statvfs64")]
     pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatvfs64")]
     pub fn fstatvfs(fd: c_int, buf: *mut statvfs) -> c_int;
 
     #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
@@ -1467,7 +1515,9 @@
 
     pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "fseeko64")]
     pub fn fseeko(stream: *mut crate::FILE, offset: off_t, whence: c_int) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "ftello64")]
     pub fn ftello(stream: *mut crate::FILE) -> off_t;
     #[cfg_attr(
         all(target_os = "macos", target_arch = "x86"),
@@ -1484,6 +1534,7 @@
     pub fn tcflush(fd: c_int, action: c_int) -> c_int;
     pub fn tcgetsid(fd: c_int) -> crate::pid_t;
     pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int;
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "mkstemp64")]
     pub fn mkstemp(template: *mut c_char) -> c_int;
     pub fn mkdtemp(template: *mut c_char) -> *mut c_char;
 
@@ -1508,6 +1559,7 @@
     pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
     pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t;
 
+    #[cfg_attr(gnu_file_offset_bits64, link_name = "lockf64")]
     pub fn lockf(fd: c_int, cmd: c_int, len: off_t) -> c_int;
 
 }
@@ -1608,6 +1660,7 @@
             pub fn pause() -> c_int;
 
             pub fn mkdirat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int;
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "openat64")]
             pub fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int, ...) -> c_int;
 
             #[cfg_attr(
@@ -1636,6 +1689,7 @@
             /// https://illumos.org/man/3lib/libc
             /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html
             /// https://www.unix.com/man-page/opensolaris/3LIB/libc/
+            #[cfg_attr(gnu_file_offset_bits64, link_name = "readdir64_r")]
             pub fn readdir_r(
                 dirp: *mut crate::DIR,
                 entry: *mut crate::dirent,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nto/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nto/mod.rs
index c1457d6..e0a1c9b 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nto/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nto/mod.rs
@@ -114,7 +114,7 @@
         pub imr_interface: in_addr,
     }
 
-    #[repr(packed)]
+    #[cfg_attr(any(target_env = "nto71", target_env = "nto70"), repr(packed))]
     pub struct in_addr {
         pub s_addr: crate::in_addr_t,
     }
@@ -125,6 +125,7 @@
         pub sa_data: [c_char; 14],
     }
 
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct sockaddr_in {
         pub sin_len: u8,
         pub sin_family: sa_family_t,
@@ -133,6 +134,15 @@
         pub sin_zero: [i8; 8],
     }
 
+    #[cfg(target_env = "nto71_iosock")]
+    pub struct sockaddr_in {
+        pub sin_len: u8,
+        pub sin_family: sa_family_t,
+        pub sin_port: crate::in_port_t,
+        pub sin_addr: crate::in_addr,
+        pub sin_zero: [c_char; 8],
+    }
+
     pub struct sockaddr_in6 {
         pub sin6_len: u8,
         pub sin6_family: sa_family_t,
@@ -234,6 +244,8 @@
         pub _Reserved: [*mut c_char; 8],
     }
 
+    // Does not exist in io-sock
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct in_pktinfo {
         pub ipi_addr: crate::in_addr,
         pub ipi_ifindex: c_uint,
@@ -255,7 +267,7 @@
         pub arp_flags: c_int,
     }
 
-    #[repr(packed)]
+    #[cfg_attr(any(target_env = "nto71", target_env = "nto70"), repr(packed))]
     pub struct arphdr {
         pub ar_hrd: u16,
         pub ar_pro: u16,
@@ -264,11 +276,18 @@
         pub ar_op: u16,
     }
 
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct mmsghdr {
         pub msg_hdr: crate::msghdr,
         pub msg_len: c_uint,
     }
 
+    #[cfg(target_env = "nto71_iosock")]
+    pub struct mmsghdr {
+        pub msg_hdr: crate::msghdr,
+        pub msg_len: ssize_t,
+    }
+
     #[repr(align(8))]
     pub struct siginfo_t {
         pub si_signo: c_int,
@@ -592,6 +611,7 @@
         pub bf_insns: *mut crate::bpf_insn,
     }
 
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct bpf_stat {
         pub bs_recv: u64,
         pub bs_drop: u64,
@@ -599,6 +619,12 @@
         bs_padding: [u64; 13],
     }
 
+    #[cfg(target_env = "nto71_iosock")]
+    pub struct bpf_stat {
+        pub bs_recv: c_uint,
+        pub bs_drop: c_uint,
+    }
+
     pub struct bpf_version {
         pub bv_major: c_ushort,
         pub bv_minor: c_ushort,
@@ -623,6 +649,8 @@
         pub bfl_list: *mut c_uint,
     }
 
+    // Does not exist in io-sock
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct unpcbid {
         pub unp_pid: crate::pid_t,
         pub unp_euid: crate::uid_t,
@@ -723,6 +751,7 @@
         msg_pad4: [c_long; 4],
     }
 
+    #[cfg(not(target_env = "nto71_iosock"))]
     pub struct sockaddr_dl {
         pub sdl_len: c_uchar,
         pub sdl_family: crate::sa_family_t,
@@ -734,6 +763,18 @@
         pub sdl_data: [c_char; 12],
     }
 
+    #[cfg(target_env = "nto71_iosock")]
+    pub struct sockaddr_dl {
+        pub sdl_len: c_uchar,
+        pub sdl_family: c_uchar,
+        pub sdl_index: c_ushort,
+        pub sdl_type: c_uchar,
+        pub sdl_nlen: c_uchar,
+        pub sdl_alen: c_uchar,
+        pub sdl_slen: c_uchar,
+        pub sdl_data: [c_char; 46],
+    }
+
     pub struct sync_t {
         __u: c_uint, // union
         pub __owner: c_uint,
@@ -1232,7 +1273,122 @@
 
 pub const SCM_RIGHTS: c_int = 0x01;
 pub const SCM_TIMESTAMP: c_int = 0x02;
-pub const SCM_CREDS: c_int = 0x04;
+cfg_if! {
+    if #[cfg(not(target_env = "nto71_iosock"))] {
+        pub const SCM_CREDS: c_int = 0x04;
+        pub const IFF_NOTRAILERS: c_int = 0x00000020;
+        pub const AF_INET6: c_int = 24;
+        pub const AF_BLUETOOTH: c_int = 31;
+        pub const pseudo_AF_KEY: c_int = 29;
+        pub const MSG_NOSIGNAL: c_int = 0x0800;
+        pub const MSG_WAITFORONE: c_int = 0x2000;
+        pub const IP_IPSEC_POLICY_COMPAT: c_int = 22;
+        pub const IP_PKTINFO: c_int = 25;
+        pub const IPPROTO_DIVERT: c_int = 259;
+        pub const IPV6_IPSEC_POLICY_COMPAT: c_int = 28;
+        pub const TCP_KEEPALIVE: c_int = 0x04;
+        pub const ARPHRD_ARCNET: u16 = 7;
+        pub const SO_BINDTODEVICE: c_int = 0x0800;
+        pub const EAI_NODATA: c_int = 7;
+        pub const IPTOS_ECN_NOT_ECT: u8 = 0x00;
+        pub const RTF_BROADCAST: u32 = 0x80000;
+        pub const UDP_ENCAP: c_int = 100;
+        pub const HW_IOSTATS: c_int = 9;
+        pub const HW_MACHINE_ARCH: c_int = 10;
+        pub const HW_ALIGNBYTES: c_int = 11;
+        pub const HW_CNMAGIC: c_int = 12;
+        pub const HW_PHYSMEM64: c_int = 13;
+        pub const HW_USERMEM64: c_int = 14;
+        pub const HW_IOSTATNAMES: c_int = 15;
+        pub const HW_MAXID: c_int = 15;
+        pub const CTL_UNSPEC: c_int = 0;
+        pub const CTL_QNX: c_int = 9;
+        pub const CTL_PROC: c_int = 10;
+        pub const CTL_VENDOR: c_int = 11;
+        pub const CTL_EMUL: c_int = 12;
+        pub const CTL_SECURITY: c_int = 13;
+        pub const CTL_MAXID: c_int = 14;
+        pub const AF_ARP: c_int = 28;
+        pub const AF_IEEE80211: c_int = 32;
+        pub const AF_NATM: c_int = 27;
+        pub const AF_NS: c_int = 6;
+        pub const BIOCGDLTLIST: c_int = -1072676233;
+        pub const BIOCGETIF: c_int = 1083196011;
+        pub const BIOCGSEESENT: c_int = 1074020984;
+        pub const BIOCGSTATS: c_int = 1082147439;
+        pub const BIOCSDLT: c_int = -2147204490;
+        pub const BIOCSETIF: c_int = -2138029460;
+        pub const BIOCSSEESENT: c_int = -2147204487;
+        pub const FIONSPACE: c_int = 1074030200;
+        pub const FIONWRITE: c_int = 1074030201;
+        pub const IFF_ACCEPTRTADV: c_int = 0x40000000;
+        pub const IFF_IP6FORWARDING: c_int = 0x20000000;
+        pub const IFF_SHIM: c_int = 0x80000000;
+        pub const KERN_ARND: c_int = 81;
+        pub const KERN_IOV_MAX: c_int = 38;
+        pub const KERN_LOGSIGEXIT: c_int = 46;
+        pub const KERN_MAXID: c_int = 83;
+        pub const KERN_PROC_ARGS: c_int = 48;
+        pub const KERN_PROC_ENV: c_int = 3;
+        pub const KERN_PROC_GID: c_int = 7;
+        pub const KERN_PROC_RGID: c_int = 8;
+        pub const LOCAL_CONNWAIT: c_int = 0x0002;
+        pub const LOCAL_CREDS: c_int = 0x0001;
+        pub const LOCAL_PEEREID: c_int = 0x0003;
+        pub const MSG_NOTIFICATION: c_int = 0x0400;
+        pub const NET_RT_IFLIST: c_int = 4;
+        pub const NI_NUMERICSCOPE: c_int = 0x00000040;
+        pub const PF_ARP: c_int = 28;
+        pub const PF_NATM: c_int = 27;
+        pub const pseudo_AF_HDRCMPLT: c_int = 30;
+        pub const SIOCGIFADDR: c_int = -1064277727;
+        pub const SO_FIB: c_int = 0x100a;
+        pub const SO_TXPRIO: c_int = 0x100b;
+        pub const SO_SETFIB: c_int = 0x100a;
+        pub const SO_VLANPRIO: c_int = 0x100c;
+        pub const USER_ATEXIT_MAX: c_int = 21;
+        pub const USER_MAXID: c_int = 22;
+        pub const SO_OVERFLOWED: c_int = 0x1009;
+    } else {
+        pub const SCM_CREDS: c_int = 0x03;
+        pub const AF_INET6: c_int = 28;
+        pub const AF_BLUETOOTH: c_int = 36;
+        pub const pseudo_AF_KEY: c_int = 27;
+        pub const MSG_NOSIGNAL: c_int = 0x20000;
+        pub const MSG_WAITFORONE: c_int = 0x00080000;
+        pub const IPPROTO_DIVERT: c_int = 258;
+        pub const RTF_BROADCAST: u32 = 0x400000;
+        pub const UDP_ENCAP: c_int = 1;
+        pub const HW_MACHINE_ARCH: c_int = 11;
+        pub const AF_ARP: c_int = 35;
+        pub const AF_IEEE80211: c_int = 37;
+        pub const AF_NATM: c_int = 29;
+        pub const BIOCGDLTLIST: c_ulong = 0xffffffffc0104279;
+        pub const BIOCGETIF: c_int = 0x4020426b;
+        pub const BIOCGSEESENT: c_int = 0x40044276;
+        pub const BIOCGSTATS: c_int = 0x4008426f;
+        pub const BIOCSDLT: c_int = 0x80044278;
+        pub const BIOCSETIF: c_int = 0x8020426c;
+        pub const BIOCSSEESENT: c_int = 0x80044277;
+        pub const KERN_ARND: c_int = 37;
+        pub const KERN_IOV_MAX: c_int = 35;
+        pub const KERN_LOGSIGEXIT: c_int = 34;
+        pub const KERN_PROC_ARGS: c_int = 7;
+        pub const KERN_PROC_ENV: c_int = 35;
+        pub const KERN_PROC_GID: c_int = 11;
+        pub const KERN_PROC_RGID: c_int = 10;
+        pub const LOCAL_CONNWAIT: c_int = 4;
+        pub const LOCAL_CREDS: c_int = 2;
+        pub const MSG_NOTIFICATION: c_int = 0x00002000;
+        pub const NET_RT_IFLIST: c_int = 3;
+        pub const NI_NUMERICSCOPE: c_int = 0x00000020;
+        pub const PF_ARP: c_int = AF_ARP;
+        pub const PF_NATM: c_int = AF_NATM;
+        pub const pseudo_AF_HDRCMPLT: c_int = 31;
+        pub const SIOCGIFADDR: c_int = 0xc0206921;
+        pub const SO_SETFIB: c_int = 0x1014;
+    }
+}
 
 pub const MAP_TYPE: c_int = 0x3;
 
@@ -1241,7 +1397,6 @@
 pub const IFF_DEBUG: c_int = 0x00000004;
 pub const IFF_LOOPBACK: c_int = 0x00000008;
 pub const IFF_POINTOPOINT: c_int = 0x00000010;
-pub const IFF_NOTRAILERS: c_int = 0x00000020;
 pub const IFF_RUNNING: c_int = 0x00000040;
 pub const IFF_NOARP: c_int = 0x00000080;
 pub const IFF_PROMISC: c_int = 0x00000100;
@@ -1254,10 +1409,9 @@
 pub const AF_INET: c_int = 2;
 pub const AF_IPX: c_int = 23;
 pub const AF_APPLETALK: c_int = 16;
-pub const AF_INET6: c_int = 24;
 pub const AF_ROUTE: c_int = 17;
 pub const AF_SNA: c_int = 11;
-pub const AF_BLUETOOTH: c_int = 31;
+
 pub const AF_ISDN: c_int = 26;
 
 pub const PF_UNSPEC: c_int = AF_UNSPEC;
@@ -1267,7 +1421,6 @@
 pub const PF_IPX: c_int = AF_IPX;
 pub const PF_APPLETALK: c_int = AF_APPLETALK;
 pub const PF_INET6: c_int = AF_INET6;
-pub const pseudo_AF_KEY: c_int = 29;
 pub const PF_KEY: c_int = pseudo_AF_KEY;
 pub const PF_ROUTE: c_int = AF_ROUTE;
 pub const PF_SNA: c_int = AF_SNA;
@@ -1285,8 +1438,6 @@
 pub const MSG_DONTWAIT: c_int = 0x0080;
 pub const MSG_EOR: c_int = 0x0008;
 pub const MSG_WAITALL: c_int = 0x0040;
-pub const MSG_NOSIGNAL: c_int = 0x0800;
-pub const MSG_WAITFORONE: c_int = 0x2000;
 
 pub const IP_TOS: c_int = 3;
 pub const IP_TTL: c_int = 4;
@@ -1294,8 +1445,6 @@
 pub const IP_OPTIONS: c_int = 1;
 pub const IP_RECVOPTS: c_int = 5;
 pub const IP_RETOPTS: c_int = 8;
-pub const IP_PKTINFO: c_int = 25;
-pub const IP_IPSEC_POLICY_COMPAT: c_int = 22;
 pub const IP_MULTICAST_IF: c_int = 9;
 pub const IP_MULTICAST_TTL: c_int = 10;
 pub const IP_MULTICAST_LOOP: c_int = 11;
@@ -1325,7 +1474,6 @@
 pub const IPPROTO_RAW: c_int = 255;
 pub const IPPROTO_MAX: c_int = 256;
 pub const IPPROTO_CARP: c_int = 112;
-pub const IPPROTO_DIVERT: c_int = 259;
 pub const IPPROTO_DONE: c_int = 257;
 pub const IPPROTO_EON: c_int = 80;
 pub const IPPROTO_ETHERIP: c_int = 97;
@@ -1343,7 +1491,6 @@
 pub const IPV6_LEAVE_GROUP: c_int = 13;
 pub const IPV6_CHECKSUM: c_int = 26;
 pub const IPV6_V6ONLY: c_int = 27;
-pub const IPV6_IPSEC_POLICY_COMPAT: c_int = 28;
 pub const IPV6_RTHDRDSTOPTS: c_int = 35;
 pub const IPV6_RECVPKTINFO: c_int = 36;
 pub const IPV6_RECVHOPLIMIT: c_int = 37;
@@ -1364,7 +1511,6 @@
 pub const TCP_NODELAY: c_int = 0x01;
 pub const TCP_MAXSEG: c_int = 0x02;
 pub const TCP_MD5SIG: c_int = 0x10;
-pub const TCP_KEEPALIVE: c_int = 0x04;
 
 pub const SHUT_RD: c_int = 0;
 pub const SHUT_WR: c_int = 1;
@@ -1514,7 +1660,6 @@
 
 pub const ARPHRD_ETHER: u16 = 1;
 pub const ARPHRD_IEEE802: u16 = 6;
-pub const ARPHRD_ARCNET: u16 = 7;
 pub const ARPHRD_IEEE1394: u16 = 24;
 
 pub const SOL_SOCKET: c_int = 0xffff;
@@ -1535,7 +1680,6 @@
 pub const SO_SNDLOWAT: c_int = 0x1003;
 pub const SO_RCVTIMEO: c_int = 0x1006;
 pub const SO_SNDTIMEO: c_int = 0x1005;
-pub const SO_BINDTODEVICE: c_int = 0x0800;
 pub const SO_TIMESTAMP: c_int = 0x0400;
 pub const SO_ACCEPTCONN: c_int = 0x0002;
 
@@ -1581,7 +1725,6 @@
 pub const EAI_NONAME: c_int = 8;
 pub const EAI_AGAIN: c_int = 2;
 pub const EAI_FAIL: c_int = 4;
-pub const EAI_NODATA: c_int = 7;
 pub const EAI_FAMILY: c_int = 5;
 pub const EAI_SOCKTYPE: c_int = 10;
 pub const EAI_SERVICE: c_int = 9;
@@ -1616,8 +1759,6 @@
 pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x00000400;
 pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x00000040;
 
-pub const IPTOS_ECN_NOT_ECT: u8 = 0x00;
-
 pub const RTF_UP: c_ushort = 0x0001;
 pub const RTF_GATEWAY: c_ushort = 0x0002;
 
@@ -1627,14 +1768,11 @@
 pub const RTF_REJECT: c_ushort = 0x0008;
 pub const RTF_STATIC: c_ushort = 0x0800;
 pub const RTF_XRESOLVE: c_ushort = 0x0200;
-pub const RTF_BROADCAST: u32 = 0x80000;
 pub const RTM_NEWADDR: u16 = 0xc;
 pub const RTM_DELADDR: u16 = 0xd;
 pub const RTA_DST: c_ushort = 0x1;
 pub const RTA_GATEWAY: c_ushort = 0x2;
 
-pub const UDP_ENCAP: c_int = 100;
-
 pub const IN_ACCESS: u32 = 0x00000001;
 pub const IN_MODIFY: u32 = 0x00000002;
 pub const IN_ATTRIB: u32 = 0x00000004;
@@ -2268,16 +2406,6 @@
 pub const HW_USERMEM: c_int = 6;
 pub const HW_PAGESIZE: c_int = 7;
 pub const HW_DISKNAMES: c_int = 8;
-pub const HW_IOSTATS: c_int = 9;
-pub const HW_MACHINE_ARCH: c_int = 10;
-pub const HW_ALIGNBYTES: c_int = 11;
-pub const HW_CNMAGIC: c_int = 12;
-pub const HW_PHYSMEM64: c_int = 13;
-pub const HW_USERMEM64: c_int = 14;
-pub const HW_IOSTATNAMES: c_int = 15;
-pub const HW_MAXID: c_int = 15;
-
-pub const CTL_UNSPEC: c_int = 0;
 pub const CTL_KERN: c_int = 1;
 pub const CTL_VM: c_int = 2;
 pub const CTL_VFS: c_int = 3;
@@ -2286,12 +2414,6 @@
 pub const CTL_HW: c_int = 6;
 pub const CTL_MACHDEP: c_int = 7;
 pub const CTL_USER: c_int = 8;
-pub const CTL_QNX: c_int = 9;
-pub const CTL_PROC: c_int = 10;
-pub const CTL_VENDOR: c_int = 11;
-pub const CTL_EMUL: c_int = 12;
-pub const CTL_SECURITY: c_int = 13;
-pub const CTL_MAXID: c_int = 14;
 
 pub const DAY_1: crate::nl_item = 8;
 pub const DAY_2: crate::nl_item = 9;
@@ -2335,7 +2457,6 @@
 pub const ABMON_11: crate::nl_item = 44;
 pub const ABMON_12: crate::nl_item = 45;
 
-pub const AF_ARP: c_int = 28;
 pub const AF_CCITT: c_int = 10;
 pub const AF_CHAOS: c_int = 5;
 pub const AF_CNT: c_int = 21;
@@ -2346,13 +2467,10 @@
 pub const AF_E164: c_int = 26;
 pub const AF_ECMA: c_int = 8;
 pub const AF_HYLINK: c_int = 15;
-pub const AF_IEEE80211: c_int = 32;
 pub const AF_IMPLINK: c_int = 3;
 pub const AF_ISO: c_int = 7;
 pub const AF_LAT: c_int = 14;
 pub const AF_LINK: c_int = 18;
-pub const AF_NATM: c_int = 27;
-pub const AF_NS: c_int = 6;
 pub const AF_OSI: c_int = 7;
 pub const AF_PUP: c_int = 4;
 pub const ALT_DIGITS: crate::nl_item = 50;
@@ -2362,21 +2480,14 @@
 pub const BIOCFLUSH: c_int = 17000;
 pub const BIOCGBLEN: c_int = 1074020966;
 pub const BIOCGDLT: c_int = 1074020970;
-pub const BIOCGDLTLIST: c_int = -1072676233;
-pub const BIOCGETIF: c_int = 1083196011;
 pub const BIOCGHDRCMPLT: c_int = 1074020980;
 pub const BIOCGRTIMEOUT: c_int = 1074807406;
-pub const BIOCGSEESENT: c_int = 1074020984;
-pub const BIOCGSTATS: c_int = 1082147439;
 pub const BIOCIMMEDIATE: c_int = -2147204496;
 pub const BIOCPROMISC: c_int = 17001;
 pub const BIOCSBLEN: c_int = -1073462682;
-pub const BIOCSDLT: c_int = -2147204490;
 pub const BIOCSETF: c_int = -2146418073;
-pub const BIOCSETIF: c_int = -2138029460;
 pub const BIOCSHDRCMPLT: c_int = -2147204491;
 pub const BIOCSRTIMEOUT: c_int = -2146418067;
-pub const BIOCSSEESENT: c_int = -2147204487;
 pub const BIOCVERSION: c_int = 1074020977;
 
 pub const BPF_ALIGNMENT: usize = mem::size_of::<c_long>();
@@ -2412,18 +2523,13 @@
 pub const FIOGETOWN: c_int = 1074030203;
 pub const FIONCLEX: c_int = 26114;
 pub const FIONREAD: c_int = 1074030207;
-pub const FIONSPACE: c_int = 1074030200;
-pub const FIONWRITE: c_int = 1074030201;
 pub const FIOSETOWN: c_int = -2147195268;
 
 pub const F_SETOWN: c_int = 36;
-pub const IFF_ACCEPTRTADV: c_int = 0x40000000;
-pub const IFF_IP6FORWARDING: c_int = 0x20000000;
 pub const IFF_LINK0: c_int = 0x00001000;
 pub const IFF_LINK1: c_int = 0x00002000;
 pub const IFF_LINK2: c_int = 0x00004000;
 pub const IFF_OACTIVE: c_int = 0x00000400;
-pub const IFF_SHIM: c_int = 0x80000000;
 pub const IFF_SIMPLEX: c_int = 0x00000800;
 pub const IHFLOW: tcflag_t = 0x00000001;
 pub const IIDLE: tcflag_t = 0x00000008;
@@ -2434,17 +2540,13 @@
 pub const IUTF8: tcflag_t = 0x0004000;
 
 pub const KERN_ARGMAX: c_int = 8;
-pub const KERN_ARND: c_int = 81;
 pub const KERN_BOOTTIME: c_int = 21;
 pub const KERN_CLOCKRATE: c_int = 12;
 pub const KERN_FILE: c_int = 15;
 pub const KERN_HOSTID: c_int = 11;
 pub const KERN_HOSTNAME: c_int = 10;
-pub const KERN_IOV_MAX: c_int = 38;
 pub const KERN_JOB_CONTROL: c_int = 19;
-pub const KERN_LOGSIGEXIT: c_int = 46;
 pub const KERN_MAXFILES: c_int = 7;
-pub const KERN_MAXID: c_int = 83;
 pub const KERN_MAXPROC: c_int = 6;
 pub const KERN_MAXVNODES: c_int = 5;
 pub const KERN_NGROUPS: c_int = 18;
@@ -2454,12 +2556,8 @@
 pub const KERN_POSIX1: c_int = 17;
 pub const KERN_PROC: c_int = 14;
 pub const KERN_PROC_ALL: c_int = 0;
-pub const KERN_PROC_ARGS: c_int = 48;
-pub const KERN_PROC_ENV: c_int = 3;
-pub const KERN_PROC_GID: c_int = 7;
 pub const KERN_PROC_PGRP: c_int = 2;
 pub const KERN_PROC_PID: c_int = 1;
-pub const KERN_PROC_RGID: c_int = 8;
 pub const KERN_PROC_RUID: c_int = 6;
 pub const KERN_PROC_SESSION: c_int = 3;
 pub const KERN_PROC_TTY: c_int = 4;
@@ -2478,25 +2576,16 @@
 pub const LC_NUMERIC: c_int = 8;
 pub const LC_TIME: c_int = 16;
 
-pub const LOCAL_CONNWAIT: c_int = 0x0002;
-pub const LOCAL_CREDS: c_int = 0x0001;
-pub const LOCAL_PEEREID: c_int = 0x0003;
-
 pub const MAP_STACK: c_int = 0x00001000;
 pub const MNT_NOEXEC: c_int = 0x02;
 pub const MNT_NOSUID: c_int = 0x04;
 pub const MNT_RDONLY: c_int = 0x01;
 
-pub const MSG_NOTIFICATION: c_int = 0x0400;
-
 pub const NET_RT_DUMP: c_int = 1;
 pub const NET_RT_FLAGS: c_int = 2;
-pub const NET_RT_IFLIST: c_int = 4;
-pub const NI_NUMERICSCOPE: c_int = 0x00000040;
 pub const OHFLOW: tcflag_t = 0x00000002;
 pub const P_ALL: idtype_t = 0;
 pub const PARSTK: tcflag_t = 0x00000004;
-pub const PF_ARP: c_int = 28;
 pub const PF_CCITT: c_int = 10;
 pub const PF_CHAOS: c_int = 5;
 pub const PF_CNT: c_int = 21;
@@ -2510,7 +2599,6 @@
 pub const PF_ISO: c_int = 7;
 pub const PF_LAT: c_int = 14;
 pub const PF_LINK: c_int = 18;
-pub const PF_NATM: c_int = 27;
 pub const PF_OSI: c_int = 7;
 pub const PF_PIP: c_int = 25;
 pub const PF_PUP: c_int = 4;
@@ -2528,7 +2616,6 @@
 pub const PRIO_PGRP: c_int = 1;
 pub const PRIO_PROCESS: c_int = 0;
 pub const PRIO_USER: c_int = 2;
-pub const pseudo_AF_HDRCMPLT: c_int = 30;
 pub const pseudo_AF_PIP: c_int = 25;
 pub const pseudo_AF_RTIP: c_int = 22;
 pub const pseudo_AF_XTP: c_int = 19;
@@ -2573,13 +2660,7 @@
 pub const SIGEV_NONE: c_int = 0;
 pub const SIGEV_SIGNAL: c_int = 129;
 pub const SIGEV_THREAD: c_int = 135;
-pub const SIOCGIFADDR: c_int = -1064277727;
-pub const SO_FIB: c_int = 0x100a;
-pub const SO_OVERFLOWED: c_int = 0x1009;
-pub const SO_SETFIB: c_int = 0x100a;
-pub const SO_TXPRIO: c_int = 0x100b;
 pub const SO_USELOOPBACK: c_int = 0x0040;
-pub const SO_VLANPRIO: c_int = 0x100c;
 pub const _SS_ALIGNSIZE: usize = mem::size_of::<i64>();
 pub const _SS_MAXSIZE: usize = 128;
 pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - 2;
@@ -2649,8 +2730,6 @@
 pub const USER_POSIX2_UPE: c_int = 18;
 pub const USER_STREAM_MAX: c_int = 19;
 pub const USER_TZNAME_MAX: c_int = 20;
-pub const USER_ATEXIT_MAX: c_int = 21;
-pub const USER_MAXID: c_int = 22;
 
 pub const VDOWN: usize = 31;
 pub const VINS: usize = 32;
@@ -2856,6 +2935,42 @@
     }
 }
 
+cfg_if! {
+    if #[cfg(not(target_env = "nto71_iosock"))] {
+        extern "C" {
+            pub fn sendmmsg(
+                sockfd: c_int,
+                msgvec: *mut crate::mmsghdr,
+                vlen: c_uint,
+                flags: c_uint,
+            ) -> c_int;
+            pub fn recvmmsg(
+                sockfd: c_int,
+                msgvec: *mut crate::mmsghdr,
+                vlen: c_uint,
+                flags: c_uint,
+                timeout: *mut crate::timespec,
+            ) -> c_int;
+        }
+    } else {
+        extern "C" {
+            pub fn sendmmsg(
+                sockfd: c_int,
+                msgvec: *mut crate::mmsghdr,
+                vlen: size_t,
+                flags: c_int,
+            ) -> ssize_t;
+            pub fn recvmmsg(
+                sockfd: c_int,
+                msgvec: *mut crate::mmsghdr,
+                vlen: size_t,
+                flags: c_int,
+                timeout: *const crate::timespec,
+            ) -> ssize_t;
+        }
+    }
+}
+
 // Network related functions are provided by libsocket and regex
 // functions are provided by libregex.
 // In QNX <=7.0, libregex functions were included in libc itself.
@@ -3277,20 +3392,6 @@
         flags: c_int,
     ) -> c_int;
 
-    pub fn sendmmsg(
-        sockfd: c_int,
-        msgvec: *mut crate::mmsghdr,
-        vlen: c_uint,
-        flags: c_uint,
-    ) -> c_int;
-    pub fn recvmmsg(
-        sockfd: c_int,
-        msgvec: *mut crate::mmsghdr,
-        vlen: c_uint,
-        flags: c_uint,
-        timeout: *mut crate::timespec,
-    ) -> c_int;
-
     pub fn mallopt(param: c_int, value: i64) -> c_int;
     pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nuttx/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nuttx/mod.rs
index 8446eaf..015a2ba 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nuttx/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/nuttx/mod.rs
@@ -517,7 +517,39 @@
 pub const _SC_GETPW_R_SIZE_MAX: i32 = 0x25;
 
 // signal.h
-pub const SIGPIPE: i32 = 13;
+pub const SIGHUP: c_int = 1;
+pub const SIGINT: c_int = 2;
+pub const SIGQUIT: c_int = 3;
+pub const SIGILL: c_int = 4;
+pub const SIGTRAP: c_int = 5;
+pub const SIGABRT: c_int = 6;
+pub const SIGIOT: c_int = 6;
+pub const SIGBUS: c_int = 7;
+pub const SIGFPE: c_int = 8;
+pub const SIGKILL: c_int = 9;
+pub const SIGUSR1: c_int = 10;
+pub const SIGSEGV: c_int = 11;
+pub const SIGUSR2: c_int = 12;
+pub const SIGPIPE: c_int = 13;
+pub const SIGALRM: c_int = 14;
+pub const SIGTERM: c_int = 15;
+pub const SIGSTKFLT: c_int = 16;
+pub const SIGCHLD: c_int = 17;
+pub const SIGCONT: c_int = 18;
+pub const SIGSTOP: c_int = 19;
+pub const SIGTSTP: c_int = 20;
+pub const SIGTTIN: c_int = 21;
+pub const SIGTTOU: c_int = 22;
+pub const SIGURG: c_int = 23;
+pub const SIGXCPU: c_int = 24;
+pub const SIGXFSZ: c_int = 25;
+pub const SIGVTALRM: c_int = 26;
+pub const SIGPROF: c_int = 27;
+pub const SIGWINCH: c_int = 28;
+pub const SIGIO: c_int = 29;
+pub const SIGPOLL: c_int = SIGIO;
+pub const SIGPWR: c_int = 30;
+pub const SIGSYS: c_int = 31;
 
 // pthread.h
 pub const PTHREAD_MUTEX_NORMAL: i32 = 0;
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/redox/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/redox/mod.rs
index c453f83e..d7ed748 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/redox/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/redox/mod.rs
@@ -131,6 +131,22 @@
         pub thousands_sep: *const c_char,
     }
 
+    pub struct msghdr {
+        pub msg_name: *mut c_void,
+        pub msg_namelen: crate::socklen_t,
+        pub msg_iov: *mut crate::iovec,
+        pub msg_iovlen: size_t,
+        pub msg_control: *mut c_void,
+        pub msg_controllen: size_t,
+        pub msg_flags: c_int,
+    }
+
+    pub struct cmsghdr {
+        pub cmsg_len: size_t,
+        pub cmsg_level: c_int,
+        pub cmsg_type: c_int,
+    }
+
     pub struct passwd {
         pub pw_name: *mut c_char,
         pub pw_passwd: *mut c_char,
@@ -1212,6 +1228,12 @@
     pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int;
 
     // sys/socket.h
+    pub fn CMSG_ALIGN(len: size_t) -> size_t;
+    pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar;
+    pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr;
+    pub fn CMSG_LEN(len: c_uint) -> c_uint;
+    pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr;
+    pub fn CMSG_SPACE(len: c_uint) -> c_uint;
     pub fn bind(
         socket: c_int,
         address: *const crate::sockaddr,
@@ -1225,11 +1247,33 @@
         addr: *mut crate::sockaddr,
         addrlen: *mut crate::socklen_t,
     ) -> ssize_t;
+    pub fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t;
+    pub fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t;
+    pub fn sendto(
+        socket: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+        addr: *const crate::sockaddr,
+        addrlen: crate::socklen_t,
+    ) -> ssize_t;
 
     // sys/stat.h
     pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int;
 
     // sys/uio.h
+    pub fn preadv(
+        fd: c_int,
+        iov: *const crate::iovec,
+        iovcnt: c_int,
+        offset: off_t,
+    ) -> ssize_t;
+    pub fn pwritev(
+        fd: c_int,
+        iov: *const crate::iovec,
+        iovcnt: c_int,
+        offset: off_t,
+    ) -> ssize_t;
     pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t;
     pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t;
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/compat.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/compat.rs
index 8fd1c750..649d6ac 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/compat.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/compat.rs
@@ -53,6 +53,7 @@
     return -1;
 }
 
+#[cfg(target_os = "illumos")]
 pub unsafe fn openpty(
     amain: *mut c_int,
     asubord: *mut c_int,
@@ -123,6 +124,7 @@
     0
 }
 
+#[cfg(target_os = "illumos")]
 pub unsafe fn forkpty(
     amain: *mut c_int,
     name: *mut c_char,
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/illumos.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/illumos.rs
index caa3f27b..3cb68e4 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/illumos.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/illumos.rs
@@ -286,6 +286,12 @@
 // sys/systeminfo.h
 pub const SI_ADDRESS_WIDTH: c_int = 520;
 
+// sys/timerfd.h
+pub const TFD_CLOEXEC: i32 = 0o2000000;
+pub const TFD_NONBLOCK: i32 = 0o4000;
+pub const TFD_TIMER_ABSTIME: i32 = 1 << 0;
+pub const TFD_TIMER_CANCEL_ON_SET: i32 = 1 << 1;
+
 extern "C" {
     pub fn eventfd(init: c_uint, flags: c_int) -> c_int;
 
@@ -353,4 +359,13 @@
         n: size_t,
         loc: crate::locale_t,
     ) -> c_int;
+
+    pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int;
+    pub fn timerfd_gettime(fd: c_int, curr_value: *mut crate::itimerspec) -> c_int;
+    pub fn timerfd_settime(
+        fd: c_int,
+        flags: c_int,
+        new_value: *const crate::itimerspec,
+        old_value: *mut crate::itimerspec,
+    ) -> c_int;
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/mod.rs
index 65aacce..3ddde8d 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/mod.rs
@@ -3201,6 +3201,8 @@
     pub fn arc4random() -> u32;
     pub fn arc4random_buf(buf: *mut c_void, nbytes: size_t);
     pub fn arc4random_uniform(upper_bound: u32) -> u32;
+
+    pub fn secure_getenv(name: *const c_char) -> *mut c_char;
 }
 
 #[link(name = "sendfile")]
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/solaris.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/solaris.rs
index d030408..7baa8a1 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/solaris.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/unix/solarish/solaris.rs
@@ -1,7 +1,7 @@
 use crate::prelude::*;
 use crate::{
-    exit_status, off_t, NET_MAC_AWARE, NET_MAC_AWARE_INHERIT, PRIV_AWARE_RESET, PRIV_DEBUG,
-    PRIV_PFEXEC, PRIV_XPOLICY,
+    exit_status, off_t, termios, NET_MAC_AWARE, NET_MAC_AWARE_INHERIT, PRIV_AWARE_RESET,
+    PRIV_DEBUG, PRIV_PFEXEC, PRIV_XPOLICY,
 };
 
 pub type door_attr_t = c_uint;
@@ -161,6 +161,14 @@
     }
 }
 
+// FIXME(solaris): O_DIRECT and SIGINFO are NOT available on Solaris.
+// But in past they were defined here and thus other crates expected them.
+// Latest version v0.29.0 of Nix crate still expects this. Since last
+// version of Nix crate is almost one year ago let's define these two
+// temporarily before new Nix version is released.
+pub const O_DIRECT: c_int = 0x2000000;
+pub const SIGINFO: c_int = 41;
+
 pub const _UTMP_USER_LEN: usize = 32;
 pub const _UTMP_LINE_LEN: usize = 32;
 pub const _UTMP_ID_LEN: usize = 4;
@@ -234,4 +242,19 @@
     pub fn pthread_getattr_np(thread: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int;
 
     pub fn euidaccess(path: *const c_char, amode: c_int) -> c_int;
+
+    pub fn openpty(
+        amain: *mut c_int,
+        asubord: *mut c_int,
+        name: *mut c_char,
+        termp: *mut termios,
+        winp: *mut crate::winsize,
+    ) -> c_int;
+
+    pub fn forkpty(
+        amain: *mut c_int,
+        name: *mut c_char,
+        termp: *mut termios,
+        winp: *mut crate::winsize,
+    ) -> crate::pid_t;
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/vxworks/mod.rs b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/vxworks/mod.rs
index 073b5d0..3a44adc 100644
--- a/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/vxworks/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libc-v0_2/src/vxworks/mod.rs
@@ -410,6 +410,7 @@
     pub struct dirent {
         pub d_ino: crate::ino_t,
         pub d_name: [c_char; _PARM_NAME_MAX as usize + 1],
+        pub d_type: c_uchar,
     }
 
     pub struct sockaddr_un {
@@ -458,6 +459,7 @@
                 f.debug_struct("dirent")
                     .field("d_ino", &self.d_ino)
                     .field("d_name", &&self.d_name[..])
+                    .field("d_type", &self.d_type)
                     .finish()
             }
         }
@@ -620,6 +622,9 @@
 pub const ENOTDIR: c_int = 20;
 pub const EISDIR: c_int = 21;
 pub const EINVAL: c_int = 22;
+pub const ENFILE: c_int = 23;
+pub const EMFILE: c_int = 24;
+pub const ENOTTY: c_int = 25;
 pub const ENAMETOOLONG: c_int = 26;
 pub const EFBIG: c_int = 27;
 pub const ENOSPC: c_int = 28;
@@ -628,7 +633,12 @@
 pub const EMLINK: c_int = 31;
 pub const EPIPE: c_int = 32;
 pub const EDEADLK: c_int = 33;
+pub const ENOLCK: c_int = 34;
+pub const ENOTSUP: c_int = 35;
+pub const EMSGSIZE: c_int = 36;
+pub const EDOM: c_int = 37;
 pub const ERANGE: c_int = 38;
+pub const EDOOM: c_int = 39;
 pub const EDESTADDRREQ: c_int = 40;
 pub const EPROTOTYPE: c_int = 41;
 pub const ENOPROTOOPT: c_int = 42;
@@ -655,12 +665,30 @@
 pub const ETXTBSY: c_int = 63;
 pub const ELOOP: c_int = 64;
 pub const EHOSTUNREACH: c_int = 65;
+pub const ENOTBLK: c_int = 66;
+pub const EHOSTDOWN: c_int = 67;
 pub const EINPROGRESS: c_int = 68;
 pub const EALREADY: c_int = 69;
 pub const EWOULDBLOCK: c_int = 70;
 pub const ENOSYS: c_int = 71;
+pub const ECANCELED: c_int = 72;
+pub const ENOSR: c_int = 74;
+pub const ENOSTR: c_int = 75;
+pub const EPROTO: c_int = 76;
+pub const EBADMSG: c_int = 77;
+pub const ENODATA: c_int = 78;
+pub const ETIME: c_int = 79;
+pub const ENOMSG: c_int = 80;
+pub const EFPOS: c_int = 81;
+pub const EILSEQ: c_int = 82;
 pub const EDQUOT: c_int = 83;
+pub const EIDRM: c_int = 84;
+pub const EOVERFLOW: c_int = 85;
+pub const EMULTIHOP: c_int = 86;
+pub const ENOLINK: c_int = 87;
 pub const ESTALE: c_int = 88;
+pub const EOWNERDEAD: c_int = 89;
+pub const ENOTRECOVERABLE: c_int = 90;
 
 // NFS errnos: Refer to pkgs_v2/storage/fs/nfs/h/nfs/nfsCommon.h
 const M_nfsStat: c_int = 48 << 16;
@@ -941,11 +969,34 @@
 pub const SIGCHLD: c_int = 20;
 pub const SIGTTIN: c_int = 21;
 pub const SIGTTOU: c_int = 22;
+pub const SIGUSR1: c_int = 30;
+pub const SIGUSR2: c_int = 31;
+pub const SIGPOLL: c_int = 32;
+pub const SIGPROF: c_int = 33;
+pub const SIGSYS: c_int = 34;
+pub const SIGURG: c_int = 35;
+pub const SIGVTALRM: c_int = 36;
+pub const SIGXCPU: c_int = 37;
+pub const SIGXFSZ: c_int = 38;
+pub const SIGRTMIN: c_int = 48;
+
+pub const SIGIO: c_int = SIGRTMIN;
+pub const SIGWINCH: c_int = SIGRTMIN + 5;
+pub const SIGLOST: c_int = SIGRTMIN + 6;
 
 pub const SIG_BLOCK: c_int = 1;
 pub const SIG_UNBLOCK: c_int = 2;
 pub const SIG_SETMASK: c_int = 3;
 
+pub const SA_NOCLDSTOP: c_int = 0x0001;
+pub const SA_SIGINFO: c_int = 0x0002;
+pub const SA_ONSTACK: c_int = 0x0004;
+pub const SA_INTERRUPT: c_int = 0x0008;
+pub const SA_RESETHAND: c_int = 0x0010;
+pub const SA_RESTART: c_int = 0x0020;
+pub const SA_NODEFER: c_int = 0x0040;
+pub const SA_NOCLDWAIT: c_int = 0x0080;
+
 pub const SI_SYNC: c_int = 0;
 pub const SI_USER: c_int = -1;
 pub const SI_QUEUE: c_int = -2;
@@ -1231,6 +1282,7 @@
     pub fn umask(mask: mode_t) -> mode_t;
     pub fn mlock(addr: *const c_void, len: size_t) -> c_int;
     pub fn mlockall(flags: c_int) -> c_int;
+    pub fn munlock(addr: *const c_void, len: size_t) -> c_int;
     pub fn munlockall() -> c_int;
 
     pub fn mmap(
@@ -1242,6 +1294,10 @@
         offset: off_t,
     ) -> *mut c_void;
     pub fn munmap(addr: *mut c_void, len: size_t) -> c_int;
+
+    pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int;
+    pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int;
+
     pub fn truncate(path: *const c_char, length: off_t) -> c_int;
     pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int;
     pub fn shm_unlink(name: *const c_char) -> c_int;
@@ -1258,6 +1314,8 @@
 
     pub fn utimes(filename: *const c_char, times: *const crate::timeval) -> c_int;
 
+    pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int;
+
     #[link_name = "_rtld_dlopen"]
     pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void;
 
@@ -1714,7 +1772,7 @@
     pub fn getppid() -> pid_t;
 
     // wait.h
-    pub fn waitpid(pid: pid_t, status: *mut c_int, optons: c_int) -> pid_t;
+    pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t;
 
     // unistd.h
     pub fn sysconf(attr: c_int) -> c_long;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.cargo_vcs_info.json
index efa0aa0..3ee48a5a 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.cargo_vcs_info.json
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "cdbf42389e40e15350745cc29e86cd5d93cb2a76"
+    "sha1": "0bdef053a00a5a17722733c550606ad15d62cea6"
   },
-  "path_in_vcs": ""
+  "path_in_vcs": "libm"
 }
\ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.editorconfig b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.editorconfig
deleted file mode 100644
index ec6e107..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.editorconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# EditorConfig helps developers define and maintain consistent
-# coding styles between different editors and IDEs
-# editorconfig.org
-
-root = true
-
-[*]
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-indent_style = space
-indent_size = 4
-
-[*.md]
-# double whitespace at end of line
-# denotes a line break in Markdown
-trim_trailing_whitespace = false
-
-[*.yml]
-indent_size = 2
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.git-blame-ignore-revs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.git-blame-ignore-revs
deleted file mode 100644
index c1e4313..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.git-blame-ignore-revs
+++ /dev/null
@@ -1,5 +0,0 @@
-# Use `git config blame.ignorerevsfile .git-blame-ignore-revs` to make
-# `git blame` ignore the following commits.
-
-# Reformat with a new `.rustfmt.toml`
-5882cabb83c30bf7c36023f9a55a80583636b0e8
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.gitignore b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.gitignore
deleted file mode 100644
index b6a5327..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-**.bk
-.#*
-/bin
-/math/src
-/math/target
-/target
-Cargo.lock
-musl/
-**.tar.gz
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.rustfmt.toml b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.rustfmt.toml
deleted file mode 100644
index c73bb930..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/.rustfmt.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-# This matches rustc
-style_edition = "2024"
-use_small_heuristics = "Max"
-group_imports = "StdExternalCrate"
-imports_granularity = "Module"
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CHANGELOG.md b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CHANGELOG.md
index 4e5acb89..292561f 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CHANGELOG.md
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CHANGELOG.md
@@ -8,6 +8,48 @@
 
 ## [Unreleased]
 
+## [0.2.13](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.12...libm-v0.2.13) - 2025-04-21
+
+### Fixed
+
+- Switch back to workspace resolver v2 to unbreak builds without the 2024 edition
+
+## [0.2.12](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.11...libm-v0.2.12) - 2025-04-21
+
+- Mark generic functions `#[inline]`
+- Combine the source files for `fmod`
+- Ensure all public functions are marked `no_panic`
+- Add assembly version of simple operations on aarch64
+- Add `roundeven{,f,f16,f128}`
+- Add `fminimum`, `fmaximum`, `fminimum_num`, and `fmaximum_num`
+- Eliminate the use of `force_eval!` in `ceil`, `floor`, and `trunc`
+- Port the CORE-MATH version of `cbrt`
+- Add `fmaf128`
+- fma: Ensure zero has the correct sign
+- Add `scalbnf16`, `scalbnf128`, `ldexpf16`, and `ldexpf128`
+- Specify license as just MIT
+- Add `fmodf128`
+- Add `fmodf16` using the generic implementation
+- Add `fminf16`, `fmaxf16`, `fminf128`, and `fmaxf128`
+- Add `roundf16` and `roundf128`
+- Add `rintf16` and `rintf128`
+- Add `floorf16` and `floorf128`
+- Add `ceilf16` and `ceilf128`
+- Add `sqrtf16` and `sqrtf128`
+- Simplify and optimize `fdim` ([#442](https://github.com/rust-lang/libm/pull/442))
+- Add `fdimf16` and `fdimf128`
+- Add `truncf16` and `truncf128`
+- Add `fabsf16`, `fabsf128`, `copysignf16`, and `copysignf128`
+- Move some numeric trait logic to default implementations
+- Add some more basic docstrings ([#352](https://github.com/rust-lang/libm/pull/352))
+- Add support for loongarch64-unknown-linux-gnu
+- Add an "arch" Cargo feature that is on by default
+- Rename the `special_case` module to `precision` and move default ULP
+- Move the existing "unstable" feature to "unstable-intrinsics"
+
+There are a number of things that changed internally, see the git log for a full
+list of changes.
+
 ## [0.2.11](https://github.com/rust-lang/libm/compare/libm-v0.2.10...libm-v0.2.11) - 2024-10-28
 
 ### Fixed
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CONTRIBUTING.md b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CONTRIBUTING.md
deleted file mode 100644
index a396236..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/CONTRIBUTING.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# How to contribute
-
-- Pick your favorite math function from the [issue tracker].
-- Look for the C implementation of the function in the [MUSL source code][src].
-- Copy paste the C code into a Rust file in the `src/math` directory and adjust
-  `src/math/mod.rs` accordingly. Also, uncomment the corresponding trait method
-  in `src/lib.rs`.
-- Write some simple tests in your module (using `#[test]`)
-- Run `cargo test` to make sure it works
-- Run `cargo test --features libm-test/test-musl-serialized` to compare your
-  implementation against musl's
-- Send us a pull request! Make sure to run `cargo fmt` on your code before
-  sending the PR. Also include "closes #42" in the PR description to close the
-  corresponding issue.
-- :tada:
-
-[issue tracker]: https://github.com/rust-lang/libm/issues
-[src]: https://git.musl-libc.org/cgit/musl/tree/src/math
-[`src/math/truncf.rs`]: https://github.com/rust-lang/libm/blob/master/src/math/truncf.rs
-
-Check [PR #65] for an example.
-
-[PR #65]: https://github.com/rust-lang/libm/pull/65
-
-## Tips and tricks
-
-- *IMPORTANT* The code in this crate will end up being used in the `core` crate so it can **not**
-  have any external dependencies (other than `core` itself).
-
-- Only use relative imports within the `math` directory / module, e.g. `use self::fabs::fabs` or
-`use super::k_cos`. Absolute imports from core are OK, e.g. `use core::u64`.
-
-- To reinterpret a float as an integer use the `to_bits` method. The MUSL code uses the
-  `GET_FLOAT_WORD` macro, or a union, to do this operation.
-
-- To reinterpret an integer as a float use the `f32::from_bits` constructor. The MUSL code uses the
-  `SET_FLOAT_WORD` macro, or a union, to do this operation.
-
-- You may use other methods from core like `f64::is_nan`, etc. as appropriate.
-
-- If you're implementing one of the private double-underscore functions, take a look at the
-  "source" name in the comment at the top for an idea for alternate naming. For example, `__sin`
-  was renamed to `k_sin` after the FreeBSD source code naming. Do `use` these private functions in
-  `mod.rs`.
-
-- You may encounter weird literals like `0x1p127f` in the MUSL code. These are hexadecimal floating
-  point literals. Rust (the language) doesn't support these kind of literals. The best way I have
-  found to deal with these literals is to turn them into their integer representation using the
-  [`hexf!`] macro and then turn them back into floats. See below:
-
-[`hexf!`]: https://crates.io/crates/hexf
-
-``` rust
-// Step 1: write a program to convert the float into its integer representation
-#[macro_use]
-extern crate hexf;
-
-fn main() {
-    println!("{:#x}", hexf32!("0x1.0p127").to_bits());
-}
-```
-
-``` console
-$ # Step 2: run the program
-$ cargo run
-0x7f000000
-```
-
-``` rust
-// Step 3: copy paste the output into libm
-let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 12
-```
-
-- Rust code panics on arithmetic overflows when not optimized. You may need to use the [`Wrapping`]
-  newtype to avoid this problem.
-
-[`Wrapping`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html
-
-## Testing
-
-Normal tests can be executed with:
-
-```sh
-cargo test
-```
-
-If you'd like to run tests with randomized inputs that get compared against musl
-itself, you'll need to be on a Linux system and then you can execute:
-
-```sh
-cargo test --features libm-test/test-musl-serialized
-```
-
-Note that you may need to pass `--release` to Cargo if there are errors related
-to integer overflow.
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.lock
new file mode 100644
index 0000000..7bebdcd
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.lock
@@ -0,0 +1,56 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "libm"
+version = "0.2.13"
+dependencies = [
+ "no-panic",
+]
+
+[[package]]
+name = "no-panic"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "113d1abd5bb3dc25a75d9b3a973f40e31eb03e0bae23c172b32cca4bcb9cfad2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml
index d01dcfe..c765fd77 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml
@@ -13,13 +13,9 @@
 edition = "2021"
 rust-version = "1.63"
 name = "libm"
-version = "0.2.11"
+version = "0.2.13"
 authors = ["Jorge Aparicio <jorge@japaric.io>"]
 build = "build.rs"
-exclude = [
-    "/ci/",
-    "/.github/workflows/",
-]
 autolib = false
 autobins = false
 autoexamples = false
@@ -33,20 +29,29 @@
     "math",
 ]
 categories = ["no-std"]
-license = "MIT AND (MIT OR Apache-2.0)"
-repository = "https://github.com/rust-lang/libm"
+license = "MIT"
+repository = "https://github.com/rust-lang/compiler-builtins"
 
-[profile.release]
-lto = "fat"
+[features]
+arch = []
+default = ["arch"]
+force-soft-floats = []
+unstable = [
+    "unstable-intrinsics",
+    "unstable-float",
+]
+unstable-float = []
+unstable-intrinsics = []
+unstable-public-internals = []
 
 [lib]
 name = "libm"
 path = "src/lib.rs"
 
 [dev-dependencies.no-panic]
-version = "0.1.30"
+version = "0.1.35"
 
-[features]
-default = []
-force-soft-floats = []
-unstable = []
+[lints.rust.unexpected_cfgs]
+level = "warn"
+priority = 0
+check-cfg = ['cfg(feature, values("compiler-builtins"))']
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml.orig
index aa6c08dd..f80715ff 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml.orig
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/Cargo.toml.orig
@@ -4,44 +4,46 @@
 description = "libm in pure Rust"
 documentation = "https://docs.rs/libm"
 keywords = ["libm", "math"]
-license = "MIT AND (MIT OR Apache-2.0)"
+license = "MIT"
 name = "libm"
 readme = "README.md"
-repository = "https://github.com/rust-lang/libm"
-version = "0.2.11"
+repository = "https://github.com/rust-lang/compiler-builtins"
+version = "0.2.13"
 edition = "2021"
-exclude = ["/ci/", "/.github/workflows/"]
 rust-version = "1.63"
 
 [features]
-default = []
+default = ["arch"]
+
+# Enable architecture-specific features such as SIMD or assembly routines.
+arch = []
 
 # This tells the compiler to assume that a Nightly toolchain is being used and
 # that it should activate any useful Nightly things accordingly.
-unstable = []
+unstable = ["unstable-intrinsics", "unstable-float"]
+
+# Enable calls to functions in `core::intrinsics`
+unstable-intrinsics = []
+
+# Make some internal things public for testing.
+unstable-public-internals = []
+
+# Enable the nightly-only `f16` and `f128`.
+unstable-float = []
 
 # Used to prevent using any intrinsics or arch-specific code.
+#
+# HACK: this is a negative feature which is generally a bad idea in Cargo, but
+# we need it to be able to forbid other features when this crate is used in
+# Rust dependencies. Setting this overrides all features that may enable
+# hard float operations.
 force-soft-floats = []
 
-[workspace]
-resolver = "2"
-members = [
-  "crates/compiler-builtins-smoke-test",
-  "crates/libm-bench",
-  "crates/libm-macros",
-  "crates/libm-test",
-  "crates/musl-math-sys",
-]
-default-members = [
-  ".",
-  "crates/libm-macros",
-  "crates/libm-test",
-]
-
 [dev-dependencies]
-no-panic = "0.1.30"
+no-panic = "0.1.35"
 
-
-# This is needed for no-panic to correctly detect the lack of panics
-[profile.release]
-lto = "fat"
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = [
+  # compiler-builtins sets this feature, but we use it in `libm`
+  'cfg(feature, values("compiler-builtins"))',
+] }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/README.md b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/README.md
index e5d64bd..349e892 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/README.md
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/README.md
@@ -1,38 +1,26 @@
 # `libm`
 
-A port of [MUSL]'s libm to Rust.
+A Rust implementations of the C math library.
 
-[MUSL]: https://musl.libc.org/
+## Usage
 
-## Goals
+`libm` provides fallback implementations for Rust's [float math functions] in
+`core`, and the [`core_float_math`] feature. If what is available suits your
+needs, there is no need to add `libm` as a dependency.
 
-The short term goal of this library is to [enable math support (e.g. `sin`, `atan2`) for the
-`wasm32-unknown-unknown` target][wasm] (cf. [rust-lang/compiler-builtins][pr]). The longer
-term goal is to enable [math support in the `core` crate][core].
+If more functionality is needed, this crate can also be used directly:
 
-[wasm]: https://github.com/rust-lang/libm/milestone/1
-[pr]: https://github.com/rust-lang/compiler-builtins/pull/248
-[core]: https://github.com/rust-lang/libm/milestone/2
+```toml
+[dependencies]
+libm = "0.2.11"
+```
 
-## Already usable
-
-This crate is [on crates.io] and can be used today in stable `#![no_std]` programs.
-
-The API documentation can be found [here](https://docs.rs/libm).
-
-[on crates.io]: https://crates.io/crates/libm
-
-## Benchmark
-[benchmark]: #benchmark
-
-The benchmarks are located in `crates/libm-bench` and require a nightly Rust toolchain.
-To run all benchmarks:
-
-> cargo +nightly bench --all
+[float math functions]: https://doc.rust-lang.org/std/primitive.f32.html
+[`core_float_math`]: https://github.com/rust-lang/rust/issues/137578
 
 ## Contributing
 
-Please check [CONTRIBUTING.md](CONTRIBUTING.md)
+Please check [CONTRIBUTING.md](../CONTRIBUTING.md)
 
 ## Minimum Rust version policy
 
@@ -40,17 +28,15 @@
 
 ## License
 
-Usage is licensed under the MIT license ([LICENSE-MIT](LICENSE-MIT) or
-http://opensource.org/licenses/MIT).
-
+Usage is under the MIT license, available at
+<https://opensource.org/license/mit>.
 
 ### Contribution
 
 Contributions are licensed under both the MIT license and the Apache License,
-Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
-http://www.apache.org/licenses/LICENSE-2.0). 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
-mentioned, without any additional terms or conditions.
+Version 2.0, available at <htps://www.apache.org/licenses/LICENSE-2.0>. 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 mentioned, without any additional terms or conditions.
 
-See `LICENSE.txt` for full details.
+See [LICENSE.txt](LICENSE.txt) for full details.
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs
index b683557..07d08ed 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs
@@ -1,17 +1,18 @@
 use std::env;
 
+mod configure;
+
 fn main() {
+    let cfg = configure::Config::from_env();
+
     println!("cargo:rerun-if-changed=build.rs");
+    println!("cargo:rerun-if-changed=configure.rs");
     println!("cargo:rustc-check-cfg=cfg(assert_no_panic)");
-    println!("cargo:rustc-check-cfg=cfg(feature, values(\"unstable\"))");
 
-    println!("cargo:rustc-check-cfg=cfg(feature, values(\"checked\"))");
-
-    #[allow(unexpected_cfgs)]
-    if !cfg!(feature = "checked") {
-        let lvl = env::var("OPT_LEVEL").unwrap();
-        if lvl != "0" {
-            println!("cargo:rustc-cfg=assert_no_panic");
-        }
+    // If set, enable `no-panic`. Requires LTO (`release-opt` profile).
+    if env::var("ENSURE_NO_PANIC").is_ok() {
+        println!("cargo:rustc-cfg=assert_no_panic");
     }
+
+    configure::emit_libm_config(&cfg);
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/configure.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/configure.rs
new file mode 100644
index 0000000..2a497c7
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/configure.rs
@@ -0,0 +1,189 @@
+// Configuration shared with both libm and libm-test
+
+use std::env;
+use std::path::PathBuf;
+
+#[allow(dead_code)]
+pub struct Config {
+    pub manifest_dir: PathBuf,
+    pub out_dir: PathBuf,
+    pub opt_level: String,
+    pub cargo_features: Vec<String>,
+    pub target_arch: String,
+    pub target_env: String,
+    pub target_family: Option<String>,
+    pub target_os: String,
+    pub target_string: String,
+    pub target_vendor: String,
+    pub target_features: Vec<String>,
+}
+
+impl Config {
+    pub fn from_env() -> Self {
+        let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
+            .map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
+            .unwrap_or_default();
+        let cargo_features = env::vars()
+            .filter_map(|(name, _value)| name.strip_prefix("CARGO_FEATURE_").map(ToOwned::to_owned))
+            .map(|s| s.to_lowercase().replace("_", "-"))
+            .collect();
+
+        Self {
+            manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
+            out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
+            opt_level: env::var("OPT_LEVEL").unwrap(),
+            cargo_features,
+            target_arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
+            target_env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
+            target_family: env::var("CARGO_CFG_TARGET_FAMILY").ok(),
+            target_os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
+            target_string: env::var("TARGET").unwrap(),
+            target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
+            target_features,
+        }
+    }
+}
+
+/// Libm gets most config options made available.
+#[allow(dead_code)]
+pub fn emit_libm_config(cfg: &Config) {
+    emit_intrinsics_cfg();
+    emit_arch_cfg();
+    emit_optimization_cfg(cfg);
+    emit_cfg_shorthands(cfg);
+    emit_cfg_env(cfg);
+    emit_f16_f128_cfg(cfg);
+}
+
+/// Tests don't need most feature-related config.
+#[allow(dead_code)]
+pub fn emit_test_config(cfg: &Config) {
+    emit_optimization_cfg(cfg);
+    emit_cfg_shorthands(cfg);
+    emit_cfg_env(cfg);
+    emit_f16_f128_cfg(cfg);
+}
+
+/// Simplify the feature logic for enabling intrinsics so code only needs to use
+/// `cfg(intrinsics_enabled)`.
+fn emit_intrinsics_cfg() {
+    println!("cargo:rustc-check-cfg=cfg(intrinsics_enabled)");
+
+    // Disabled by default; `unstable-intrinsics` enables again; `force-soft-floats` overrides
+    // to disable.
+    if cfg!(feature = "unstable-intrinsics") && !cfg!(feature = "force-soft-floats") {
+        println!("cargo:rustc-cfg=intrinsics_enabled");
+    }
+}
+
+/// Simplify the feature logic for enabling arch-specific features so code only needs to use
+/// `cfg(arch_enabled)`.
+fn emit_arch_cfg() {
+    println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
+
+    // Enabled by default via the "arch" feature, `force-soft-floats` overrides to disable.
+    if cfg!(feature = "arch") && !cfg!(feature = "force-soft-floats") {
+        println!("cargo:rustc-cfg=arch_enabled");
+    }
+}
+
+/// Some tests are extremely slow. Emit a config option based on optimization level.
+fn emit_optimization_cfg(cfg: &Config) {
+    println!("cargo:rustc-check-cfg=cfg(optimizations_enabled)");
+
+    if !matches!(cfg.opt_level.as_str(), "0" | "1") {
+        println!("cargo:rustc-cfg=optimizations_enabled");
+    }
+}
+
+/// Provide an alias for common longer config combinations.
+fn emit_cfg_shorthands(cfg: &Config) {
+    println!("cargo:rustc-check-cfg=cfg(x86_no_sse)");
+    if cfg.target_arch == "x86" && !cfg.target_features.iter().any(|f| f == "sse") {
+        // Shorthand to detect i586 targets
+        println!("cargo:rustc-cfg=x86_no_sse");
+    }
+}
+
+/// Reemit config that we make use of for test logging.
+fn emit_cfg_env(cfg: &Config) {
+    println!(
+        "cargo:rustc-env=CFG_CARGO_FEATURES={:?}",
+        cfg.cargo_features
+    );
+    println!("cargo:rustc-env=CFG_OPT_LEVEL={}", cfg.opt_level);
+    println!(
+        "cargo:rustc-env=CFG_TARGET_FEATURES={:?}",
+        cfg.target_features
+    );
+}
+
+/// Configure whether or not `f16` and `f128` support should be enabled.
+fn emit_f16_f128_cfg(cfg: &Config) {
+    println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
+    println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
+
+    // `unstable-float` enables these features.
+    if !cfg!(feature = "unstable-float") {
+        return;
+    }
+
+    // Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
+    // that the backend will not crash when using these types and generates code that can be called
+    // without crashing (no infinite recursion). This does not mean that the platform doesn't have
+    // ABI or other bugs.
+    //
+    // We do this here rather than in `rust-lang/rust` because configuring via cargo features is
+    // not straightforward.
+    //
+    // Original source of this list:
+    // <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
+    let f16_enabled = match cfg.target_arch.as_str() {
+        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
+        "arm64ec" => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
+        "s390x" => false,
+        // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
+        // FIXME(llvm): loongarch fixed by <https://github.com/llvm/llvm-project/pull/107791>
+        "csky" => false,
+        "hexagon" => false,
+        "loongarch64" => false,
+        "mips" | "mips64" | "mips32r6" | "mips64r6" => false,
+        "powerpc" | "powerpc64" => false,
+        "sparc" | "sparc64" => false,
+        "wasm32" | "wasm64" => false,
+        // Most everything else works as of LLVM 19
+        _ => true,
+    };
+
+    let f128_enabled = match cfg.target_arch.as_str() {
+        // Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
+        "amdgpu" => false,
+        // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
+        "arm64ec" => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/96432>
+        "mips64" | "mips64r6" => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/95471>
+        "nvptx64" => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/101545>
+        "powerpc64" if &cfg.target_os == "aix" => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/41838>
+        "sparc" => false,
+        // Most everything else works as of LLVM 19
+        _ => true,
+    };
+
+    // If the feature is set, disable these types.
+    let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
+
+    println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
+    println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
+
+    if f16_enabled && !disable_both {
+        println!("cargo:rustc-cfg=f16_enabled");
+    }
+
+    if f128_enabled && !disable_both {
+        println!("cargo:rustc-cfg=f128_enabled");
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/lib.rs
index 6d95fa1..31b1223 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/lib.rs
@@ -1,16 +1,27 @@
 //! libm in pure Rust
 #![no_std]
-#![cfg_attr(feature = "unstable", allow(internal_features))]
-#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
+#![cfg_attr(intrinsics_enabled, allow(internal_features))]
+#![cfg_attr(intrinsics_enabled, feature(core_intrinsics))]
+#![cfg_attr(
+    all(intrinsics_enabled, target_family = "wasm"),
+    feature(wasm_numeric_instr)
+)]
+#![cfg_attr(f128_enabled, feature(f128))]
+#![cfg_attr(f16_enabled, feature(f16))]
 #![allow(clippy::assign_op_pattern)]
 #![allow(clippy::deprecated_cfg_attr)]
 #![allow(clippy::eq_op)]
+#![allow(clippy::excessive_precision)]
 #![allow(clippy::float_cmp)]
 #![allow(clippy::int_plus_one)]
+#![allow(clippy::just_underscores_and_digits)]
 #![allow(clippy::many_single_char_names)]
 #![allow(clippy::mixed_case_hex_literals)]
+#![allow(clippy::needless_late_init)]
 #![allow(clippy::needless_return)]
 #![allow(clippy::unreadable_literal)]
+#![allow(clippy::zero_divided_by_zero)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 mod libm_helper;
 mod math;
@@ -20,28 +31,3 @@
 pub use libm_helper::*;
 
 pub use self::math::*;
-
-/// Approximate equality with 1 ULP of tolerance
-#[doc(hidden)]
-#[inline]
-pub fn _eqf(a: f32, b: f32) -> Result<(), u32> {
-    if a.is_nan() && b.is_nan() {
-        Ok(())
-    } else {
-        let err = (a.to_bits() as i32).wrapping_sub(b.to_bits() as i32).abs();
-
-        if err <= 1 { Ok(()) } else { Err(err as u32) }
-    }
-}
-
-#[doc(hidden)]
-#[inline]
-pub fn _eq(a: f64, b: f64) -> Result<(), u64> {
-    if a.is_nan() && b.is_nan() {
-        Ok(())
-    } else {
-        let err = (a.to_bits() as i64).wrapping_sub(b.to_bits() as i64).abs();
-
-        if err <= 1 { Ok(()) } else { Err(err as u64) }
-    }
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/libm_helper.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/libm_helper.rs
index 52d0c4c..dfa1ff77 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/libm_helper.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/libm_helper.rs
@@ -30,7 +30,7 @@
         }
     };
 
-    ({$($func:tt);*}) => {
+    ({$($func:tt;)*}) => {
         $(
             libm_helper! { $func }
         )*
@@ -44,9 +44,11 @@
     };
 }
 
+// verify-apilist-start
 libm_helper! {
     f32,
     funcs: {
+        // verify-sorted-start
         (fn acos(x: f32) -> (f32);                  => acosf);
         (fn acosh(x: f32) -> (f32);                 => acoshf);
         (fn asin(x: f32) -> (f32);                  => asinf);
@@ -62,8 +64,8 @@
         (fn erf(x: f32) -> (f32);                   => erff);
         (fn erfc(x: f32) -> (f32);                  => erfcf);
         (fn exp(x: f32) -> (f32);                   => expf);
-        (fn exp2(x: f32) -> (f32);                  => exp2f);
         (fn exp10(x: f32) -> (f32);                 => exp10f);
+        (fn exp2(x: f32) -> (f32);                  => exp2f);
         (fn expm1(x: f32) -> (f32);                 => expm1f);
         (fn fabs(x: f32) -> (f32);                  => fabsf);
         (fn fdim(x: f32, y: f32) -> (f32);          => fdimf);
@@ -79,12 +81,12 @@
         (fn j1(x: f32) -> (f32);                    => j1f);
         (fn jn(n: i32, x: f32) -> (f32);            => jnf);
         (fn ldexp(x: f32, n: i32) -> (f32);         => ldexpf);
-        (fn lgamma_r(x: f32) -> (f32, i32);         => lgammaf_r);
         (fn lgamma(x: f32) -> (f32);                => lgammaf);
+        (fn lgamma_r(x: f32) -> (f32, i32);         => lgammaf_r);
         (fn log(x: f32) -> (f32);                   => logf);
+        (fn log10(x: f32) -> (f32);                 => log10f);
         (fn log1p(x: f32) -> (f32);                 => log1pf);
         (fn log2(x: f32) -> (f32);                  => log2f);
-        (fn log10(x: f32) -> (f32);                 => log10f);
         (fn modf(x: f32) -> (f32, f32);             => modff);
         (fn nextafter(x: f32, y: f32) -> (f32);     => nextafterf);
         (fn pow(x: f32, y: f32) -> (f32);           => powf);
@@ -92,6 +94,7 @@
         (fn remquo(x: f32, y: f32) -> (f32, i32);   => remquof);
         (fn rint(x: f32) -> (f32);                  => rintf);
         (fn round(x: f32) -> (f32);                 => roundf);
+        (fn roundeven(x: f32) -> (f32);             => roundevenf);
         (fn scalbn(x: f32, n: i32) -> (f32);        => scalbnf);
         (fn sin(x: f32) -> (f32);                   => sinf);
         (fn sincos(x: f32) -> (f32, f32);           => sincosf);
@@ -103,13 +106,15 @@
         (fn trunc(x: f32) -> (f32);                 => truncf);
         (fn y0(x: f32) -> (f32);                    => y0f);
         (fn y1(x: f32) -> (f32);                    => y1f);
-        (fn yn(n: i32, x: f32) -> (f32);            => ynf)
+        (fn yn(n: i32, x: f32) -> (f32);            => ynf);
+        // verify-sorted-end
     }
 }
 
 libm_helper! {
     f64,
     funcs: {
+        // verify-sorted-start
         (fn acos(x: f64) -> (f64);                  => acos);
         (fn acosh(x: f64) -> (f64);                 => acosh);
         (fn asin(x: f64) -> (f64);                  => asin);
@@ -125,15 +130,23 @@
         (fn erf(x: f64) -> (f64);                   => erf);
         (fn erfc(x: f64) -> (f64);                  => erfc);
         (fn exp(x: f64) -> (f64);                   => exp);
-        (fn exp2(x: f64) -> (f64);                  => exp2);
         (fn exp10(x: f64) -> (f64);                 => exp10);
+        (fn exp2(x: f64) -> (f64);                  => exp2);
         (fn expm1(x: f64) -> (f64);                 => expm1);
         (fn fabs(x: f64) -> (f64);                  => fabs);
         (fn fdim(x: f64, y: f64) -> (f64);          => fdim);
         (fn floor(x: f64) -> (f64);                 => floor);
         (fn fma(x: f64, y: f64, z: f64) -> (f64);   => fma);
         (fn fmax(x: f64, y: f64) -> (f64);          => fmax);
+        (fn fmaximum(x: f64, y: f64) -> (f64);      => fmaximum);
+        (fn fmaximum_num(x: f64, y: f64) -> (f64);  => fmaximum_num);
+        (fn fmaximum_numf(x: f32, y: f32) -> (f32); => fmaximum_numf);
+        (fn fmaximumf(x: f32, y: f32) -> (f32);     => fmaximumf);
         (fn fmin(x: f64, y: f64) -> (f64);          => fmin);
+        (fn fminimum(x: f64, y: f64) -> (f64);      => fminimum);
+        (fn fminimum_num(x: f64, y: f64) -> (f64);  => fminimum_num);
+        (fn fminimum_numf(x: f32, y: f32) -> (f32); => fminimum_numf);
+        (fn fminimumf(x: f32, y: f32) -> (f32);     => fminimumf);
         (fn fmod(x: f64, y: f64) -> (f64);          => fmod);
         (fn frexp(x: f64) -> (f64, i32);            => frexp);
         (fn hypot(x: f64, y: f64) -> (f64);         => hypot);
@@ -142,12 +155,12 @@
         (fn j1(x: f64) -> (f64);                    => j1);
         (fn jn(n: i32, x: f64) -> (f64);            => jn);
         (fn ldexp(x: f64, n: i32) -> (f64);         => ldexp);
-        (fn lgamma_r(x: f64) -> (f64, i32);         => lgamma_r);
         (fn lgamma(x: f64) -> (f64);                => lgamma);
+        (fn lgamma_r(x: f64) -> (f64, i32);         => lgamma_r);
         (fn log(x: f64) -> (f64);                   => log);
+        (fn log10(x: f64) -> (f64);                 => log10);
         (fn log1p(x: f64) -> (f64);                 => log1p);
         (fn log2(x: f64) -> (f64);                  => log2);
-        (fn log10(x: f64) -> (f64);                 => log10);
         (fn modf(x: f64) -> (f64, f64);             => modf);
         (fn nextafter(x: f64, y: f64) -> (f64);     => nextafter);
         (fn pow(x: f64, y: f64) -> (f64);           => pow);
@@ -155,6 +168,7 @@
         (fn remquo(x: f64, y: f64) -> (f64, i32);   => remquo);
         (fn rint(x: f64) -> (f64);                  => rint);
         (fn round(x: f64) -> (f64);                 => round);
+        (fn roundevem(x: f64) -> (f64);             => roundeven);
         (fn scalbn(x: f64, n: i32) -> (f64);        => scalbn);
         (fn sin(x: f64) -> (f64);                   => sin);
         (fn sincos(x: f64) -> (f64, f64);           => sincos);
@@ -166,6 +180,65 @@
         (fn trunc(x: f64) -> (f64);                 => trunc);
         (fn y0(x: f64) -> (f64);                    => y0);
         (fn y1(x: f64) -> (f64);                    => y1);
-        (fn yn(n: i32, x: f64) -> (f64);            => yn)
+        (fn yn(n: i32, x: f64) -> (f64);            => yn);
+        // verify-sorted-end
     }
 }
+
+#[cfg(f16_enabled)]
+libm_helper! {
+    f16,
+    funcs: {
+        // verify-sorted-start
+        (fn ceil(x: f16) -> (f16);                  => ceilf16);
+        (fn copysign(x: f16, y: f16) -> (f16);      => copysignf16);
+        (fn fabs(x: f16) -> (f16);                  => fabsf16);
+        (fn fdim(x: f16, y: f16) -> (f16);          => fdimf16);
+        (fn floor(x: f16) -> (f16);                 => floorf16);
+        (fn fmax(x: f16, y: f16) -> (f16);          => fmaxf16);
+        (fn fmaximum_num(x: f16, y: f16) -> (f16);  => fmaximum_numf16);
+        (fn fmaximumf16(x: f16, y: f16) -> (f16);   => fmaximumf16);
+        (fn fmin(x: f16, y: f16) -> (f16);          => fminf16);
+        (fn fminimum(x: f16, y: f16) -> (f16);      => fminimumf16);
+        (fn fminimum_num(x: f16, y: f16) -> (f16);  => fminimum_numf16);
+        (fn fmod(x: f16, y: f16) -> (f16);          => fmodf16);
+        (fn ldexp(x: f16, n: i32) -> (f16);         => ldexpf16);
+        (fn rint(x: f16) -> (f16);                  => rintf16);
+        (fn round(x: f16) -> (f16);                 => roundf16);
+        (fn roundeven(x: f16) -> (f16);             => roundevenf16);
+        (fn scalbn(x: f16, n: i32) -> (f16);        => scalbnf16);
+        (fn sqrtf(x: f16) -> (f16);                 => sqrtf16);
+        (fn truncf(x: f16) -> (f16);                => truncf16);
+        // verify-sorted-end
+    }
+}
+
+#[cfg(f128_enabled)]
+libm_helper! {
+    f128,
+    funcs: {
+        // verify-sorted-start
+        (fn ceil(x: f128) -> (f128);                => ceilf128);
+        (fn copysign(x: f128, y: f128) -> (f128);   => copysignf128);
+        (fn fabs(x: f128) -> (f128);                => fabsf128);
+        (fn fdim(x: f128, y: f128) -> (f128);       => fdimf128);
+        (fn floor(x: f128) -> (f128);               => floorf128);
+        (fn fma(x: f128, y: f128, z: f128) -> (f128); => fmaf128);
+        (fn fmax(x: f128, y: f128) -> (f128);       => fmaxf128);
+        (fn fmaximum(x: f128, y: f128) -> (f128);      => fmaximumf128);
+        (fn fmaximum_num(x: f128, y: f128) -> (f128);  => fmaximum_numf128);
+        (fn fmin(x: f128, y: f128) -> (f128);       => fminf128);
+        (fn fminimum(x: f128, y: f128) -> (f128);      => fminimumf128);
+        (fn fminimum_num(x: f128, y: f128) -> (f128);  => fminimum_numf128);
+        (fn fmod(x: f128, y: f128) -> (f128);       => fmodf128);
+        (fn ldexp(x: f128, n: i32) -> (f128);       => ldexpf128);
+        (fn rint(x: f128) -> (f128);                => rintf128);
+        (fn round(x: f128) -> (f128);               => roundf128);
+        (fn roundeven(x: f128) -> (f128);           => roundevenf128);
+        (fn scalbn(x: f128, n: i32) -> (f128);      => scalbnf128);
+        (fn sqrt(x: f128) -> (f128);                => sqrtf128);
+        (fn trunc(x: f128) -> (f128);               => truncf128);
+        // verify-sorted-end
+    }
+}
+// verify-apilist-end
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosf.rs
index 1a60479..dd88eea5 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosf.rs
@@ -13,7 +13,7 @@
  * ====================================================
  */
 
-use super::sqrtf::sqrtf;
+use super::sqrt::sqrtf;
 
 const PIO2_HI: f32 = 1.5707962513e+00; /* 0x3fc90fda */
 const PIO2_LO: f32 = 7.5497894159e-08; /* 0x33a22168 */
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/aarch64.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/aarch64.rs
new file mode 100644
index 0000000..020bb73
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/aarch64.rs
@@ -0,0 +1,115 @@
+//! Architecture-specific support for aarch64 with neon.
+
+use core::arch::asm;
+
+pub fn fma(mut x: f64, y: f64, z: f64) -> f64 {
+    // SAFETY: `fmadd` is available with neon and has no side effects.
+    unsafe {
+        asm!(
+            "fmadd {x:d}, {x:d}, {y:d}, {z:d}",
+            x = inout(vreg) x,
+            y = in(vreg) y,
+            z = in(vreg) z,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+pub fn fmaf(mut x: f32, y: f32, z: f32) -> f32 {
+    // SAFETY: `fmadd` is available with neon and has no side effects.
+    unsafe {
+        asm!(
+            "fmadd {x:s}, {x:s}, {y:s}, {z:s}",
+            x = inout(vreg) x,
+            y = in(vreg) y,
+            z = in(vreg) z,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+pub fn rint(mut x: f64) -> f64 {
+    // SAFETY: `frintn` is available with neon and has no side effects.
+    //
+    // `frintn` is always round-to-nearest which does not match the C specification, but Rust does
+    // not support rounding modes.
+    unsafe {
+        asm!(
+            "frintn {x:d}, {x:d}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+pub fn rintf(mut x: f32) -> f32 {
+    // SAFETY: `frintn` is available with neon and has no side effects.
+    //
+    // `frintn` is always round-to-nearest which does not match the C specification, but Rust does
+    // not support rounding modes.
+    unsafe {
+        asm!(
+            "frintn {x:s}, {x:s}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+#[cfg(all(f16_enabled, target_feature = "fp16"))]
+pub fn rintf16(mut x: f16) -> f16 {
+    // SAFETY: `frintn` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
+    //
+    // `frintn` is always round-to-nearest which does not match the C specification, but Rust does
+    // not support rounding modes.
+    unsafe {
+        asm!(
+            "frintn {x:h}, {x:h}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+pub fn sqrt(mut x: f64) -> f64 {
+    // SAFETY: `fsqrt` is available with neon and has no side effects.
+    unsafe {
+        asm!(
+            "fsqrt {x:d}, {x:d}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+pub fn sqrtf(mut x: f32) -> f32 {
+    // SAFETY: `fsqrt` is available with neon and has no side effects.
+    unsafe {
+        asm!(
+            "fsqrt {x:s}, {x:s}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
+
+#[cfg(all(f16_enabled, target_feature = "fp16"))]
+pub fn sqrtf16(mut x: f16) -> f16 {
+    // SAFETY: `fsqrt` is available for `f16` with `fp16` (implies `neon`) and has no
+    // side effects.
+    unsafe {
+        asm!(
+            "fsqrt {x:h}, {x:h}",
+            x = inout(vreg) x,
+            options(nomem, nostack, pure)
+        );
+    }
+    x
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i586.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i586.rs
new file mode 100644
index 0000000..f92b9a2
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i586.rs
@@ -0,0 +1,37 @@
+//! Architecture-specific support for x86-32 without SSE2
+
+use super::super::fabs;
+
+/// Use an alternative implementation on x86, because the
+/// main implementation fails with the x87 FPU used by
+/// debian i386, probably due to excess precision issues.
+/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
+pub fn ceil(x: f64) -> f64 {
+    if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
+        let truncated = x as i64 as f64;
+        if truncated < x {
+            return truncated + 1.0;
+        } else {
+            return truncated;
+        }
+    } else {
+        return x;
+    }
+}
+
+/// Use an alternative implementation on x86, because the
+/// main implementation fails with the x87 FPU used by
+/// debian i386, probably due to excess precision issues.
+/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
+pub fn floor(x: f64) -> f64 {
+    if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
+        let truncated = x as i64 as f64;
+        if truncated > x {
+            return truncated - 1.0;
+        } else {
+            return truncated;
+        }
+    } else {
+        return x;
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i686.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i686.rs
new file mode 100644
index 0000000..3e1d19bf
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i686.rs
@@ -0,0 +1,27 @@
+//! Architecture-specific support for x86-32 and x86-64 with SSE2
+
+pub fn sqrtf(mut x: f32) -> f32 {
+    // SAFETY: `sqrtss` is part of `sse2`, which this module is gated behind. It has no memory
+    // access or side effects.
+    unsafe {
+        core::arch::asm!(
+            "sqrtss {x}, {x}",
+            x = inout(xmm_reg) x,
+            options(nostack, nomem, pure),
+        )
+    };
+    x
+}
+
+pub fn sqrt(mut x: f64) -> f64 {
+    // SAFETY: `sqrtsd` is part of `sse2`, which this module is gated behind. It has no memory
+    // access or side effects.
+    unsafe {
+        core::arch::asm!(
+            "sqrtsd {x}, {x}",
+            x = inout(xmm_reg) x,
+            options(nostack, nomem, pure),
+        )
+    };
+    x
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/mod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/mod.rs
new file mode 100644
index 0000000..d9f2aad
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/mod.rs
@@ -0,0 +1,50 @@
+//! Architecture-specific routines and operations.
+//!
+//! LLVM will already optimize calls to some of these in cases that there are hardware
+//! instructions. Providing an implementation here just ensures that the faster implementation
+//! is used when calling the function directly. This helps anyone who uses `libm` directly, as
+//! well as improving things when these routines are called as part of other implementations.
+
+// Most implementations should be defined here, to ensure they are not made available when
+// soft floats are required.
+#[cfg(arch_enabled)]
+cfg_if! {
+    if #[cfg(all(target_arch = "wasm32", intrinsics_enabled))] {
+        mod wasm32;
+        pub use wasm32::{
+            ceil, ceilf, fabs, fabsf, floor, floorf, rint, rintf, sqrt, sqrtf, trunc, truncf,
+        };
+    } else if #[cfg(target_feature = "sse2")] {
+        mod i686;
+        pub use i686::{sqrt, sqrtf};
+    } else if #[cfg(all(
+        any(target_arch = "aarch64", target_arch = "arm64ec"),
+        target_feature = "neon"
+    ))] {
+        mod aarch64;
+
+        pub use aarch64::{
+            fma,
+            fmaf,
+            rint,
+            rintf,
+            sqrt,
+            sqrtf,
+        };
+
+        #[cfg(all(f16_enabled, target_feature = "fp16"))]
+        pub use aarch64::{
+            rintf16,
+            sqrtf16,
+        };
+    }
+}
+
+// There are certain architecture-specific implementations that are needed for correctness
+// even with `force-soft-float`. These are configured here.
+cfg_if! {
+    if #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] {
+        mod i586;
+        pub use i586::{ceil, floor};
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/wasm32.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/wasm32.rs
new file mode 100644
index 0000000..de80c8a
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/wasm32.rs
@@ -0,0 +1,50 @@
+//! Wasm has builtins for simple float operations. Use the unstable `core::arch` intrinsics which
+//! are significantly faster than soft float operations.
+
+pub fn ceil(x: f64) -> f64 {
+    core::arch::wasm32::f64_ceil(x)
+}
+
+pub fn ceilf(x: f32) -> f32 {
+    core::arch::wasm32::f32_ceil(x)
+}
+
+pub fn fabs(x: f64) -> f64 {
+    x.abs()
+}
+
+pub fn fabsf(x: f32) -> f32 {
+    x.abs()
+}
+
+pub fn floor(x: f64) -> f64 {
+    core::arch::wasm32::f64_floor(x)
+}
+
+pub fn floorf(x: f32) -> f32 {
+    core::arch::wasm32::f32_floor(x)
+}
+
+pub fn rint(x: f64) -> f64 {
+    core::arch::wasm32::f64_nearest(x)
+}
+
+pub fn rintf(x: f32) -> f32 {
+    core::arch::wasm32::f32_nearest(x)
+}
+
+pub fn sqrt(x: f64) -> f64 {
+    core::arch::wasm32::f64_sqrt(x)
+}
+
+pub fn sqrtf(x: f32) -> f32 {
+    core::arch::wasm32::f32_sqrt(x)
+}
+
+pub fn trunc(x: f64) -> f64 {
+    core::arch::wasm32::f64_trunc(x)
+}
+
+pub fn truncf(x: f32) -> f32 {
+    core::arch::wasm32::f32_trunc(x)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asin.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asin.rs
index 12fe08f..12d0cd3 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asin.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asin.rs
@@ -90,7 +90,7 @@
     /* |x| < 0.5 */
     if ix < 0x3fe00000 {
         /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
-        if ix < 0x3e500000 && ix >= 0x00100000 {
+        if (0x00100000..0x3e500000).contains(&ix) {
             return x;
         } else {
             return x + x * comp_r(x * x);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinf.rs
index 2c785ab..ed68555 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinf.rs
@@ -13,8 +13,8 @@
  * ====================================================
  */
 
-use super::fabsf::fabsf;
 use super::sqrt::sqrt;
+use super::support::Float;
 
 const PIO2: f64 = 1.570796326794896558e+00;
 
@@ -54,14 +54,14 @@
     if ix < 0x3f000000 {
         /* |x| < 0.5 */
         /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */
-        if (ix < 0x39800000) && (ix >= 0x00800000) {
+        if (0x00800000..0x39800000).contains(&ix) {
             return x;
         }
         return x + x * r(x * x);
     }
 
     /* 1 > |x| >= 0.5 */
-    let z = (1. - fabsf(x)) * 0.5;
+    let z = (1. - Float::abs(x)) * 0.5;
     let s = sqrt(z as f64);
     x = (PIO2 - 2. * (s + s * (r(z) as f64))) as f32;
     if (hx >> 31) != 0 { -x } else { x }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2.rs
index b9bf0da..c668731 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2.rs
@@ -114,12 +114,18 @@
     }
 }
 
-#[test]
-fn sanity_check() {
-    assert_eq!(atan2(0.0, 1.0), 0.0);
-    assert_eq!(atan2(0.0, -1.0), PI);
-    assert_eq!(atan2(-0.0, -1.0), -PI);
-    assert_eq!(atan2(3.0, 2.0), atan(3.0 / 2.0));
-    assert_eq!(atan2(2.0, -1.0), atan(2.0 / -1.0) + PI);
-    assert_eq!(atan2(-2.0, -1.0), atan(-2.0 / -1.0) - PI);
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    #[cfg_attr(x86_no_sse, ignore = "FIXME(i586): possible incorrect rounding")]
+    fn sanity_check() {
+        assert_eq!(atan2(0.0, 1.0), 0.0);
+        assert_eq!(atan2(0.0, -1.0), PI);
+        assert_eq!(atan2(-0.0, -1.0), -PI);
+        assert_eq!(atan2(3.0, 2.0), atan(3.0 / 2.0));
+        assert_eq!(atan2(2.0, -1.0), atan(2.0 / -1.0) + PI);
+        assert_eq!(atan2(-2.0, -1.0), atan(-2.0 / -1.0) - PI);
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2f.rs
index fa33f54..95b466f 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atan2f.rs
@@ -42,9 +42,9 @@
     /* when y = 0 */
     if iy == 0 {
         return match m {
-            0 | 1 => y,   /* atan(+-0,+anything)=+-0 */
-            2 => PI,      /* atan(+0,-anything) = pi */
-            3 | _ => -PI, /* atan(-0,-anything) =-pi */
+            0 | 1 => y, /* atan(+-0,+anything)=+-0 */
+            2 => PI,    /* atan(+0,-anything) = pi */
+            _ => -PI,   /* atan(-0,-anything) =-pi */
         };
     }
     /* when x = 0 */
@@ -55,17 +55,17 @@
     if ix == 0x7f800000 {
         return if iy == 0x7f800000 {
             match m {
-                0 => PI / 4.,           /* atan(+INF,+INF) */
-                1 => -PI / 4.,          /* atan(-INF,+INF) */
-                2 => 3. * PI / 4.,      /* atan(+INF,-INF)*/
-                3 | _ => -3. * PI / 4., /* atan(-INF,-INF)*/
+                0 => PI / 4.,       /* atan(+INF,+INF) */
+                1 => -PI / 4.,      /* atan(-INF,+INF) */
+                2 => 3. * PI / 4.,  /* atan(+INF,-INF)*/
+                _ => -3. * PI / 4., /* atan(-INF,-INF)*/
             }
         } else {
             match m {
-                0 => 0.,      /* atan(+...,+INF) */
-                1 => -0.,     /* atan(-...,+INF) */
-                2 => PI,      /* atan(+...,-INF) */
-                3 | _ => -PI, /* atan(-...,-INF) */
+                0 => 0.,  /* atan(+...,+INF) */
+                1 => -0., /* atan(-...,+INF) */
+                2 => PI,  /* atan(+...,-INF) */
+                _ => -PI, /* atan(-...,-INF) */
             }
         };
     }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanf.rs
index eb3d401..da8daa41 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanf.rs
@@ -29,8 +29,13 @@
     7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
 ];
 
-const A_T: [f32; 5] =
-    [3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02];
+const A_T: [f32; 5] = [
+    3.3333328366e-01,
+    -1.9999158382e-01,
+    1.4253635705e-01,
+    -1.0648017377e-01,
+    6.1687607318e-02,
+];
 
 /// Arctangent (f32)
 ///
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanhf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanhf.rs
index 3545411..80ccec1f 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanhf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/atanhf.rs
@@ -18,7 +18,7 @@
         if u < 0x3f800000 - (32 << 23) {
             /* handle underflow */
             if u < (1 << 23) {
-                force_eval!((x * x) as f32);
+                force_eval!(x * x);
             }
         } else {
             /* |x| < 0.5, up to 1.7ulp error */
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrt.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrt.rs
index b4e77ea..cf56f7a 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrt.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrt.rs
@@ -1,113 +1,219 @@
-/* origin: FreeBSD /usr/src/lib/msun/src/s_cbrt.c */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- *
- * Optimized by Bruce D. Evans.
- */
-/* cbrt(x)
- * Return cube root of x
+/* SPDX-License-Identifier: MIT */
+/* origin: core-math/src/binary64/cbrt/cbrt.c
+ * Copyright (c) 2021-2022 Alexei Sibidanov.
+ * Ported to Rust in 2025 by Trevor Gross.
  */
 
-use core::f64;
+use super::Float;
+use super::support::{FpResult, Round, cold_path};
 
-const B1: u32 = 715094163; /* B1 = (1023-1023/3-0.03306235651)*2**20 */
-const B2: u32 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */
-
-/* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */
-const P0: f64 = 1.87595182427177009643; /* 0x3ffe03e6, 0x0f61e692 */
-const P1: f64 = -1.88497979543377169875; /* 0xbffe28e0, 0x92f02420 */
-const P2: f64 = 1.621429720105354466140; /* 0x3ff9f160, 0x4a49d6c2 */
-const P3: f64 = -0.758397934778766047437; /* 0xbfe844cb, 0xbee751d9 */
-const P4: f64 = 0.145996192886612446982; /* 0x3fc2b000, 0xd4e4edd7 */
-
-// Cube root (f64)
-///
-/// Computes the cube root of the argument.
+/// Compute the cube root of the argument.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn cbrt(x: f64) -> f64 {
-    let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54
+    cbrt_round(x, Round::Nearest).val
+}
 
-    let mut ui: u64 = x.to_bits();
-    let mut r: f64;
-    let s: f64;
-    let mut t: f64;
-    let w: f64;
-    let mut hx: u32 = (ui >> 32) as u32 & 0x7fffffff;
+pub fn cbrt_round(x: f64, round: Round) -> FpResult<f64> {
+    const ESCALE: [f64; 3] = [
+        1.0,
+        hf64!("0x1.428a2f98d728bp+0"), /* 2^(1/3) */
+        hf64!("0x1.965fea53d6e3dp+0"), /* 2^(2/3) */
+    ];
 
-    if hx >= 0x7ff00000 {
-        /* cbrt(NaN,INF) is itself */
-        return x + x;
-    }
+    /* the polynomial c0+c1*x+c2*x^2+c3*x^3 approximates x^(1/3) on [1,2]
+    with maximal error < 9.2e-5 (attained at x=2) */
+    const C: [f64; 4] = [
+        hf64!("0x1.1b0babccfef9cp-1"),
+        hf64!("0x1.2c9a3e94d1da5p-1"),
+        hf64!("-0x1.4dc30b1a1ddbap-3"),
+        hf64!("0x1.7a8d3e4ec9b07p-6"),
+    ];
 
-    /*
-     * Rough cbrt to 5 bits:
-     *    cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3)
-     * where e is integral and >= 0, m is real and in [0, 1), and "/" and
-     * "%" are integer division and modulus with rounding towards minus
-     * infinity.  The RHS is always >= the LHS and has a maximum relative
-     * error of about 1 in 16.  Adding a bias of -0.03306235651 to the
-     * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE
-     * floating point representation, for finite positive normal values,
-     * ordinary integer divison of the value in bits magically gives
-     * almost exactly the RHS of the above provided we first subtract the
-     * exponent bias (1023 for doubles) and later add it back.  We do the
-     * subtraction virtually to keep e >= 0 so that ordinary integer
-     * division rounds towards minus infinity; this is also efficient.
-     */
-    if hx < 0x00100000 {
-        /* zero or subnormal? */
-        ui = (x * x1p54).to_bits();
-        hx = (ui >> 32) as u32 & 0x7fffffff;
-        if hx == 0 {
-            return x; /* cbrt(0) is itself */
+    let u0: f64 = hf64!("0x1.5555555555555p-2");
+    let u1: f64 = hf64!("0x1.c71c71c71c71cp-3");
+
+    let rsc = [1.0, -1.0, 0.5, -0.5, 0.25, -0.25];
+
+    let off = [hf64!("0x1p-53"), 0.0, 0.0, 0.0];
+
+    /* rm=0 for rounding to nearest, and other values for directed roundings */
+    let hx: u64 = x.to_bits();
+    let mut mant: u64 = hx & f64::SIG_MASK;
+    let sign: u64 = hx >> 63;
+
+    let mut e: u32 = (hx >> f64::SIG_BITS) as u32 & f64::EXP_SAT;
+
+    if ((e + 1) & f64::EXP_SAT) < 2 {
+        cold_path();
+
+        let ix: u64 = hx & !f64::SIGN_MASK;
+
+        /* 0, inf, nan: we return x + x instead of simply x,
+        to that for x a signaling NaN, it correctly triggers
+        the invalid exception. */
+        if e == f64::EXP_SAT || ix == 0 {
+            return FpResult::ok(x + x);
         }
-        hx = hx / 3 + B2;
-    } else {
-        hx = hx / 3 + B1;
+
+        let nz = ix.leading_zeros() - 11; /* subnormal */
+        mant <<= nz;
+        mant &= f64::SIG_MASK;
+        e = e.wrapping_sub(nz - 1);
     }
-    ui &= 1 << 63;
-    ui |= (hx as u64) << 32;
-    t = f64::from_bits(ui);
 
-    /*
-     * New cbrt to 23 bits:
-     *    cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x)
-     * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r)
-     * to within 2**-23.5 when |r - 1| < 1/10.  The rough approximation
-     * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this
-     * gives us bounds for r = t**3/x.
-     *
-     * Try to optimize for parallel evaluation as in __tanf.c.
-     */
-    r = (t * t) * (t / x);
-    t = t * ((P0 + r * (P1 + r * P2)) + ((r * r) * r) * (P3 + r * P4));
+    e = e.wrapping_add(3072);
+    let cvt1: u64 = mant | (0x3ffu64 << 52);
+    let mut cvt5: u64 = cvt1;
 
-    /*
-     * Round t away from zero to 23 bits (sloppily except for ensuring that
-     * the result is larger in magnitude than cbrt(x) but not much more than
-     * 2 23-bit ulps larger).  With rounding towards zero, the error bound
-     * would be ~5/6 instead of ~4/6.  With a maximum error of 2 23-bit ulps
-     * in the rounded t, the infinite-precision error in the Newton
-     * approximation barely affects third digit in the final error
-     * 0.667; the error in the rounded t can be up to about 3 23-bit ulps
-     * before the final error is larger than 0.667 ulps.
-     */
-    ui = t.to_bits();
-    ui = (ui + 0x80000000) & 0xffffffffc0000000;
-    t = f64::from_bits(ui);
+    let et: u32 = e / 3;
+    let it: u32 = e % 3;
 
-    /* one step Newton iteration to 53 bits with error < 0.667 ulps */
-    s = t * t; /* t*t is exact */
-    r = x / s; /* error <= 0.5 ulps; |r| < |t| */
-    w = t + t; /* t+t is exact */
-    r = (r - t) / (w + r); /* r-t is exact; w+r ~= 3*t */
-    t = t + t * r; /* error <= 0.5 + 0.5/3 + epsilon */
-    t
+    /* 2^(3k+it) <= x < 2^(3k+it+1), with 0 <= it <= 3 */
+    cvt5 += u64::from(it) << f64::SIG_BITS;
+    cvt5 |= sign << 63;
+    let zz: f64 = f64::from_bits(cvt5);
+
+    /* cbrt(x) = cbrt(zz)*2^(et-1365) where 1 <= zz < 8 */
+    let mut isc: u64 = ESCALE[it as usize].to_bits(); // todo: index
+    isc |= sign << 63;
+    let cvt2: u64 = isc;
+    let z: f64 = f64::from_bits(cvt1);
+
+    /* cbrt(zz) = cbrt(z)*isc, where isc encodes 1, 2^(1/3) or 2^(2/3),
+    and 1 <= z < 2 */
+    let r: f64 = 1.0 / z;
+    let rr: f64 = r * rsc[((it as usize) << 1) | sign as usize];
+    let z2: f64 = z * z;
+    let c0: f64 = C[0] + z * C[1];
+    let c2: f64 = C[2] + z * C[3];
+    let mut y: f64 = c0 + z2 * c2;
+    let mut y2: f64 = y * y;
+
+    /* y is an approximation of z^(1/3) */
+    let mut h: f64 = y2 * (y * r) - 1.0;
+
+    /* h determines the error between y and z^(1/3) */
+    y -= (h * y) * (u0 - u1 * h);
+
+    /* The correction y -= (h*y)*(u0 - u1*h) corresponds to a cubic variant
+    of Newton's method, with the function f(y) = 1-z/y^3. */
+    y *= f64::from_bits(cvt2);
+
+    /* Now y is an approximation of zz^(1/3),
+     * and rr an approximation of 1/zz. We now perform another iteration of
+     * Newton-Raphson, this time with a linear approximation only. */
+    y2 = y * y;
+    let mut y2l: f64 = y.fma(y, -y2);
+
+    /* y2 + y2l = y^2 exactly */
+    let mut y3: f64 = y2 * y;
+    let mut y3l: f64 = y.fma(y2, -y3) + y * y2l;
+
+    /* y3 + y3l approximates y^3 with about 106 bits of accuracy */
+    h = ((y3 - zz) + y3l) * rr;
+    let mut dy: f64 = h * (y * u0);
+
+    /* the approximation of zz^(1/3) is y - dy */
+    let mut y1: f64 = y - dy;
+    dy = (y - y1) - dy;
+
+    /* the approximation of zz^(1/3) is now y1 + dy, where |dy| < 1/2 ulp(y)
+     * (for rounding to nearest) */
+    let mut ady: f64 = dy.abs();
+
+    /* For directed roundings, ady0 is tiny when dy is tiny, or ady0 is near
+     * from ulp(1);
+     * for rounding to nearest, ady0 is tiny when dy is near from 1/2 ulp(1),
+     * or from 3/2 ulp(1). */
+    let mut ady0: f64 = (ady - off[round as usize]).abs();
+    let mut ady1: f64 = (ady - (hf64!("0x1p-52") + off[round as usize])).abs();
+
+    if ady0 < hf64!("0x1p-75") || ady1 < hf64!("0x1p-75") {
+        cold_path();
+
+        y2 = y1 * y1;
+        y2l = y1.fma(y1, -y2);
+        y3 = y2 * y1;
+        y3l = y1.fma(y2, -y3) + y1 * y2l;
+        h = ((y3 - zz) + y3l) * rr;
+        dy = h * (y1 * u0);
+        y = y1 - dy;
+        dy = (y1 - y) - dy;
+        y1 = y;
+        ady = dy.abs();
+        ady0 = (ady - off[round as usize]).abs();
+        ady1 = (ady - (hf64!("0x1p-52") + off[round as usize])).abs();
+
+        if ady0 < hf64!("0x1p-98") || ady1 < hf64!("0x1p-98") {
+            cold_path();
+            let azz: f64 = zz.abs();
+
+            // ~ 0x1.79d15d0e8d59b80000000000000ffc3dp+0
+            if azz == hf64!("0x1.9b78223aa307cp+1") {
+                y1 = hf64!("0x1.79d15d0e8d59cp+0").copysign(zz);
+            }
+
+            // ~ 0x1.de87aa837820e80000000000001c0f08p+0
+            if azz == hf64!("0x1.a202bfc89ddffp+2") {
+                y1 = hf64!("0x1.de87aa837820fp+0").copysign(zz);
+            }
+
+            if round != Round::Nearest {
+                let wlist = [
+                    (hf64!("0x1.3a9ccd7f022dbp+0"), hf64!("0x1.1236160ba9b93p+0")), // ~ 0x1.1236160ba9b930000000000001e7e8fap+0
+                    (hf64!("0x1.7845d2faac6fep+0"), hf64!("0x1.23115e657e49cp+0")), // ~ 0x1.23115e657e49c0000000000001d7a799p+0
+                    (hf64!("0x1.d1ef81cbbbe71p+0"), hf64!("0x1.388fb44cdcf5ap+0")), // ~ 0x1.388fb44cdcf5a0000000000002202c55p+0
+                    (hf64!("0x1.0a2014f62987cp+1"), hf64!("0x1.46bcbf47dc1e8p+0")), // ~ 0x1.46bcbf47dc1e8000000000000303aa2dp+0
+                    (hf64!("0x1.fe18a044a5501p+1"), hf64!("0x1.95decfec9c904p+0")), // ~ 0x1.95decfec9c9040000000000000159e8ep+0
+                    (hf64!("0x1.a6bb8c803147bp+2"), hf64!("0x1.e05335a6401dep+0")), // ~ 0x1.e05335a6401de00000000000027ca017p+0
+                    (hf64!("0x1.ac8538a031cbdp+2"), hf64!("0x1.e281d87098de8p+0")), // ~ 0x1.e281d87098de80000000000000ee9314p+0
+                ];
+
+                for (a, b) in wlist {
+                    if azz == a {
+                        let tmp = if round as u64 + sign == 2 {
+                            hf64!("0x1p-52")
+                        } else {
+                            0.0
+                        };
+                        y1 = (b + tmp).copysign(zz);
+                    }
+                }
+            }
+        }
+    }
+
+    let mut cvt3: u64 = y1.to_bits();
+    cvt3 = cvt3.wrapping_add(((et.wrapping_sub(342).wrapping_sub(1023)) as u64) << 52);
+    let m0: u64 = cvt3 << 30;
+    let m1 = m0 >> 63;
+
+    if (m0 ^ m1) <= (1u64 << 30) {
+        cold_path();
+
+        let mut cvt4: u64 = y1.to_bits();
+        cvt4 = (cvt4 + (164 << 15)) & 0xffffffffffff0000u64;
+
+        if ((f64::from_bits(cvt4) - y1) - dy).abs() < hf64!("0x1p-60") || (zz).abs() == 1.0 {
+            cvt3 = (cvt3 + (1u64 << 15)) & 0xffffffffffff0000u64;
+        }
+    }
+
+    FpResult::ok(f64::from_bits(cvt3))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn spot_checks() {
+        if !cfg!(x86_no_sse) {
+            // Exposes a rounding mode problem. Ignored on i586 because of inaccurate FMA.
+            assert_biteq!(
+                cbrt(f64::from_bits(0xf7f792b28f600000)),
+                f64::from_bits(0xd29ce68655d962f3)
+            );
+        }
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceil.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceil.rs
index 1593fdaf..4e10354 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceil.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceil.rs
@@ -1,75 +1,46 @@
-#![allow(unreachable_code)]
-use core::f64;
+/// Ceil (f16)
+///
+/// Finds the nearest integer greater than or equal to `x`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ceilf16(x: f16) -> f16 {
+    super::generic::ceil(x)
+}
 
-const TOINT: f64 = 1. / f64::EPSILON;
+/// Ceil (f32)
+///
+/// Finds the nearest integer greater than or equal to `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ceilf(x: f32) -> f32 {
+    select_implementation! {
+        name: ceilf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
+    }
+
+    super::generic::ceil(x)
+}
 
 /// Ceil (f64)
 ///
 /// Finds the nearest integer greater than or equal to `x`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn ceil(x: f64) -> f64 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f64.ceil` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::ceilf64(x) }
-        }
+    select_implementation! {
+        name: ceil,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
+        args: x,
     }
-    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-    {
-        //use an alternative implementation on x86, because the
-        //main implementation fails with the x87 FPU used by
-        //debian i386, probably due to excess precision issues.
-        //basic implementation taken from https://github.com/rust-lang/libm/issues/219
-        use super::fabs;
-        if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
-            let truncated = x as i64 as f64;
-            if truncated < x {
-                return truncated + 1.0;
-            } else {
-                return truncated;
-            }
-        } else {
-            return x;
-        }
-    }
-    let u: u64 = x.to_bits();
-    let e: i64 = (u >> 52 & 0x7ff) as i64;
-    let y: f64;
 
-    if e >= 0x3ff + 52 || x == 0. {
-        return x;
-    }
-    // y = int(x) - x, where int(x) is an integer neighbor of x
-    y = if (u >> 63) != 0 { x - TOINT + TOINT - x } else { x + TOINT - TOINT - x };
-    // special case because of non-nearest rounding modes
-    if e < 0x3ff {
-        force_eval!(y);
-        return if (u >> 63) != 0 { -0. } else { 1. };
-    }
-    if y < 0. { x + y + 1. } else { x + y }
+    super::generic::ceil(x)
 }
 
-#[cfg(test)]
-mod tests {
-    use core::f64::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(ceil(1.1), 2.0);
-        assert_eq!(ceil(2.9), 3.0);
-    }
-
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/ceil
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: that the current rounding mode has no effect.
-        assert!(ceil(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(ceil(f), f);
-        }
-    }
+/// Ceil (f128)
+///
+/// Finds the nearest integer greater than or equal to `x`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ceilf128(x: f128) -> f128 {
+    super::generic::ceil(x)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceilf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceilf.rs
deleted file mode 100644
index bf9ba122..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceilf.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-use core::f32;
-
-/// Ceil (f32)
-///
-/// Finds the nearest integer greater than or equal to `x`.
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn ceilf(x: f32) -> f32 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f32.ceil` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::ceilf32(x) }
-        }
-    }
-    let mut ui = x.to_bits();
-    let e = (((ui >> 23) & 0xff).wrapping_sub(0x7f)) as i32;
-
-    if e >= 23 {
-        return x;
-    }
-    if e >= 0 {
-        let m = 0x007fffff >> e;
-        if (ui & m) == 0 {
-            return x;
-        }
-        force_eval!(x + f32::from_bits(0x7b800000));
-        if ui >> 31 == 0 {
-            ui += m;
-        }
-        ui &= !m;
-    } else {
-        force_eval!(x + f32::from_bits(0x7b800000));
-        if ui >> 31 != 0 {
-            return -0.0;
-        } else if ui << 1 != 0 {
-            return 1.0;
-        }
-    }
-    f32::from_bits(ui)
-}
-
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use core::f32::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(ceilf(1.1), 2.0);
-        assert_eq!(ceilf(2.9), 3.0);
-    }
-
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/ceil
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: that the current rounding mode has no effect.
-        assert!(ceilf(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(ceilf(f), f);
-        }
-    }
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysign.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysign.rs
index 1f4a35a..d2a86e7 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysign.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysign.rs
@@ -1,12 +1,88 @@
+/// Sign of Y, magnitude of X (f16)
+///
+/// Constructs a number with the magnitude (absolute value) of its
+/// first argument, `x`, and the sign of its second argument, `y`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn copysignf16(x: f16, y: f16) -> f16 {
+    super::generic::copysign(x, y)
+}
+
+/// Sign of Y, magnitude of X (f32)
+///
+/// Constructs a number with the magnitude (absolute value) of its
+/// first argument, `x`, and the sign of its second argument, `y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn copysignf(x: f32, y: f32) -> f32 {
+    super::generic::copysign(x, y)
+}
+
 /// Sign of Y, magnitude of X (f64)
 ///
 /// Constructs a number with the magnitude (absolute value) of its
 /// first argument, `x`, and the sign of its second argument, `y`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn copysign(x: f64, y: f64) -> f64 {
-    let mut ux = x.to_bits();
-    let uy = y.to_bits();
-    ux &= (!0) >> 1;
-    ux |= uy & (1 << 63);
-    f64::from_bits(ux)
+    super::generic::copysign(x, y)
+}
+
+/// Sign of Y, magnitude of X (f128)
+///
+/// Constructs a number with the magnitude (absolute value) of its
+/// first argument, `x`, and the sign of its second argument, `y`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn copysignf128(x: f128, y: f128) -> f128 {
+    super::generic::copysign(x, y)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::Float;
+
+    fn spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        assert_biteq!(f(F::ZERO, F::ZERO), F::ZERO);
+        assert_biteq!(f(F::NEG_ZERO, F::ZERO), F::ZERO);
+        assert_biteq!(f(F::ZERO, F::NEG_ZERO), F::NEG_ZERO);
+        assert_biteq!(f(F::NEG_ZERO, F::NEG_ZERO), F::NEG_ZERO);
+
+        assert_biteq!(f(F::ONE, F::ONE), F::ONE);
+        assert_biteq!(f(F::NEG_ONE, F::ONE), F::ONE);
+        assert_biteq!(f(F::ONE, F::NEG_ONE), F::NEG_ONE);
+        assert_biteq!(f(F::NEG_ONE, F::NEG_ONE), F::NEG_ONE);
+
+        assert_biteq!(f(F::INFINITY, F::INFINITY), F::INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY, F::INFINITY), F::INFINITY);
+        assert_biteq!(f(F::INFINITY, F::NEG_INFINITY), F::NEG_INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY, F::NEG_INFINITY), F::NEG_INFINITY);
+
+        // Not required but we expect it
+        assert_biteq!(f(F::NAN, F::NAN), F::NAN);
+        assert_biteq!(f(F::NEG_NAN, F::NAN), F::NAN);
+        assert_biteq!(f(F::NAN, F::NEG_NAN), F::NEG_NAN);
+        assert_biteq!(f(F::NEG_NAN, F::NEG_NAN), F::NEG_NAN);
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        spec_test::<f16>(copysignf16);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        spec_test::<f32>(copysignf);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        spec_test::<f64>(copysign);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        spec_test::<f128>(copysignf128);
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf.rs
index 6c346e3..8b9bed4c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf.rs
@@ -4,9 +4,5 @@
 /// first argument, `x`, and the sign of its second argument, `y`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn copysignf(x: f32, y: f32) -> f32 {
-    let mut ux = x.to_bits();
-    let uy = y.to_bits();
-    ux &= 0x7fffffff;
-    ux |= uy & 0x80000000;
-    f32::from_bits(ux)
+    super::generic::copysign(x, y)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf128.rs
new file mode 100644
index 0000000..7bd81d4
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf128.rs
@@ -0,0 +1,8 @@
+/// Sign of Y, magnitude of X (f128)
+///
+/// Constructs a number with the magnitude (absolute value) of its
+/// first argument, `x`, and the sign of its second argument, `y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn copysignf128(x: f128, y: f128) -> f128 {
+    super::generic::copysign(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf16.rs
new file mode 100644
index 0000000..82065868
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf16.rs
@@ -0,0 +1,8 @@
+/// Sign of Y, magnitude of X (f16)
+///
+/// Constructs a number with the magnitude (absolute value) of its
+/// first argument, `x`, and the sign of its second argument, `y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn copysignf16(x: f16, y: f16) -> f16 {
+    super::generic::copysign(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erf.rs
index 1b634abe..5d82228 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erf.rs
@@ -306,5 +306,9 @@
     }
 
     let x1p_1022 = f64::from_bits(0x0010000000000000);
-    if sign != 0 { 2.0 - x1p_1022 } else { x1p_1022 * x1p_1022 }
+    if sign != 0 {
+        2.0 - x1p_1022
+    } else {
+        x1p_1022 * x1p_1022
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erff.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erff.rs
index 2e41183..fe15f01 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erff.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/erff.rs
@@ -218,5 +218,9 @@
     }
 
     let x1p_120 = f32::from_bits(0x03800000);
-    if sign != 0 { 2.0 - x1p_120 } else { x1p_120 * x1p_120 }
+    if sign != 0 {
+        2.0 - x1p_120
+    } else {
+        x1p_120 * x1p_120
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10.rs
index 559930e10..7c33c92 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10.rs
@@ -6,12 +6,13 @@
     1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
 ];
 
+/// Calculates 10 raised to the power of `x` (f64).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn exp10(x: f64) -> f64 {
     let (mut y, n) = modf(x);
     let u: u64 = n.to_bits();
     /* fabs(n) < 16 without raising invalid on nan */
-    if (u >> 52 & 0x7ff) < 0x3ff + 4 {
+    if ((u >> 52) & 0x7ff) < 0x3ff + 4 {
         if y == 0.0 {
             return i!(P10, ((n as isize) + 15) as usize);
         }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10f.rs
index 78630548..303045b 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp10f.rs
@@ -2,15 +2,17 @@
 
 const LN10_F32: f32 = 3.32192809488736234787031942948939;
 const LN10_F64: f64 = 3.32192809488736234787031942948939;
-const P10: &[f32] =
-    &[1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7];
+const P10: &[f32] = &[
+    1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
+];
 
+/// Calculates 10 raised to the power of `x` (f32).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn exp10f(x: f32) -> f32 {
     let (mut y, n) = modff(x);
     let u = n.to_bits();
     /* fabsf(n) < 8 without raising invalid on nan */
-    if (u >> 23 & 0xff) < 0x7f + 3 {
+    if ((u >> 23) & 0xff) < 0x7f + 3 {
         if y == 0.0 {
             return i!(P10, ((n as isize) + 7) as usize);
         }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2.rs
index dce2ab4..6e98d06 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2.rs
@@ -341,7 +341,7 @@
 
     /* Filter out exceptional cases. */
     let ui = f64::to_bits(x);
-    let ix = ui >> 32 & 0x7fffffff;
+    let ix = (ui >> 32) & 0x7fffffff;
     if ix >= 0x408ff000 {
         /* |x| >= 1022 or nan */
         if ix >= 0x40900000 && ui >> 63 == 0 {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2f.rs
index f4867b80..f452b6a 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/exp2f.rs
@@ -95,7 +95,7 @@
             /* NaN */
             return x;
         }
-        if ui >= 0x43000000 && ui < 0x80000000 {
+        if (0x43000000..0x80000000).contains(&ui) {
             /* x >= 128 */
             x *= x1p127;
             return x;
@@ -127,7 +127,7 @@
     let z: f64 = (x - uf) as f64;
     /* Compute r = exp2(y) = exp2ft[i0] * p(z). */
     let r: f64 = f64::from_bits(i!(EXP2FT, i0 as usize));
-    let t: f64 = r as f64 * z;
+    let t: f64 = r * z;
     let r: f64 = r + t * (p1 as f64 + z * p2 as f64) + t * (z * z) * (p3 as f64 + z * p4 as f64);
 
     /* Scale by 2**k */
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1.rs
index 4260850..f25153f 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1.rs
@@ -115,7 +115,7 @@
     }
     ui = ((0x3ff + k) as u64) << 52; /* 2^k */
     let twopk = f64::from_bits(ui);
-    if k < 0 || k > 56 {
+    if !(0..=56).contains(&k) {
         /* suffice to return exp(x)-1 */
         y = x - e + 1.0;
         if k == 1024 {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1f.rs
index a862fe25..63dc86e3 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expm1f.rs
@@ -115,7 +115,7 @@
         return 1. + 2. * (x - e);
     }
     let twopk = f32::from_bits(((0x7f + k) << 23) as u32); /* 2^k */
-    if (k < 0) || (k > 56) {
+    if !(0..=56).contains(&k) {
         /* suffice to return exp(x)-1 */
         let mut y = x - e + 1.;
         if k == 128 {
@@ -126,5 +126,9 @@
         return y - 1.;
     }
     let uf = f32::from_bits(((0x7f - k) << 23) as u32); /* 2^-k */
-    if k < 23 { (x - e + (1. - uf)) * twopk } else { (x - (e + uf) + 1.) * twopk }
+    if k < 23 {
+        (x - e + (1. - uf)) * twopk
+    } else {
+        (x - (e + uf) + 1.) * twopk
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabs.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabs.rs
index 3b0628a..0050a30 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabs.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabs.rs
@@ -1,42 +1,116 @@
-use core::u64;
+/// Absolute value (magnitude) (f16)
+///
+/// Calculates the absolute value (magnitude) of the argument `x`,
+/// by direct manipulation of the bit representation of `x`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fabsf16(x: f16) -> f16 {
+    super::generic::fabs(x)
+}
+
+/// Absolute value (magnitude) (f32)
+///
+/// Calculates the absolute value (magnitude) of the argument `x`,
+/// by direct manipulation of the bit representation of `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fabsf(x: f32) -> f32 {
+    select_implementation! {
+        name: fabsf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
+    }
+
+    super::generic::fabs(x)
+}
 
 /// Absolute value (magnitude) (f64)
+///
 /// Calculates the absolute value (magnitude) of the argument `x`,
 /// by direct manipulation of the bit representation of `x`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fabs(x: f64) -> f64 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f64.abs` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::fabsf64(x) }
-        }
+    select_implementation! {
+        name: fabs,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
-    f64::from_bits(x.to_bits() & (u64::MAX / 2))
+
+    super::generic::fabs(x)
+}
+
+/// Absolute value (magnitude) (f128)
+///
+/// Calculates the absolute value (magnitude) of the argument `x`,
+/// by direct manipulation of the bit representation of `x`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fabsf128(x: f128) -> f128 {
+    super::generic::fabs(x)
 }
 
 #[cfg(test)]
 mod tests {
-    use core::f64::*;
-
     use super::*;
+    use crate::support::Float;
 
-    #[test]
-    fn sanity_check() {
-        assert_eq!(fabs(-1.0), 1.0);
-        assert_eq!(fabs(2.8), 2.8);
+    /// Based on https://en.cppreference.com/w/cpp/numeric/math/fabs
+    fn spec_test<F: Float>(f: impl Fn(F) -> F) {
+        assert_biteq!(f(F::ZERO), F::ZERO);
+        assert_biteq!(f(F::NEG_ZERO), F::ZERO);
+        assert_biteq!(f(F::INFINITY), F::INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY), F::INFINITY);
+        assert!(f(F::NAN).is_nan());
+
+        // Not spec rewquired but we expect it
+        assert!(f(F::NAN).is_sign_positive());
+        assert!(f(F::from_bits(F::NAN.to_bits() | F::SIGN_MASK)).is_sign_positive());
     }
 
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
     #[test]
-    fn spec_tests() {
-        assert!(fabs(NAN).is_nan());
-        for f in [0.0, -0.0].iter().copied() {
-            assert_eq!(fabs(f), 0.0);
-        }
-        for f in [INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(fabs(f), INFINITY);
-        }
+    #[cfg(f16_enabled)]
+    fn sanity_check_f16() {
+        assert_eq!(fabsf16(-1.0f16), 1.0);
+        assert_eq!(fabsf16(2.8f16), 2.8);
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        spec_test::<f16>(fabsf16);
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_eq!(fabsf(-1.0f32), 1.0);
+        assert_eq!(fabsf(2.8f32), 2.8);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        spec_test::<f32>(fabsf);
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_eq!(fabs(-1.0f64), 1.0);
+        assert_eq!(fabs(2.8f64), 2.8);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        spec_test::<f64>(fabs);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn sanity_check_f128() {
+        assert_eq!(fabsf128(-1.0f128), 1.0);
+        assert_eq!(fabsf128(2.8f128), 2.8);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        spec_test::<f128>(fabsf128);
     }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf.rs
index f81c8ca..e5820a2 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf.rs
@@ -1,25 +1,22 @@
 /// Absolute value (magnitude) (f32)
+///
 /// Calculates the absolute value (magnitude) of the argument `x`,
 /// by direct manipulation of the bit representation of `x`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fabsf(x: f32) -> f32 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f32.abs` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::fabsf32(x) }
-        }
+    select_implementation! {
+        name: fabsf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
-    f32::from_bits(x.to_bits() & 0x7fffffff)
+
+    super::generic::fabs(x)
 }
 
 // PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
 #[cfg(not(target_arch = "powerpc64"))]
 #[cfg(test)]
 mod tests {
-    use core::f32::*;
-
     use super::*;
 
     #[test]
@@ -31,12 +28,12 @@
     /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
     #[test]
     fn spec_tests() {
-        assert!(fabsf(NAN).is_nan());
+        assert!(fabsf(f32::NAN).is_nan());
         for f in [0.0, -0.0].iter().copied() {
             assert_eq!(fabsf(f), 0.0);
         }
-        for f in [INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(fabsf(f), INFINITY);
+        for f in [f32::INFINITY, f32::NEG_INFINITY].iter().copied() {
+            assert_eq!(fabsf(f), f32::INFINITY);
         }
     }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf128.rs
new file mode 100644
index 0000000..46429ca4
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf128.rs
@@ -0,0 +1,31 @@
+/// Absolute value (magnitude) (f128)
+///
+/// Calculates the absolute value (magnitude) of the argument `x`,
+/// by direct manipulation of the bit representation of `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fabsf128(x: f128) -> f128 {
+    super::generic::fabs(x)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn sanity_check() {
+        assert_eq!(fabsf128(-1.0), 1.0);
+        assert_eq!(fabsf128(2.8), 2.8);
+    }
+
+    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
+    #[test]
+    fn spec_tests() {
+        assert!(fabsf128(f128::NAN).is_nan());
+        for f in [0.0, -0.0].iter().copied() {
+            assert_eq!(fabsf128(f), 0.0);
+        }
+        for f in [f128::INFINITY, f128::NEG_INFINITY].iter().copied() {
+            assert_eq!(fabsf128(f), f128::INFINITY);
+        }
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf16.rs
new file mode 100644
index 0000000..eee42ac
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf16.rs
@@ -0,0 +1,31 @@
+/// Absolute value (magnitude) (f16)
+///
+/// Calculates the absolute value (magnitude) of the argument `x`,
+/// by direct manipulation of the bit representation of `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fabsf16(x: f16) -> f16 {
+    super::generic::fabs(x)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn sanity_check() {
+        assert_eq!(fabsf16(-1.0), 1.0);
+        assert_eq!(fabsf16(2.8), 2.8);
+    }
+
+    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
+    #[test]
+    fn spec_tests() {
+        assert!(fabsf16(f16::NAN).is_nan());
+        for f in [0.0, -0.0].iter().copied() {
+            assert_eq!(fabsf16(f), 0.0);
+        }
+        for f in [f16::INFINITY, f16::NEG_INFINITY].iter().copied() {
+            assert_eq!(fabsf16(f), f16::INFINITY);
+        }
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdim.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdim.rs
index 0149300..082c5478 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdim.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdim.rs
@@ -1,22 +1,53 @@
-use core::f64;
+/// Positive difference (f16)
+///
+/// Determines the positive difference between arguments, returning:
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
+///
+/// A range error may occur.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fdimf16(x: f16, y: f16) -> f16 {
+    super::generic::fdim(x, y)
+}
+
+/// Positive difference (f32)
+///
+/// Determines the positive difference between arguments, returning:
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
+///
+/// A range error may occur.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fdimf(x: f32, y: f32) -> f32 {
+    super::generic::fdim(x, y)
+}
 
 /// Positive difference (f64)
 ///
 /// Determines the positive difference between arguments, returning:
-/// * x - y	if x > y, or
-/// * +0	if x <= y, or
-/// * NAN	if either argument is NAN.
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
 ///
 /// A range error may occur.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fdim(x: f64, y: f64) -> f64 {
-    if x.is_nan() {
-        x
-    } else if y.is_nan() {
-        y
-    } else if x > y {
-        x - y
-    } else {
-        0.0
-    }
+    super::generic::fdim(x, y)
+}
+
+/// Positive difference (f128)
+///
+/// Determines the positive difference between arguments, returning:
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
+///
+/// A range error may occur.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fdimf128(x: f128, y: f128) -> f128 {
+    super::generic::fdim(x, y)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf.rs
index ea0b592..367ef51 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf.rs
@@ -1,22 +1,12 @@
-use core::f32;
-
 /// Positive difference (f32)
 ///
 /// Determines the positive difference between arguments, returning:
-/// * x - y	if x > y, or
-/// * +0	if x <= y, or
-/// * NAN	if either argument is NAN.
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
 ///
 /// A range error may occur.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fdimf(x: f32, y: f32) -> f32 {
-    if x.is_nan() {
-        x
-    } else if y.is_nan() {
-        y
-    } else if x > y {
-        x - y
-    } else {
-        0.0
-    }
+    super::generic::fdim(x, y)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf128.rs
new file mode 100644
index 0000000..6f3d1d0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf128.rs
@@ -0,0 +1,12 @@
+/// Positive difference (f128)
+///
+/// Determines the positive difference between arguments, returning:
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
+///
+/// A range error may occur.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fdimf128(x: f128, y: f128) -> f128 {
+    super::generic::fdim(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf16.rs
new file mode 100644
index 0000000..37bd688
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf16.rs
@@ -0,0 +1,12 @@
+/// Positive difference (f16)
+///
+/// Determines the positive difference between arguments, returning:
+/// * x - y if x > y, or
+/// * +0    if x <= y, or
+/// * NAN   if either argument is NAN.
+///
+/// A range error may occur.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fdimf16(x: f16, y: f16) -> f16 {
+    super::generic::fdim(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fenv.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fenv.rs
deleted file mode 100644
index c91272e..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fenv.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// src: musl/src/fenv/fenv.c
-/* Dummy functions for archs lacking fenv implementation */
-
-pub(crate) const FE_UNDERFLOW: i32 = 0;
-pub(crate) const FE_INEXACT: i32 = 0;
-
-pub(crate) const FE_TONEAREST: i32 = 0;
-
-#[inline]
-pub(crate) fn feclearexcept(_mask: i32) -> i32 {
-    0
-}
-
-#[inline]
-pub(crate) fn feraiseexcept(_mask: i32) -> i32 {
-    0
-}
-
-#[inline]
-pub(crate) fn fetestexcept(_mask: i32) -> i32 {
-    0
-}
-
-#[inline]
-pub(crate) fn fegetround() -> i32 {
-    FE_TONEAREST
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floor.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floor.rs
index e8fb21e..3c5eab1 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floor.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floor.rs
@@ -1,74 +1,46 @@
-#![allow(unreachable_code)]
-use core::f64;
-
-const TOINT: f64 = 1. / f64::EPSILON;
+/// Floor (f16)
+///
+/// Finds the nearest integer less than or equal to `x`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn floorf16(x: f16) -> f16 {
+    return super::generic::floor(x);
+}
 
 /// Floor (f64)
 ///
 /// Finds the nearest integer less than or equal to `x`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn floor(x: f64) -> f64 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f64.floor` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::floorf64(x) }
-        }
+    select_implementation! {
+        name: floor,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
+        args: x,
     }
-    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-    {
-        //use an alternative implementation on x86, because the
-        //main implementation fails with the x87 FPU used by
-        //debian i386, probably due to excess precision issues.
-        //basic implementation taken from https://github.com/rust-lang/libm/issues/219
-        use super::fabs;
-        if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
-            let truncated = x as i64 as f64;
-            if truncated > x {
-                return truncated - 1.0;
-            } else {
-                return truncated;
-            }
-        } else {
-            return x;
-        }
-    }
-    let ui = x.to_bits();
-    let e = ((ui >> 52) & 0x7ff) as i32;
 
-    if (e >= 0x3ff + 52) || (x == 0.) {
-        return x;
-    }
-    /* y = int(x) - x, where int(x) is an integer neighbor of x */
-    let y = if (ui >> 63) != 0 { x - TOINT + TOINT - x } else { x + TOINT - TOINT - x };
-    /* special case because of non-nearest rounding modes */
-    if e < 0x3ff {
-        force_eval!(y);
-        return if (ui >> 63) != 0 { -1. } else { 0. };
-    }
-    if y > 0. { x + y - 1. } else { x + y }
+    return super::generic::floor(x);
 }
 
-#[cfg(test)]
-mod tests {
-    use core::f64::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(floor(1.1), 1.0);
-        assert_eq!(floor(2.9), 2.0);
+/// Floor (f32)
+///
+/// Finds the nearest integer less than or equal to `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn floorf(x: f32) -> f32 {
+    select_implementation! {
+        name: floorf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
 
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/floor
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: that the current rounding mode has no effect.
-        assert!(floor(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(floor(f), f);
-        }
-    }
+    return super::generic::floor(x);
+}
+
+/// Floor (f128)
+///
+/// Finds the nearest integer less than or equal to `x`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn floorf128(x: f128) -> f128 {
+    return super::generic::floor(x);
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf.rs
index f66cab7..16957b7 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf.rs
@@ -1,67 +1,13 @@
-use core::f32;
-
 /// Floor (f32)
 ///
 /// Finds the nearest integer less than or equal to `x`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn floorf(x: f32) -> f32 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f32.floor` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::floorf32(x) }
-        }
-    }
-    let mut ui = x.to_bits();
-    let e = (((ui >> 23) as i32) & 0xff) - 0x7f;
-
-    if e >= 23 {
-        return x;
-    }
-    if e >= 0 {
-        let m: u32 = 0x007fffff >> e;
-        if (ui & m) == 0 {
-            return x;
-        }
-        force_eval!(x + f32::from_bits(0x7b800000));
-        if ui >> 31 != 0 {
-            ui += m;
-        }
-        ui &= !m;
-    } else {
-        force_eval!(x + f32::from_bits(0x7b800000));
-        if ui >> 31 == 0 {
-            ui = 0;
-        } else if ui << 1 != 0 {
-            return -1.0;
-        }
-    }
-    f32::from_bits(ui)
-}
-
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use core::f32::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(floorf(0.5), 0.0);
-        assert_eq!(floorf(1.1), 1.0);
-        assert_eq!(floorf(2.9), 2.0);
+    select_implementation! {
+        name: floorf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
 
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/floor
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: that the current rounding mode has no effect.
-        assert!(floorf(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() {
-            assert_eq!(floorf(f), f);
-        }
-    }
+    return super::generic::floor(x);
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf128.rs
new file mode 100644
index 0000000..9a9fe41
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf128.rs
@@ -0,0 +1,7 @@
+/// Floor (f128)
+///
+/// Finds the nearest integer less than or equal to `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn floorf128(x: f128) -> f128 {
+    return super::generic::floor(x);
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf16.rs
new file mode 100644
index 0000000..f9b868e0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf16.rs
@@ -0,0 +1,7 @@
+/// Floor (f16)
+///
+/// Finds the nearest integer less than or equal to `x`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn floorf16(x: f16) -> f16 {
+    return super::generic::floor(x);
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma.rs
index bb2028f..8856e63 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma.rs
@@ -1,200 +1,371 @@
-use core::{f32, f64};
+/* SPDX-License-Identifier: MIT */
+/* origin: musl src/math/fma.c. Ported to generic Rust algorithm in 2025, TG. */
 
-use super::scalbn;
+use super::support::{DInt, FpResult, HInt, IntTy, Round, Status};
+use super::{CastFrom, CastInto, Float, Int, MinInt};
 
-const ZEROINFNAN: i32 = 0x7ff - 0x3ff - 52 - 1;
-
-struct Num {
-    m: u64,
-    e: i32,
-    sign: i32,
-}
-
-fn normalize(x: f64) -> Num {
-    let x1p63: f64 = f64::from_bits(0x43e0000000000000); // 0x1p63 === 2 ^ 63
-
-    let mut ix: u64 = x.to_bits();
-    let mut e: i32 = (ix >> 52) as i32;
-    let sign: i32 = e & 0x800;
-    e &= 0x7ff;
-    if e == 0 {
-        ix = (x * x1p63).to_bits();
-        e = (ix >> 52) as i32 & 0x7ff;
-        e = if e != 0 { e - 63 } else { 0x800 };
-    }
-    ix &= (1 << 52) - 1;
-    ix |= 1 << 52;
-    ix <<= 1;
-    e -= 0x3ff + 52 + 1;
-    Num { m: ix, e, sign }
-}
-
-#[inline]
-fn mul(x: u64, y: u64) -> (u64, u64) {
-    let t = (x as u128).wrapping_mul(y as u128);
-    ((t >> 64) as u64, t as u64)
-}
-
-/// Floating multiply add (f64)
+/// Fused multiply add (f64)
 ///
-/// Computes `(x*y)+z`, rounded as one ternary operation:
-/// Computes the value (as if) to infinite precision and rounds once to the result format,
-/// according to the rounding mode characterized by the value of FLT_ROUNDS.
+/// Computes `(x*y)+z`, rounded as one ternary operation (i.e. calculated with infinite precision).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fma(x: f64, y: f64, z: f64) -> f64 {
-    let x1p63: f64 = f64::from_bits(0x43e0000000000000); // 0x1p63 === 2 ^ 63
-    let x0_ffffff8p_63 = f64::from_bits(0x3bfffffff0000000); // 0x0.ffffff8p-63
-
-    /* normalize so top 10bits and last bit are 0 */
-    let nx = normalize(x);
-    let ny = normalize(y);
-    let nz = normalize(z);
-
-    if nx.e >= ZEROINFNAN || ny.e >= ZEROINFNAN {
-        return x * y + z;
+    select_implementation! {
+        name: fma,
+        use_arch: all(target_arch = "aarch64", target_feature = "neon"),
+        args: x, y, z,
     }
-    if nz.e >= ZEROINFNAN {
-        if nz.e > ZEROINFNAN {
-            /* z==0 */
-            return x * y + z;
+
+    fma_round(x, y, z, Round::Nearest).val
+}
+
+/// Fused multiply add (f128)
+///
+/// Computes `(x*y)+z`, rounded as one ternary operation (i.e. calculated with infinite precision).
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaf128(x: f128, y: f128, z: f128) -> f128 {
+    fma_round(x, y, z, Round::Nearest).val
+}
+
+/// Fused multiply-add that works when there is not a larger float size available. Computes
+/// `(x * y) + z`.
+#[inline]
+pub fn fma_round<F>(x: F, y: F, z: F, _round: Round) -> FpResult<F>
+where
+    F: Float,
+    F: CastFrom<F::SignedInt>,
+    F: CastFrom<i8>,
+    F::Int: HInt,
+    u32: CastInto<F::Int>,
+{
+    let one = IntTy::<F>::ONE;
+    let zero = IntTy::<F>::ZERO;
+
+    // Normalize such that the top of the mantissa is zero and we have a guard bit.
+    let nx = Norm::from_float(x);
+    let ny = Norm::from_float(y);
+    let nz = Norm::from_float(z);
+
+    if nx.is_zero_nan_inf() || ny.is_zero_nan_inf() {
+        // Value will overflow, defer to non-fused operations.
+        return FpResult::ok(x * y + z);
+    }
+
+    if nz.is_zero_nan_inf() {
+        if nz.is_zero() {
+            // Empty add component means we only need to multiply.
+            return FpResult::ok(x * y);
         }
-        return z;
+        // `z` is NaN or infinity, which sets the result.
+        return FpResult::ok(z);
     }
 
-    /* mul: r = x*y */
-    let zhi: u64;
-    let zlo: u64;
-    let (mut rhi, mut rlo) = mul(nx.m, ny.m);
-    /* either top 20 or 21 bits of rhi and last 2 bits of rlo are 0 */
+    // multiply: r = x * y
+    let zhi: F::Int;
+    let zlo: F::Int;
+    let (mut rlo, mut rhi) = nx.m.widen_mul(ny.m).lo_hi();
 
-    /* align exponents */
+    // Exponent result of multiplication
     let mut e: i32 = nx.e + ny.e;
+    // Needed shift to align `z` to the multiplication result
     let mut d: i32 = nz.e - e;
-    /* shift bits z<<=kz, r>>=kr, so kz+kr == d, set e = e+kr (== ez-kz) */
+    let sbits = F::BITS as i32;
+
+    // Scale `z`. Shift `z <<= kz`, `r >>= kr`, so `kz+kr == d`, set `e = e+kr` (== ez-kz)
     if d > 0 {
-        if d < 64 {
+        // The magnitude of `z` is larger than `x * y`
+        if d < sbits {
+            // Maximum shift of one `F::BITS` means shifted `z` will fit into `2 * F::BITS`. Shift
+            // it into `(zhi, zlo)`. No exponent adjustment necessary.
             zlo = nz.m << d;
-            zhi = nz.m >> (64 - d);
+            zhi = nz.m >> (sbits - d);
         } else {
-            zlo = 0;
+            // Shift larger than `sbits`, `z` only needs the top half `zhi`. Place it there (acts
+            // as a shift by `sbits`).
+            zlo = zero;
             zhi = nz.m;
-            e = nz.e - 64;
-            d -= 64;
+            d -= sbits;
+
+            // `z`'s exponent is large enough that it now needs to be taken into account.
+            e = nz.e - sbits;
+
             if d == 0 {
-            } else if d < 64 {
-                rlo = rhi << (64 - d) | rlo >> d | ((rlo << (64 - d)) != 0) as u64;
+                // Exactly `sbits`, nothing to do
+            } else if d < sbits {
+                // Remaining shift fits within `sbits`. Leave `z` in place, shift `x * y`
+                rlo = (rhi << (sbits - d)) | (rlo >> d);
+                // Set the sticky bit
+                rlo |= IntTy::<F>::from((rlo << (sbits - d)) != zero);
                 rhi = rhi >> d;
             } else {
-                rlo = 1;
-                rhi = 0;
+                // `z`'s magnitude is enough that `x * y` is irrelevant. It was nonzero, so set
+                // the sticky bit.
+                rlo = one;
+                rhi = zero;
             }
         }
     } else {
-        zhi = 0;
+        // `z`'s magnitude once shifted fits entirely within `zlo`
+        zhi = zero;
         d = -d;
         if d == 0 {
+            // No shift needed
             zlo = nz.m;
-        } else if d < 64 {
-            zlo = nz.m >> d | ((nz.m << (64 - d)) != 0) as u64;
+        } else if d < sbits {
+            // Shift s.t. `nz.m` fits into `zlo`
+            let sticky = IntTy::<F>::from((nz.m << (sbits - d)) != zero);
+            zlo = (nz.m >> d) | sticky;
         } else {
-            zlo = 1;
+            // Would be entirely shifted out, only set the sticky bit
+            zlo = one;
         }
     }
 
-    /* add */
-    let mut sign: i32 = nx.sign ^ ny.sign;
-    let samesign: bool = (sign ^ nz.sign) == 0;
-    let mut nonzero: i32 = 1;
+    /* addition */
+
+    let mut neg = nx.neg ^ ny.neg;
+    let samesign: bool = !neg ^ nz.neg;
+    let mut rhi_nonzero = true;
+
     if samesign {
-        /* r += z */
+        // r += z
         rlo = rlo.wrapping_add(zlo);
-        rhi += zhi + (rlo < zlo) as u64;
+        rhi += zhi + IntTy::<F>::from(rlo < zlo);
     } else {
-        /* r -= z */
+        // r -= z
         let (res, borrow) = rlo.overflowing_sub(zlo);
         rlo = res;
-        rhi = rhi.wrapping_sub(zhi.wrapping_add(borrow as u64));
-        if (rhi >> 63) != 0 {
-            rlo = (rlo as i64).wrapping_neg() as u64;
-            rhi = (rhi as i64).wrapping_neg() as u64 - (rlo != 0) as u64;
-            sign = (sign == 0) as i32;
+        rhi = rhi.wrapping_sub(zhi.wrapping_add(IntTy::<F>::from(borrow)));
+        if (rhi >> (F::BITS - 1)) != zero {
+            rlo = rlo.signed().wrapping_neg().unsigned();
+            rhi = rhi.signed().wrapping_neg().unsigned() - IntTy::<F>::from(rlo != zero);
+            neg = !neg;
         }
-        nonzero = (rhi != 0) as i32;
+        rhi_nonzero = rhi != zero;
     }
 
-    /* set rhi to top 63bit of the result (last bit is sticky) */
-    if nonzero != 0 {
-        e += 64;
+    /* Construct result */
+
+    // Shift result into `rhi`, left-aligned. Last bit is sticky
+    if rhi_nonzero {
+        // `d` > 0, need to shift both `rhi` and `rlo` into result
+        e += sbits;
         d = rhi.leading_zeros() as i32 - 1;
-        /* note: d > 0 */
-        rhi = rhi << d | rlo >> (64 - d) | ((rlo << d) != 0) as u64;
-    } else if rlo != 0 {
+        rhi = (rhi << d) | (rlo >> (sbits - d));
+        // Update sticky
+        rhi |= IntTy::<F>::from((rlo << d) != zero);
+    } else if rlo != zero {
+        // `rhi` is zero, `rlo` is the entire result and needs to be shifted
         d = rlo.leading_zeros() as i32 - 1;
         if d < 0 {
-            rhi = rlo >> 1 | (rlo & 1);
+            // Shift and set sticky
+            rhi = (rlo >> 1) | (rlo & one);
         } else {
             rhi = rlo << d;
         }
     } else {
-        /* exact +-0 */
-        return x * y + z;
+        // exact +/- 0.0
+        return FpResult::ok(x * y + z);
     }
+
     e -= d;
 
-    /* convert to double */
-    let mut i: i64 = rhi as i64; /* i is in [1<<62,(1<<63)-1] */
-    if sign != 0 {
+    // Use int->float conversion to populate the significand.
+    // i is in [1 << (BITS - 2), (1 << (BITS - 1)) - 1]
+    let mut i: F::SignedInt = rhi.signed();
+
+    if neg {
         i = -i;
     }
-    let mut r: f64 = i as f64; /* |r| is in [0x1p62,0x1p63] */
 
-    if e < -1022 - 62 {
-        /* result is subnormal before rounding */
-        if e == -1022 - 63 {
-            let mut c: f64 = x1p63;
-            if sign != 0 {
+    // `|r|` is in `[0x1p62,0x1p63]` for `f64`
+    let mut r: F = F::cast_from_lossy(i);
+
+    /* Account for subnormal and rounding */
+
+    // Unbiased exponent for the maximum value of `r`
+    let max_pow = F::BITS - 1 + F::EXP_BIAS;
+
+    let mut status = Status::OK;
+
+    if e < -(max_pow as i32 - 2) {
+        // Result is subnormal before rounding
+        if e == -(max_pow as i32 - 1) {
+            let mut c = F::from_parts(false, max_pow, zero);
+            if neg {
                 c = -c;
             }
+
             if r == c {
-                /* min normal after rounding, underflow depends
-                on arch behaviour which can be imitated by
-                a double to float conversion */
-                let fltmin: f32 = (x0_ffffff8p_63 * f32::MIN_POSITIVE as f64 * r) as f32;
-                return f64::MIN_POSITIVE / f32::MIN_POSITIVE as f64 * fltmin as f64;
+                // Min normal after rounding,
+                status.set_underflow(true);
+                r = F::MIN_POSITIVE_NORMAL.copysign(r);
+                return FpResult::new(r, status);
             }
-            /* one bit is lost when scaled, add another top bit to
-            only round once at conversion if it is inexact */
-            if (rhi << 53) != 0 {
-                i = (rhi >> 1 | (rhi & 1) | 1 << 62) as i64;
-                if sign != 0 {
+
+            if (rhi << (F::SIG_BITS + 1)) != zero {
+                // Account for truncated bits. One bit will be lost in the `scalbn` call, add
+                // another top bit to avoid double rounding if inexact.
+                let iu: F::Int = (rhi >> 1) | (rhi & one) | (one << (F::BITS - 2));
+                i = iu.signed();
+
+                if neg {
                     i = -i;
                 }
-                r = i as f64;
-                r = 2. * r - c; /* remove top bit */
 
-                /* raise underflow portably, such that it
-                cannot be optimized away */
-                {
-                    let tiny: f64 = f64::MIN_POSITIVE / f32::MIN_POSITIVE as f64 * r;
-                    r += (tiny * tiny) * (r - r);
-                }
+                r = F::cast_from_lossy(i);
+
+                // Remove the top bit
+                r = F::cast_from(2i8) * r - c;
+                status.set_underflow(true);
             }
         } else {
-            /* only round once when scaled */
-            d = 10;
-            i = ((rhi >> d | ((rhi << (64 - d)) != 0) as u64) << d) as i64;
-            if sign != 0 {
+            // Only round once when scaled
+            d = F::EXP_BITS as i32 - 1;
+            let sticky = IntTy::<F>::from(rhi << (F::BITS as i32 - d) != zero);
+            i = (((rhi >> d) | sticky) << d).signed();
+
+            if neg {
                 i = -i;
             }
-            r = i as f64;
+
+            r = F::cast_from_lossy(i);
         }
     }
-    scalbn(r, e)
+
+    // Use our exponent to scale the final value.
+    FpResult::new(super::generic::scalbn(r, e), status)
+}
+
+/// Representation of `F` that has handled subnormals.
+#[derive(Clone, Copy, Debug)]
+struct Norm<F: Float> {
+    /// Normalized significand with one guard bit, unsigned.
+    m: F::Int,
+    /// Exponent of the mantissa such that `m * 2^e = x`. Accounts for the shift in the mantissa
+    /// and the guard bit; that is, 1.0 will normalize as `m = 1 << 53` and `e = -53`.
+    e: i32,
+    neg: bool,
+}
+
+impl<F: Float> Norm<F> {
+    /// Unbias the exponent and account for the mantissa's precision, including the guard bit.
+    const EXP_UNBIAS: u32 = F::EXP_BIAS + F::SIG_BITS + 1;
+
+    /// Values greater than this had a saturated exponent (infinity or NaN), OR were zero and we
+    /// adjusted the exponent such that it exceeds this threashold.
+    const ZERO_INF_NAN: u32 = F::EXP_SAT - Self::EXP_UNBIAS;
+
+    fn from_float(x: F) -> Self {
+        let mut ix = x.to_bits();
+        let mut e = x.ex() as i32;
+        let neg = x.is_sign_negative();
+        if e == 0 {
+            // Normalize subnormals by multiplication
+            let scale_i = F::BITS - 1;
+            let scale_f = F::from_parts(false, scale_i + F::EXP_BIAS, F::Int::ZERO);
+            let scaled = x * scale_f;
+            ix = scaled.to_bits();
+            e = scaled.ex() as i32;
+            e = if e == 0 {
+                // If the exponent is still zero, the input was zero. Artifically set this value
+                // such that the final `e` will exceed `ZERO_INF_NAN`.
+                1 << F::EXP_BITS
+            } else {
+                // Otherwise, account for the scaling we just did.
+                e - scale_i as i32
+            };
+        }
+
+        e -= Self::EXP_UNBIAS as i32;
+
+        // Absolute  value, set the implicit bit, and shift to create a guard bit
+        ix &= F::SIG_MASK;
+        ix |= F::IMPLICIT_BIT;
+        ix <<= 1;
+
+        Self { m: ix, e, neg }
+    }
+
+    /// True if the value was zero, infinity, or NaN.
+    fn is_zero_nan_inf(self) -> bool {
+        self.e >= Self::ZERO_INF_NAN as i32
+    }
+
+    /// The only value we have
+    fn is_zero(self) -> bool {
+        // The only exponent that strictly exceeds this value is our sentinel value for zero.
+        self.e > Self::ZERO_INF_NAN as i32
+    }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
+
+    /// Test the generic `fma_round` algorithm for a given float.
+    fn spec_test<F>()
+    where
+        F: Float,
+        F: CastFrom<F::SignedInt>,
+        F: CastFrom<i8>,
+        F::Int: HInt,
+        u32: CastInto<F::Int>,
+    {
+        let x = F::from_bits(F::Int::ONE);
+        let y = F::from_bits(F::Int::ONE);
+        let z = F::ZERO;
+
+        let fma = |x, y, z| fma_round(x, y, z, Round::Nearest).val;
+
+        // 754-2020 says "When the exact result of (a × b) + c is non-zero yet the result of
+        // fusedMultiplyAdd is zero because of rounding, the zero result takes the sign of the
+        // exact result"
+        assert_biteq!(fma(x, y, z), F::ZERO);
+        assert_biteq!(fma(x, -y, z), F::NEG_ZERO);
+        assert_biteq!(fma(-x, y, z), F::NEG_ZERO);
+        assert_biteq!(fma(-x, -y, z), F::ZERO);
+    }
+
+    #[test]
+    fn spec_test_f32() {
+        spec_test::<f32>();
+    }
+
+    #[test]
+    fn spec_test_f64() {
+        spec_test::<f64>();
+
+        let expect_underflow = [
+            (
+                hf64!("0x1.0p-1070"),
+                hf64!("0x1.0p-1070"),
+                hf64!("0x1.ffffffffffffp-1023"),
+                hf64!("0x0.ffffffffffff8p-1022"),
+            ),
+            (
+                // FIXME: we raise underflow but this should only be inexact (based on C and
+                // `rustc_apfloat`).
+                hf64!("0x1.0p-1070"),
+                hf64!("0x1.0p-1070"),
+                hf64!("-0x1.0p-1022"),
+                hf64!("-0x1.0p-1022"),
+            ),
+        ];
+
+        for (x, y, z, res) in expect_underflow {
+            let FpResult { val, status } = fma_round(x, y, z, Round::Nearest);
+            assert_biteq!(val, res);
+            assert_eq!(status, Status::UNDERFLOW);
+        }
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_test_f128() {
+        spec_test::<f128>();
+    }
+
     #[test]
     fn fma_segfault() {
         // These two inputs cause fma to segfault on release due to overflow:
@@ -216,11 +387,17 @@
 
     #[test]
     fn fma_sbb() {
-        assert_eq!(fma(-(1.0 - f64::EPSILON), f64::MIN, f64::MIN), -3991680619069439e277);
+        assert_eq!(
+            fma(-(1.0 - f64::EPSILON), f64::MIN, f64::MIN),
+            -3991680619069439e277
+        );
     }
 
     #[test]
     fn fma_underflow() {
-        assert_eq!(fma(1.1102230246251565e-16, -9.812526705433188e-305, 1.0894e-320), 0.0,);
+        assert_eq!(
+            fma(1.1102230246251565e-16, -9.812526705433188e-305, 1.0894e-320),
+            0.0,
+        );
     }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma_wide.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma_wide.rs
new file mode 100644
index 0000000..f268c2f
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma_wide.rs
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: MIT */
+/* origin: musl src/math/fmaf.c. Ported to generic Rust algorithm in 2025, TG. */
+
+use super::support::{FpResult, IntTy, Round, Status};
+use super::{CastFrom, CastInto, DFloat, Float, HFloat, MinInt};
+
+// Placeholder so we can have `fmaf16` in the `Float` trait.
+#[allow(unused)]
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub(crate) fn fmaf16(_x: f16, _y: f16, _z: f16) -> f16 {
+    unimplemented!()
+}
+
+/// Floating multiply add (f32)
+///
+/// Computes `(x*y)+z`, rounded as one ternary operation (i.e. calculated with infinite precision).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaf(x: f32, y: f32, z: f32) -> f32 {
+    select_implementation! {
+        name: fmaf,
+        use_arch: all(target_arch = "aarch64", target_feature = "neon"),
+        args: x, y, z,
+    }
+
+    fma_wide_round(x, y, z, Round::Nearest).val
+}
+
+/// Fma implementation when a hardware-backed larger float type is available. For `f32` and `f64`,
+/// `f64` has enough precision to represent the `f32` in its entirety, except for double rounding.
+#[inline]
+pub fn fma_wide_round<F, B>(x: F, y: F, z: F, round: Round) -> FpResult<F>
+where
+    F: Float + HFloat<D = B>,
+    B: Float + DFloat<H = F>,
+    B::Int: CastInto<i32>,
+    i32: CastFrom<i32>,
+{
+    let one = IntTy::<B>::ONE;
+
+    let xy: B = x.widen() * y.widen();
+    let mut result: B = xy + z.widen();
+    let mut ui: B::Int = result.to_bits();
+    let re = result.ex();
+    let zb: B = z.widen();
+
+    let prec_diff = B::SIG_BITS - F::SIG_BITS;
+    let excess_prec = ui & ((one << prec_diff) - one);
+    let halfway = one << (prec_diff - 1);
+
+    // Common case: the larger precision is fine if...
+    // This is not a halfway case
+    if excess_prec != halfway
+        // Or the result is NaN
+        || re == B::EXP_SAT
+        // Or the result is exact
+        || (result - xy == zb && result - zb == xy)
+        // Or the mode is something other than round to nearest
+        || round != Round::Nearest
+    {
+        let min_inexact_exp = (B::EXP_BIAS as i32 + F::EXP_MIN_SUBNORM) as u32;
+        let max_inexact_exp = (B::EXP_BIAS as i32 + F::EXP_MIN) as u32;
+
+        let mut status = Status::OK;
+
+        if (min_inexact_exp..max_inexact_exp).contains(&re) && status.inexact() {
+            // This branch is never hit; requires previous operations to set a status
+            status.set_inexact(false);
+
+            result = xy + z.widen();
+            if status.inexact() {
+                status.set_underflow(true);
+            } else {
+                status.set_inexact(true);
+            }
+        }
+
+        return FpResult {
+            val: result.narrow(),
+            status,
+        };
+    }
+
+    let neg = ui >> (B::BITS - 1) != IntTy::<B>::ZERO;
+    let err = if neg == (zb > xy) {
+        xy - result + zb
+    } else {
+        zb - result + xy
+    };
+    if neg == (err < B::ZERO) {
+        ui += one;
+    } else {
+        ui -= one;
+    }
+
+    FpResult::ok(B::from_bits(ui).narrow())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn issue_263() {
+        let a = f32::from_bits(1266679807);
+        let b = f32::from_bits(1300234242);
+        let c = f32::from_bits(1115553792);
+        let expected = f32::from_bits(1501560833);
+        assert_eq!(fmaf(a, b, c), expected);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaf.rs
deleted file mode 100644
index 10bdaeab..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaf.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-/* origin: FreeBSD /usr/src/lib/msun/src/s_fmaf.c */
-/*-
- * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-use core::f32;
-use core::ptr::read_volatile;
-
-use super::fenv::{
-    FE_INEXACT, FE_TONEAREST, FE_UNDERFLOW, feclearexcept, fegetround, feraiseexcept, fetestexcept,
-};
-
-/*
- * Fused multiply-add: Compute x * y + z with a single rounding error.
- *
- * A double has more than twice as much precision than a float, so
- * direct double-precision arithmetic suffices, except where double
- * rounding occurs.
- */
-
-/// Floating multiply add (f32)
-///
-/// Computes `(x*y)+z`, rounded as one ternary operation:
-/// Computes the value (as if) to infinite precision and rounds once to the result format,
-/// according to the rounding mode characterized by the value of FLT_ROUNDS.
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn fmaf(x: f32, y: f32, mut z: f32) -> f32 {
-    let xy: f64;
-    let mut result: f64;
-    let mut ui: u64;
-    let e: i32;
-
-    xy = x as f64 * y as f64;
-    result = xy + z as f64;
-    ui = result.to_bits();
-    e = (ui >> 52) as i32 & 0x7ff;
-    /* Common case: The double precision result is fine. */
-    if (
-        /* not a halfway case */
-        ui & 0x1fffffff) != 0x10000000 ||
-        /* NaN */
-        e == 0x7ff ||
-        /* exact */
-        (result - xy == z as f64 && result - z as f64 == xy) ||
-        /* not round-to-nearest */
-        fegetround() != FE_TONEAREST
-    {
-        /*
-            underflow may not be raised correctly, example:
-            fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f)
-        */
-        if e < 0x3ff - 126 && e >= 0x3ff - 149 && fetestexcept(FE_INEXACT) != 0 {
-            feclearexcept(FE_INEXACT);
-            // prevent `xy + vz` from being CSE'd with `xy + z` above
-            let vz: f32 = unsafe { read_volatile(&z) };
-            result = xy + vz as f64;
-            if fetestexcept(FE_INEXACT) != 0 {
-                feraiseexcept(FE_UNDERFLOW);
-            } else {
-                feraiseexcept(FE_INEXACT);
-            }
-        }
-        z = result as f32;
-        return z;
-    }
-
-    /*
-     * If result is inexact, and exactly halfway between two float values,
-     * we need to adjust the low-order bit in the direction of the error.
-     */
-    let neg = ui >> 63 != 0;
-    let err = if neg == (z as f64 > xy) { xy - result + z as f64 } else { z as f64 - result + xy };
-    if neg == (err < 0.0) {
-        ui += 1;
-    } else {
-        ui -= 1;
-    }
-    f64::from_bits(ui) as f32
-}
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn issue_263() {
-        let a = f32::from_bits(1266679807);
-        let b = f32::from_bits(1300234242);
-        let c = f32::from_bits(1115553792);
-        let expected = f32::from_bits(1501560833);
-        assert_eq!(super::fmaf(a, b, c), expected);
-    }
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmax.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmax.rs
deleted file mode 100644
index 93c97bc..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmax.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn fmax(x: f64, y: f64) -> f64 {
-    // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
-    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-    // is either x or y, canonicalized (this means results might differ among implementations).
-    // When either x or y is a signalingNaN, then the result is according to 6.2.
-    //
-    // Since we do not support sNaN in Rust yet, we do not need to handle them.
-    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-    (if x.is_nan() || x < y { y } else { x }) * 1.0
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaxf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaxf.rs
deleted file mode 100644
index 6077466..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaxf.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn fmaxf(x: f32, y: f32) -> f32 {
-    // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
-    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-    // is either x or y, canonicalized (this means results might differ among implementations).
-    // When either x or y is a signalingNaN, then the result is according to 6.2.
-    //
-    // Since we do not support sNaN in Rust yet, we do not need to handle them.
-    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-    (if x.is_nan() || x < y { y } else { x }) * 1.0
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin.rs
deleted file mode 100644
index ab1509f..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn fmin(x: f64, y: f64) -> f64 {
-    // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
-    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-    // is either x or y, canonicalized (this means results might differ among implementations).
-    // When either x or y is a signalingNaN, then the result is according to 6.2.
-    //
-    // Since we do not support sNaN in Rust yet, we do not need to handle them.
-    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-    (if y.is_nan() || x < y { x } else { y }) * 1.0
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin_fmax.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin_fmax.rs
new file mode 100644
index 0000000..2947b78
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin_fmax.rs
@@ -0,0 +1,167 @@
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminf16(x: f16, y: f16) -> f16 {
+    super::generic::fmin(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminf(x: f32, y: f32) -> f32 {
+    super::generic::fmin(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmin(x: f64, y: f64) -> f64 {
+    super::generic::fmin(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminf128(x: f128, y: f128) -> f128 {
+    super::generic::fmin(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaxf16(x: f16, y: f16) -> f16 {
+    super::generic::fmax(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaxf(x: f32, y: f32) -> f32 {
+    super::generic::fmax(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmax(x: f64, y: f64) -> f64 {
+    super::generic::fmax(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
+/// the inputs are -0.0 and +0.0, either may be returned).
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaxf128(x: f128, y: f128) -> f128 {
+    super::generic::fmax(x, y)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::{Float, Hexf};
+
+    fn fmin_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ZERO),
+            (F::ONE, F::ZERO, F::ZERO),
+            (F::ZERO, F::NEG_ONE, F::NEG_ONE),
+            (F::NEG_ONE, F::ZERO, F::NEG_ONE),
+            (F::INFINITY, F::ZERO, F::ZERO),
+            (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
+            (F::NAN, F::ZERO, F::ZERO),
+            (F::ZERO, F::NAN, F::ZERO),
+            (F::NAN, F::NAN, F::NAN),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fmin({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fmin_spec_tests_f16() {
+        fmin_spec_test::<f16>(fminf16);
+    }
+
+    #[test]
+    fn fmin_spec_tests_f32() {
+        fmin_spec_test::<f32>(fminf);
+    }
+
+    #[test]
+    fn fmin_spec_tests_f64() {
+        fmin_spec_test::<f64>(fmin);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fmin_spec_tests_f128() {
+        fmin_spec_test::<f128>(fminf128);
+    }
+
+    fn fmax_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ONE),
+            (F::ONE, F::ZERO, F::ONE),
+            (F::ZERO, F::NEG_ONE, F::ZERO),
+            (F::NEG_ONE, F::ZERO, F::ZERO),
+            (F::INFINITY, F::ZERO, F::INFINITY),
+            (F::NEG_INFINITY, F::ZERO, F::ZERO),
+            (F::NAN, F::ZERO, F::ZERO),
+            (F::ZERO, F::NAN, F::ZERO),
+            (F::NAN, F::NAN, F::NAN),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fmax({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fmax_spec_tests_f16() {
+        fmax_spec_test::<f16>(fmaxf16);
+    }
+
+    #[test]
+    fn fmax_spec_tests_f32() {
+        fmax_spec_test::<f32>(fmaxf);
+    }
+
+    #[test]
+    fn fmax_spec_tests_f64() {
+        fmax_spec_test::<f64>(fmax);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fmax_spec_tests_f128() {
+        fmax_spec_test::<f128>(fmaxf128);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminf.rs
deleted file mode 100644
index 0049e711..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminf.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn fminf(x: f32, y: f32) -> f32 {
-    // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
-    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
-    // is either x or y, canonicalized (this means results might differ among implementations).
-    // When either x or y is a signalingNaN, then the result is according to 6.2.
-    //
-    // Since we do not support sNaN in Rust yet, we do not need to handle them.
-    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
-    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
-    (if y.is_nan() || x < y { x } else { y }) * 1.0
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum.rs
new file mode 100644
index 0000000..b7999e2
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum.rs
@@ -0,0 +1,163 @@
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `minimum`. The result orders -0.0 < 0.0.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimumf16(x: f16, y: f16) -> f16 {
+    super::generic::fminimum(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `minimum`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimum(x: f64, y: f64) -> f64 {
+    super::generic::fminimum(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `minimum`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimumf(x: f32, y: f32) -> f32 {
+    super::generic::fminimum(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `minimum`. The result orders -0.0 < 0.0.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimumf128(x: f128, y: f128) -> f128 {
+    super::generic::fminimum(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `maximum`. The result orders -0.0 < 0.0.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximumf16(x: f16, y: f16) -> f16 {
+    super::generic::fmaximum(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `maximum`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximumf(x: f32, y: f32) -> f32 {
+    super::generic::fmaximum(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `maximum`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximum(x: f64, y: f64) -> f64 {
+    super::generic::fmaximum(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, the other argument.
+///
+/// This coincides with IEEE 754-2019 `maximum`. The result orders -0.0 < 0.0.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximumf128(x: f128, y: f128) -> f128 {
+    super::generic::fmaximum(x, y)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::{Float, Hexf};
+
+    fn fminimum_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ZERO),
+            (F::ONE, F::ZERO, F::ZERO),
+            (F::ZERO, F::NEG_ONE, F::NEG_ONE),
+            (F::NEG_ONE, F::ZERO, F::NEG_ONE),
+            (F::INFINITY, F::ZERO, F::ZERO),
+            (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
+            (F::NAN, F::ZERO, F::NAN),
+            (F::ZERO, F::NAN, F::NAN),
+            (F::NAN, F::NAN, F::NAN),
+            (F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
+            (F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fminimum({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fminimum_spec_tests_f16() {
+        fminimum_spec_test::<f16>(fminimumf16);
+    }
+
+    #[test]
+    fn fminimum_spec_tests_f32() {
+        fminimum_spec_test::<f32>(fminimumf);
+    }
+
+    #[test]
+    fn fminimum_spec_tests_f64() {
+        fminimum_spec_test::<f64>(fminimum);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fminimum_spec_tests_f128() {
+        fminimum_spec_test::<f128>(fminimumf128);
+    }
+
+    fn fmaximum_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ONE),
+            (F::ONE, F::ZERO, F::ONE),
+            (F::ZERO, F::NEG_ONE, F::ZERO),
+            (F::NEG_ONE, F::ZERO, F::ZERO),
+            (F::INFINITY, F::ZERO, F::INFINITY),
+            (F::NEG_INFINITY, F::ZERO, F::ZERO),
+            (F::NAN, F::ZERO, F::NAN),
+            (F::ZERO, F::NAN, F::NAN),
+            (F::NAN, F::NAN, F::NAN),
+            (F::ZERO, F::NEG_ZERO, F::ZERO),
+            (F::NEG_ZERO, F::ZERO, F::ZERO),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fmaximum({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fmaximum_spec_tests_f16() {
+        fmaximum_spec_test::<f16>(fmaximumf16);
+    }
+
+    #[test]
+    fn fmaximum_spec_tests_f32() {
+        fmaximum_spec_test::<f32>(fmaximumf);
+    }
+
+    #[test]
+    fn fmaximum_spec_tests_f64() {
+        fmaximum_spec_test::<f64>(fmaximum);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fmaximum_spec_tests_f128() {
+        fmaximum_spec_test::<f128>(fmaximumf128);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum_num.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum_num.rs
new file mode 100644
index 0000000..180d21f
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum_num.rs
@@ -0,0 +1,163 @@
+/// Return the lesser of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `minimumNumber`. The result orders -0.0 < 0.0.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimum_numf16(x: f16, y: f16) -> f16 {
+    super::generic::fminimum_num(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `minimumNumber`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimum_numf(x: f32, y: f32) -> f32 {
+    super::generic::fminimum_num(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `minimumNumber`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimum_num(x: f64, y: f64) -> f64 {
+    super::generic::fminimum_num(x, y)
+}
+
+/// Return the lesser of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `minimumNumber`. The result orders -0.0 < 0.0.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fminimum_numf128(x: f128, y: f128) -> f128 {
+    super::generic::fminimum_num(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `maximumNumber`. The result orders -0.0 < 0.0.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximum_numf16(x: f16, y: f16) -> f16 {
+    super::generic::fmaximum_num(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `maximumNumber`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximum_numf(x: f32, y: f32) -> f32 {
+    super::generic::fmaximum_num(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `maximumNumber`. The result orders -0.0 < 0.0.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximum_num(x: f64, y: f64) -> f64 {
+    super::generic::fmaximum_num(x, y)
+}
+
+/// Return the greater of two arguments or, if either argument is NaN, NaN.
+///
+/// This coincides with IEEE 754-2019 `maximumNumber`. The result orders -0.0 < 0.0.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmaximum_numf128(x: f128, y: f128) -> f128 {
+    super::generic::fmaximum_num(x, y)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::{Float, Hexf};
+
+    fn fminimum_num_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ZERO),
+            (F::ONE, F::ZERO, F::ZERO),
+            (F::ZERO, F::NEG_ONE, F::NEG_ONE),
+            (F::NEG_ONE, F::ZERO, F::NEG_ONE),
+            (F::INFINITY, F::ZERO, F::ZERO),
+            (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
+            (F::NAN, F::ZERO, F::ZERO),
+            (F::ZERO, F::NAN, F::ZERO),
+            (F::NAN, F::NAN, F::NAN),
+            (F::ZERO, F::NEG_ZERO, F::NEG_ZERO),
+            (F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fminimum_num({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fminimum_num_spec_tests_f16() {
+        fminimum_num_spec_test::<f16>(fminimum_numf16);
+    }
+
+    #[test]
+    fn fminimum_num_spec_tests_f32() {
+        fminimum_num_spec_test::<f32>(fminimum_numf);
+    }
+
+    #[test]
+    fn fminimum_num_spec_tests_f64() {
+        fminimum_num_spec_test::<f64>(fminimum_num);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fminimum_num_spec_tests_f128() {
+        fminimum_num_spec_test::<f128>(fminimum_numf128);
+    }
+
+    fn fmaximum_num_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
+        let cases = [
+            (F::ZERO, F::ZERO, F::ZERO),
+            (F::ONE, F::ONE, F::ONE),
+            (F::ZERO, F::ONE, F::ONE),
+            (F::ONE, F::ZERO, F::ONE),
+            (F::ZERO, F::NEG_ONE, F::ZERO),
+            (F::NEG_ONE, F::ZERO, F::ZERO),
+            (F::INFINITY, F::ZERO, F::INFINITY),
+            (F::NEG_INFINITY, F::ZERO, F::ZERO),
+            (F::NAN, F::ZERO, F::ZERO),
+            (F::ZERO, F::NAN, F::ZERO),
+            (F::NAN, F::NAN, F::NAN),
+            (F::ZERO, F::NEG_ZERO, F::ZERO),
+            (F::NEG_ZERO, F::ZERO, F::ZERO),
+        ];
+
+        for (x, y, res) in cases {
+            let val = f(x, y);
+            assert_biteq!(val, res, "fmaximum_num({}, {})", Hexf(x), Hexf(y));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn fmaximum_num_spec_tests_f16() {
+        fmaximum_num_spec_test::<f16>(fmaximum_numf16);
+    }
+
+    #[test]
+    fn fmaximum_num_spec_tests_f32() {
+        fmaximum_num_spec_test::<f32>(fmaximum_numf);
+    }
+
+    #[test]
+    fn fmaximum_num_spec_tests_f64() {
+        fmaximum_num_spec_test::<f64>(fmaximum_num);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn fmaximum_num_spec_tests_f128() {
+        fmaximum_num_spec_test::<f128>(fmaximum_numf128);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmod.rs
index d892ffd..c4752b9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmod.rs
@@ -1,80 +1,25 @@
-use core::u64;
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmodf16(x: f16, y: f16) -> f16 {
+    super::generic::fmod(x, y)
+}
 
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmodf(x: f32, y: f32) -> f32 {
+    super::generic::fmod(x, y)
+}
+
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fmod(x: f64, y: f64) -> f64 {
-    let mut uxi = x.to_bits();
-    let mut uyi = y.to_bits();
-    let mut ex = (uxi >> 52 & 0x7ff) as i64;
-    let mut ey = (uyi >> 52 & 0x7ff) as i64;
-    let sx = uxi >> 63;
-    let mut i;
+    super::generic::fmod(x, y)
+}
 
-    if uyi << 1 == 0 || y.is_nan() || ex == 0x7ff {
-        return (x * y) / (x * y);
-    }
-    if uxi << 1 <= uyi << 1 {
-        if uxi << 1 == uyi << 1 {
-            return 0.0 * x;
-        }
-        return x;
-    }
-
-    /* normalize x and y */
-    if ex == 0 {
-        i = uxi << 12;
-        while i >> 63 == 0 {
-            ex -= 1;
-            i <<= 1;
-        }
-        uxi <<= -ex + 1;
-    } else {
-        uxi &= u64::MAX >> 12;
-        uxi |= 1 << 52;
-    }
-    if ey == 0 {
-        i = uyi << 12;
-        while i >> 63 == 0 {
-            ey -= 1;
-            i <<= 1;
-        }
-        uyi <<= -ey + 1;
-    } else {
-        uyi &= u64::MAX >> 12;
-        uyi |= 1 << 52;
-    }
-
-    /* x mod y */
-    while ex > ey {
-        i = uxi.wrapping_sub(uyi);
-        if i >> 63 == 0 {
-            if i == 0 {
-                return 0.0 * x;
-            }
-            uxi = i;
-        }
-        uxi <<= 1;
-        ex -= 1;
-    }
-    i = uxi.wrapping_sub(uyi);
-    if i >> 63 == 0 {
-        if i == 0 {
-            return 0.0 * x;
-        }
-        uxi = i;
-    }
-    while uxi >> 52 == 0 {
-        uxi <<= 1;
-        ex -= 1;
-    }
-
-    /* scale result */
-    if ex > 0 {
-        uxi -= 1 << 52;
-        uxi |= (ex as u64) << 52;
-    } else {
-        uxi >>= -ex + 1;
-    }
-    uxi |= (sx as u64) << 63;
-
-    f64::from_bits(uxi)
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmodf128(x: f128, y: f128) -> f128 {
+    super::generic::fmod(x, y)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf.rs
index 1d80013..4e95696e 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf.rs
@@ -1,88 +1,5 @@
-use core::{f32, u32};
-
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn fmodf(x: f32, y: f32) -> f32 {
-    let mut uxi = x.to_bits();
-    let mut uyi = y.to_bits();
-    let mut ex = (uxi >> 23 & 0xff) as i32;
-    let mut ey = (uyi >> 23 & 0xff) as i32;
-    let sx = uxi & 0x80000000;
-    let mut i;
-
-    if uyi << 1 == 0 || y.is_nan() || ex == 0xff {
-        return (x * y) / (x * y);
-    }
-
-    if uxi << 1 <= uyi << 1 {
-        if uxi << 1 == uyi << 1 {
-            return 0.0 * x;
-        }
-
-        return x;
-    }
-
-    /* normalize x and y */
-    if ex == 0 {
-        i = uxi << 9;
-        while i >> 31 == 0 {
-            ex -= 1;
-            i <<= 1;
-        }
-
-        uxi <<= -ex + 1;
-    } else {
-        uxi &= u32::MAX >> 9;
-        uxi |= 1 << 23;
-    }
-
-    if ey == 0 {
-        i = uyi << 9;
-        while i >> 31 == 0 {
-            ey -= 1;
-            i <<= 1;
-        }
-
-        uyi <<= -ey + 1;
-    } else {
-        uyi &= u32::MAX >> 9;
-        uyi |= 1 << 23;
-    }
-
-    /* x mod y */
-    while ex > ey {
-        i = uxi.wrapping_sub(uyi);
-        if i >> 31 == 0 {
-            if i == 0 {
-                return 0.0 * x;
-            }
-            uxi = i;
-        }
-        uxi <<= 1;
-
-        ex -= 1;
-    }
-
-    i = uxi.wrapping_sub(uyi);
-    if i >> 31 == 0 {
-        if i == 0 {
-            return 0.0 * x;
-        }
-        uxi = i;
-    }
-
-    while uxi >> 23 == 0 {
-        uxi <<= 1;
-        ex -= 1;
-    }
-
-    /* scale result up */
-    if ex > 0 {
-        uxi -= 1 << 23;
-        uxi |= (ex as u32) << 23;
-    } else {
-        uxi >>= -ex + 1;
-    }
-    uxi |= sx;
-
-    f32::from_bits(uxi)
+    super::generic::fmod(x, y)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf128.rs
new file mode 100644
index 0000000..ff0e049
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf128.rs
@@ -0,0 +1,5 @@
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmodf128(x: f128, y: f128) -> f128 {
+    super::generic::fmod(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf16.rs
new file mode 100644
index 0000000..11972a7
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf16.rs
@@ -0,0 +1,5 @@
+/// Calculate the remainder of `x / y`, the precise result of `x - trunc(x / y) * y`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn fmodf16(x: f16, y: f16) -> f16 {
+    super::generic::fmod(x, y)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexp.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexp.rs
index badad78..de7a64f 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexp.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexp.rs
@@ -1,3 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn frexp(x: f64) -> (f64, i32) {
     let mut y = x.to_bits();
     let ee = ((y >> 52) & 0x7ff) as i32;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexpf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexpf.rs
index 2919c0a..0ec91c2 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexpf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexpf.rs
@@ -1,3 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn frexpf(x: f32) -> (f32, i32) {
     let mut y = x.to_bits();
     let ee: i32 = ((y >> 23) & 0xff) as i32;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/ceil.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/ceil.rs
new file mode 100644
index 0000000..499770c0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/ceil.rs
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: MIT */
+/* origin: musl src/math/ceilf.c */
+
+//! Generic `ceil` algorithm.
+//!
+//! Note that this uses the algorithm from musl's `ceilf` rather than `ceil` or `ceill` because
+//! performance seems to be better (based on icount) and it does not seem to experience rounding
+//! errors on i386.
+
+use super::super::support::{FpResult, Status};
+use super::super::{Float, Int, IntTy, MinInt};
+
+#[inline]
+pub fn ceil<F: Float>(x: F) -> F {
+    ceil_status(x).val
+}
+
+#[inline]
+pub fn ceil_status<F: Float>(x: F) -> FpResult<F> {
+    let zero = IntTy::<F>::ZERO;
+
+    let mut ix = x.to_bits();
+    let e = x.exp_unbiased();
+
+    // If the represented value has no fractional part, no truncation is needed.
+    if e >= F::SIG_BITS as i32 {
+        return FpResult::ok(x);
+    }
+
+    let status;
+    let res = if e >= 0 {
+        // |x| >= 1.0
+        let m = F::SIG_MASK >> e.unsigned();
+        if (ix & m) == zero {
+            // Portion to be masked is already zero; no adjustment needed.
+            return FpResult::ok(x);
+        }
+
+        // Otherwise, raise an inexact exception.
+        status = Status::INEXACT;
+
+        if x.is_sign_positive() {
+            ix += m;
+        }
+
+        ix &= !m;
+        F::from_bits(ix)
+    } else {
+        // |x| < 1.0, raise an inexact exception since truncation will happen (unless x == 0).
+        if ix & F::SIG_MASK == F::Int::ZERO {
+            status = Status::OK;
+        } else {
+            status = Status::INEXACT;
+        }
+
+        if x.is_sign_negative() {
+            // -1.0 < x <= -0.0; rounding up goes toward -0.0.
+            F::NEG_ZERO
+        } else if ix << 1 != zero {
+            // 0.0 < x < 1.0; rounding up goes toward +1.0.
+            F::ONE
+        } else {
+            // +0.0 remains unchanged
+            x
+        }
+    };
+
+    FpResult::new(res, status)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::Hexf;
+
+    /// Test against https://en.cppreference.com/w/cpp/numeric/math/ceil
+    fn spec_test<F: Float>(cases: &[(F, F, Status)]) {
+        let roundtrip = [
+            F::ZERO,
+            F::ONE,
+            F::NEG_ONE,
+            F::NEG_ZERO,
+            F::INFINITY,
+            F::NEG_INFINITY,
+        ];
+
+        for x in roundtrip {
+            let FpResult { val, status } = ceil_status(x);
+            assert_biteq!(val, x, "{}", Hexf(x));
+            assert_eq!(status, Status::OK, "{}", Hexf(x));
+        }
+
+        for &(x, res, res_stat) in cases {
+            let FpResult { val, status } = ceil_status(x);
+            assert_biteq!(val, res, "{}", Hexf(x));
+            assert_eq!(status, res_stat, "{}", Hexf(x));
+        }
+    }
+
+    /* Skipping f16 / f128 "sanity_check"s due to rejected literal lexing at MSRV */
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        let cases = [
+            (0.1, 1.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 1.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 2.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 2.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f16>(&cases);
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_eq!(ceil(1.1f32), 2.0);
+        assert_eq!(ceil(2.9f32), 3.0);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        let cases = [
+            (0.1, 1.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 1.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 2.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 2.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f32>(&cases);
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_eq!(ceil(1.1f64), 2.0);
+        assert_eq!(ceil(2.9f64), 3.0);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        let cases = [
+            (0.1, 1.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 1.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 2.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 2.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f64>(&cases);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        let cases = [
+            (0.1, 1.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 1.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 2.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 2.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f128>(&cases);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/copysign.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/copysign.rs
new file mode 100644
index 0000000..a61af22f
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/copysign.rs
@@ -0,0 +1,11 @@
+use super::super::Float;
+
+/// Copy the sign of `y` to `x`.
+#[inline]
+pub fn copysign<F: Float>(x: F, y: F) -> F {
+    let mut ux = x.to_bits();
+    let uy = y.to_bits();
+    ux &= !F::SIGN_MASK;
+    ux |= uy & F::SIGN_MASK;
+    F::from_bits(ux)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fabs.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fabs.rs
new file mode 100644
index 0000000..0fa0edf
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fabs.rs
@@ -0,0 +1,8 @@
+use super::super::Float;
+
+/// Absolute value.
+#[inline]
+pub fn fabs<F: Float>(x: F) -> F {
+    let abs_mask = !F::SIGN_MASK;
+    F::from_bits(x.to_bits() & abs_mask)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fdim.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fdim.rs
new file mode 100644
index 0000000..a63007b
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fdim.rs
@@ -0,0 +1,6 @@
+use super::super::Float;
+
+#[inline]
+pub fn fdim<F: Float>(x: F, y: F) -> F {
+    if x <= y { F::ZERO } else { x - y }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/floor.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/floor.rs
new file mode 100644
index 0000000..58d1ee4c
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/floor.rs
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: MIT
+ * origin: musl src/math/floor.c */
+
+//! Generic `floor` algorithm.
+//!
+//! Note that this uses the algorithm from musl's `floorf` rather than `floor` or `floorl` because
+//! performance seems to be better (based on icount) and it does not seem to experience rounding
+//! errors on i386.
+
+use super::super::support::{FpResult, Status};
+use super::super::{Float, Int, IntTy, MinInt};
+
+#[inline]
+pub fn floor<F: Float>(x: F) -> F {
+    floor_status(x).val
+}
+
+#[inline]
+pub fn floor_status<F: Float>(x: F) -> FpResult<F> {
+    let zero = IntTy::<F>::ZERO;
+
+    let mut ix = x.to_bits();
+    let e = x.exp_unbiased();
+
+    // If the represented value has no fractional part, no truncation is needed.
+    if e >= F::SIG_BITS as i32 {
+        return FpResult::ok(x);
+    }
+
+    let status;
+    let res = if e >= 0 {
+        // |x| >= 1.0
+        let m = F::SIG_MASK >> e.unsigned();
+        if ix & m == zero {
+            // Portion to be masked is already zero; no adjustment needed.
+            return FpResult::ok(x);
+        }
+
+        // Otherwise, raise an inexact exception.
+        status = Status::INEXACT;
+
+        if x.is_sign_negative() {
+            ix += m;
+        }
+
+        ix &= !m;
+        F::from_bits(ix)
+    } else {
+        // |x| < 1.0, raise an inexact exception since truncation will happen.
+        if ix & F::SIG_MASK == F::Int::ZERO {
+            status = Status::OK;
+        } else {
+            status = Status::INEXACT;
+        }
+
+        if x.is_sign_positive() {
+            // 0.0 <= x < 1.0; rounding down goes toward +0.0.
+            F::ZERO
+        } else if ix << 1 != zero {
+            // -1.0 < x < 0.0; rounding down goes toward -1.0.
+            F::NEG_ONE
+        } else {
+            // -0.0 remains unchanged
+            x
+        }
+    };
+
+    FpResult::new(res, status)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::Hexf;
+
+    /// Test against https://en.cppreference.com/w/cpp/numeric/math/floor
+    fn spec_test<F: Float>(cases: &[(F, F, Status)]) {
+        let roundtrip = [
+            F::ZERO,
+            F::ONE,
+            F::NEG_ONE,
+            F::NEG_ZERO,
+            F::INFINITY,
+            F::NEG_INFINITY,
+        ];
+
+        for x in roundtrip {
+            let FpResult { val, status } = floor_status(x);
+            assert_biteq!(val, x, "{}", Hexf(x));
+            assert_eq!(status, Status::OK, "{}", Hexf(x));
+        }
+
+        for &(x, res, res_stat) in cases {
+            let FpResult { val, status } = floor_status(x);
+            assert_biteq!(val, res, "{}", Hexf(x));
+            assert_eq!(status, res_stat, "{}", Hexf(x));
+        }
+    }
+
+    /* Skipping f16 / f128 "sanity_check"s and spec cases due to rejected literal lexing at MSRV */
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        let cases = [];
+        spec_test::<f16>(&cases);
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_eq!(floor(0.5f32), 0.0);
+        assert_eq!(floor(1.1f32), 1.0);
+        assert_eq!(floor(2.9f32), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        let cases = [
+            (0.1, 0.0, Status::INEXACT),
+            (-0.1, -1.0, Status::INEXACT),
+            (0.9, 0.0, Status::INEXACT),
+            (-0.9, -1.0, Status::INEXACT),
+            (1.1, 1.0, Status::INEXACT),
+            (-1.1, -2.0, Status::INEXACT),
+            (1.9, 1.0, Status::INEXACT),
+            (-1.9, -2.0, Status::INEXACT),
+        ];
+        spec_test::<f32>(&cases);
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_eq!(floor(1.1f64), 1.0);
+        assert_eq!(floor(2.9f64), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        let cases = [
+            (0.1, 0.0, Status::INEXACT),
+            (-0.1, -1.0, Status::INEXACT),
+            (0.9, 0.0, Status::INEXACT),
+            (-0.9, -1.0, Status::INEXACT),
+            (1.1, 1.0, Status::INEXACT),
+            (-1.1, -2.0, Status::INEXACT),
+            (1.9, 1.0, Status::INEXACT),
+            (-1.9, -2.0, Status::INEXACT),
+        ];
+        spec_test::<f64>(&cases);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        let cases = [];
+        spec_test::<f128>(&cases);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmax.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmax.rs
new file mode 100644
index 0000000..bf3f847e
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmax.rs
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2011 `maxNum`. This has been superseded by IEEE 754-2019 `maximumNumber`.
+//!
+//! Per the spec, returns the canonicalized result of:
+//! - `x` if `x > y`
+//! - `y` if `y > x`
+//! - The other number if one is NaN
+//! - Otherwise, either `x` or `y`, canonicalized
+//! - -0.0 and +0.0 may be disregarded (unlike newer operations)
+//!
+//! Excluded from our implementation is sNaN handling.
+//!
+//! More on the differences: [link].
+//!
+//! [link]: https://grouper.ieee.org/groups/msc/ANSI_IEEE-Std-754-2019/background/minNum_maxNum_Removal_Demotion_v3.pdf
+
+use super::super::Float;
+
+#[inline]
+pub fn fmax<F: Float>(x: F, y: F) -> F {
+    let res = if x.is_nan() || x < y { y } else { x };
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum.rs
new file mode 100644
index 0000000..387055a
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum.rs
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2019 `maximum`.
+//!
+//! Per the spec, returns the canonicalized result of:
+//! - `x` if `x > y`
+//! - `y` if `y > x`
+//! - qNaN if either operation is NaN
+//! - Logic following +0.0 > -0.0
+//!
+//! Excluded from our implementation is sNaN handling.
+
+use super::super::Float;
+
+#[inline]
+pub fn fmaximum<F: Float>(x: F, y: F) -> F {
+    let res = if x.is_nan() {
+        x
+    } else if y.is_nan() {
+        y
+    } else if x > y || (y.to_bits() == F::NEG_ZERO.to_bits() && x.is_sign_positive()) {
+        x
+    } else {
+        y
+    };
+
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum_num.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum_num.rs
new file mode 100644
index 0000000..f7efdde
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum_num.rs
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2019 `maximumNumber`.
+//!
+//! Per the spec, returns:
+//! - `x` if `x > y`
+//! - `y` if `y > x`
+//! - Non-NaN if one operand is NaN
+//! - Logic following +0.0 > -0.0
+//! - Either `x` or `y` if `x == y` and the signs are the same
+//! - qNaN if either operand is a NaN
+//!
+//! Excluded from our implementation is sNaN handling.
+
+use super::super::Float;
+
+#[inline]
+pub fn fmaximum_num<F: Float>(x: F, y: F) -> F {
+    let res =
+        if x.is_nan() || x < y || (x.to_bits() == F::NEG_ZERO.to_bits() && y.is_sign_positive()) {
+            y
+        } else {
+            x
+        };
+
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmin.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmin.rs
new file mode 100644
index 0000000..cd3caee
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmin.rs
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2008 `minNum`. This has been superseded by IEEE 754-2019 `minimumNumber`.
+//!
+//! Per the spec, returns the canonicalized result of:
+//! - `x` if `x < y`
+//! - `y` if `y < x`
+//! - The other number if one is NaN
+//! - Otherwise, either `x` or `y`, canonicalized
+//! - -0.0 and +0.0 may be disregarded (unlike newer operations)
+//!
+//! Excluded from our implementation is sNaN handling.
+//!
+//! More on the differences: [link].
+//!
+//! [link]: https://grouper.ieee.org/groups/msc/ANSI_IEEE-Std-754-2019/background/minNum_maxNum_Removal_Demotion_v3.pdf
+
+use super::super::Float;
+
+#[inline]
+pub fn fmin<F: Float>(x: F, y: F) -> F {
+    let res = if y.is_nan() || x < y { x } else { y };
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum.rs
new file mode 100644
index 0000000..4ddb364
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum.rs
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2019 `minimum`.
+//!
+//! Per the spec, returns the canonicalized result of:
+//! - `x` if `x < y`
+//! - `y` if `y < x`
+//! - qNaN if either operation is NaN
+//! - Logic following +0.0 > -0.0
+//!
+//! Excluded from our implementation is sNaN handling.
+
+use super::super::Float;
+
+#[inline]
+pub fn fminimum<F: Float>(x: F, y: F) -> F {
+    let res = if x.is_nan() {
+        x
+    } else if y.is_nan() {
+        y
+    } else if x < y || (x.to_bits() == F::NEG_ZERO.to_bits() && y.is_sign_positive()) {
+        x
+    } else {
+        y
+    };
+
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum_num.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum_num.rs
new file mode 100644
index 0000000..441c204
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum_num.rs
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+//! IEEE 754-2019 `minimum`.
+//!
+//! Per the spec, returns:
+//! - `x` if `x < y`
+//! - `y` if `y < x`
+//! - Non-NaN if one operand is NaN
+//! - Logic following +0.0 > -0.0
+//! - Either `x` or `y` if `x == y` and the signs are the same
+//! - qNaN if either operand is a NaN
+//!
+//! Excluded from our implementation is sNaN handling.
+
+use super::super::Float;
+
+#[inline]
+pub fn fminimum_num<F: Float>(x: F, y: F) -> F {
+    let res =
+        if y.is_nan() || x < y || (x.to_bits() == F::NEG_ZERO.to_bits() && y.is_sign_positive()) {
+            x
+        } else {
+            y
+        };
+
+    // Canonicalize
+    res * F::ONE
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmod.rs
new file mode 100644
index 0000000..e9898012
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmod.rs
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: MIT OR Apache-2.0 */
+use super::super::{CastFrom, Float, Int, MinInt};
+
+#[inline]
+pub fn fmod<F: Float>(x: F, y: F) -> F {
+    let _1 = F::Int::ONE;
+    let sx = x.to_bits() & F::SIGN_MASK;
+    let ux = x.to_bits() & !F::SIGN_MASK;
+    let uy = y.to_bits() & !F::SIGN_MASK;
+
+    // Cases that return NaN:
+    //   NaN % _
+    //   Inf % _
+    //     _ % NaN
+    //     _ % 0
+    let x_nan_or_inf = ux & F::EXP_MASK == F::EXP_MASK;
+    let y_nan_or_zero = uy.wrapping_sub(_1) & F::EXP_MASK == F::EXP_MASK;
+    if x_nan_or_inf | y_nan_or_zero {
+        return (x * y) / (x * y);
+    }
+
+    if ux < uy {
+        // |x| < |y|
+        return x;
+    }
+
+    let (num, ex) = into_sig_exp::<F>(ux);
+    let (div, ey) = into_sig_exp::<F>(uy);
+
+    // To compute `(num << ex) % (div << ey)`, first
+    // evaluate `rem = (num << (ex - ey)) % div` ...
+    let rem = reduction(num, ex - ey, div);
+    // ... so the result will be `rem << ey`
+
+    if rem.is_zero() {
+        // Return zero with the sign of `x`
+        return F::from_bits(sx);
+    };
+
+    // We would shift `rem` up by `ey`, but have to stop at `F::SIG_BITS`
+    let shift = ey.min(F::SIG_BITS - rem.ilog2());
+    // Anything past that is added to the exponent field
+    let bits = (rem << shift) + (F::Int::cast_from(ey - shift) << F::SIG_BITS);
+    F::from_bits(sx + bits)
+}
+
+/// Given the bits of a finite float, return a tuple of
+///  - the mantissa with the implicit bit (0 if subnormal, 1 otherwise)
+///  - the additional exponent past 1, (0 for subnormal, 0 or more otherwise)
+fn into_sig_exp<F: Float>(mut bits: F::Int) -> (F::Int, u32) {
+    bits &= !F::SIGN_MASK;
+    // Subtract 1 from the exponent, clamping at 0
+    let sat = bits.checked_sub(F::IMPLICIT_BIT).unwrap_or(F::Int::ZERO);
+    (
+        bits - (sat & F::EXP_MASK),
+        u32::cast_from(sat >> F::SIG_BITS),
+    )
+}
+
+/// Compute the remainder `(x * 2.pow(e)) % y` without overflow.
+fn reduction<I: Int>(mut x: I, e: u32, y: I) -> I {
+    x %= y;
+    for _ in 0..e {
+        x <<= 1;
+        x = x.checked_sub(y).unwrap_or(x);
+    }
+    x
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/mod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/mod.rs
new file mode 100644
index 0000000..3584635
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/mod.rs
@@ -0,0 +1,38 @@
+// Note: generic functions are marked `#[inline]` because, even though generic functions are
+// typically inlined, this does not seem to always be the case.
+
+mod ceil;
+mod copysign;
+mod fabs;
+mod fdim;
+mod floor;
+mod fmax;
+mod fmaximum;
+mod fmaximum_num;
+mod fmin;
+mod fminimum;
+mod fminimum_num;
+mod fmod;
+mod rint;
+mod round;
+mod scalbn;
+mod sqrt;
+mod trunc;
+
+pub use ceil::ceil;
+pub use copysign::copysign;
+pub use fabs::fabs;
+pub use fdim::fdim;
+pub use floor::floor;
+pub use fmax::fmax;
+pub use fmaximum::fmaximum;
+pub use fmaximum_num::fmaximum_num;
+pub use fmin::fmin;
+pub use fminimum::fminimum;
+pub use fminimum_num::fminimum_num;
+pub use fmod::fmod;
+pub use rint::rint_round;
+pub use round::round;
+pub use scalbn::scalbn;
+pub use sqrt::sqrt;
+pub use trunc::trunc;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/rint.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/rint.rs
new file mode 100644
index 0000000..7bf38e3
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/rint.rs
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: MIT */
+/* origin: musl src/math/rint.c */
+
+use super::super::Float;
+use super::super::support::{FpResult, Round};
+
+/// IEEE 754-2019 `roundToIntegralExact`, which respects rounding mode and raises inexact if
+/// applicable.
+#[inline]
+pub fn rint_round<F: Float>(x: F, _round: Round) -> FpResult<F> {
+    let toint = F::ONE / F::EPSILON;
+    let e = x.ex();
+    let positive = x.is_sign_positive();
+
+    // On i386 `force_eval!` must be used to force rounding via storage to memory. Otherwise,
+    // the excess precission from x87 would cause an incorrect final result.
+    let force = |x| {
+        if cfg!(x86_no_sse) && (F::BITS == 32 || F::BITS == 64) {
+            force_eval!(x)
+        } else {
+            x
+        }
+    };
+
+    let res = if e >= F::EXP_BIAS + F::SIG_BITS {
+        // No fractional part; exact result can be returned.
+        x
+    } else {
+        // Apply a net-zero adjustment that nudges `y` in the direction of the rounding mode. For
+        // Rust this is always nearest, but ideally it would take `round` into account.
+        let y = if positive {
+            force(force(x) + toint) - toint
+        } else {
+            force(force(x) - toint) + toint
+        };
+
+        if y == F::ZERO {
+            // A zero result takes the sign of the input.
+            if positive { F::ZERO } else { F::NEG_ZERO }
+        } else {
+            y
+        }
+    };
+
+    FpResult::ok(res)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::{Hexf, Status};
+
+    fn spec_test<F: Float>(cases: &[(F, F, Status)]) {
+        let roundtrip = [
+            F::ZERO,
+            F::ONE,
+            F::NEG_ONE,
+            F::NEG_ZERO,
+            F::INFINITY,
+            F::NEG_INFINITY,
+        ];
+
+        for x in roundtrip {
+            let FpResult { val, status } = rint_round(x, Round::Nearest);
+            assert_biteq!(val, x, "rint_round({})", Hexf(x));
+            assert_eq!(status, Status::OK, "{}", Hexf(x));
+        }
+
+        for &(x, res, res_stat) in cases {
+            let FpResult { val, status } = rint_round(x, Round::Nearest);
+            assert_biteq!(val, res, "rint_round({})", Hexf(x));
+            assert_eq!(status, res_stat, "{}", Hexf(x));
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        let cases = [];
+        spec_test::<f16>(&cases);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        let cases = [
+            (0.1, 0.0, Status::OK),
+            (-0.1, -0.0, Status::OK),
+            (0.5, 0.0, Status::OK),
+            (-0.5, -0.0, Status::OK),
+            (0.9, 1.0, Status::OK),
+            (-0.9, -1.0, Status::OK),
+            (1.1, 1.0, Status::OK),
+            (-1.1, -1.0, Status::OK),
+            (1.5, 2.0, Status::OK),
+            (-1.5, -2.0, Status::OK),
+            (1.9, 2.0, Status::OK),
+            (-1.9, -2.0, Status::OK),
+            (2.8, 3.0, Status::OK),
+            (-2.8, -3.0, Status::OK),
+        ];
+        spec_test::<f32>(&cases);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        let cases = [
+            (0.1, 0.0, Status::OK),
+            (-0.1, -0.0, Status::OK),
+            (0.5, 0.0, Status::OK),
+            (-0.5, -0.0, Status::OK),
+            (0.9, 1.0, Status::OK),
+            (-0.9, -1.0, Status::OK),
+            (1.1, 1.0, Status::OK),
+            (-1.1, -1.0, Status::OK),
+            (1.5, 2.0, Status::OK),
+            (-1.5, -2.0, Status::OK),
+            (1.9, 2.0, Status::OK),
+            (-1.9, -2.0, Status::OK),
+            (2.8, 3.0, Status::OK),
+            (-2.8, -3.0, Status::OK),
+        ];
+        spec_test::<f64>(&cases);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        let cases = [];
+        spec_test::<f128>(&cases);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/round.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/round.rs
new file mode 100644
index 0000000..01314ac
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/round.rs
@@ -0,0 +1,83 @@
+use super::super::{Float, MinInt};
+use super::{copysign, trunc};
+
+#[inline]
+pub fn round<F: Float>(x: F) -> F {
+    let f0p5 = F::from_parts(false, F::EXP_BIAS - 1, F::Int::ZERO); // 0.5
+    let f0p25 = F::from_parts(false, F::EXP_BIAS - 2, F::Int::ZERO); // 0.25
+
+    trunc(x + copysign(f0p5 - f0p25 * F::EPSILON, x))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn zeroes_f16() {
+        assert_biteq!(round(0.0_f16), 0.0_f16);
+        assert_biteq!(round(-0.0_f16), -0.0_f16);
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn sanity_check_f16() {
+        assert_eq!(round(-1.0_f16), -1.0);
+        assert_eq!(round(2.8_f16), 3.0);
+        assert_eq!(round(-0.5_f16), -1.0);
+        assert_eq!(round(0.5_f16), 1.0);
+        assert_eq!(round(-1.5_f16), -2.0);
+        assert_eq!(round(1.5_f16), 2.0);
+    }
+
+    #[test]
+    fn zeroes_f32() {
+        assert_biteq!(round(0.0_f32), 0.0_f32);
+        assert_biteq!(round(-0.0_f32), -0.0_f32);
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_eq!(round(-1.0_f32), -1.0);
+        assert_eq!(round(2.8_f32), 3.0);
+        assert_eq!(round(-0.5_f32), -1.0);
+        assert_eq!(round(0.5_f32), 1.0);
+        assert_eq!(round(-1.5_f32), -2.0);
+        assert_eq!(round(1.5_f32), 2.0);
+    }
+
+    #[test]
+    fn zeroes_f64() {
+        assert_biteq!(round(0.0_f64), 0.0_f64);
+        assert_biteq!(round(-0.0_f64), -0.0_f64);
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_eq!(round(-1.0_f64), -1.0);
+        assert_eq!(round(2.8_f64), 3.0);
+        assert_eq!(round(-0.5_f64), -1.0);
+        assert_eq!(round(0.5_f64), 1.0);
+        assert_eq!(round(-1.5_f64), -2.0);
+        assert_eq!(round(1.5_f64), 2.0);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn zeroes_f128() {
+        assert_biteq!(round(0.0_f128), 0.0_f128);
+        assert_biteq!(round(-0.0_f128), -0.0_f128);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn sanity_check_f128() {
+        assert_eq!(round(-1.0_f128), -1.0);
+        assert_eq!(round(2.8_f128), 3.0);
+        assert_eq!(round(-0.5_f128), -1.0);
+        assert_eq!(round(0.5_f128), 1.0);
+        assert_eq!(round(-1.5_f128), -2.0);
+        assert_eq!(round(1.5_f128), 2.0);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/scalbn.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/scalbn.rs
new file mode 100644
index 0000000..a45db1b
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/scalbn.rs
@@ -0,0 +1,121 @@
+use super::super::{CastFrom, CastInto, Float, IntTy, MinInt};
+
+/// Scale the exponent.
+///
+/// From N3220:
+///
+/// > The scalbn and scalbln functions compute `x * b^n`, where `b = FLT_RADIX` if the return type
+/// > of the function is a standard floating type, or `b = 10` if the return type of the function
+/// > is a decimal floating type. A range error occurs for some finite x, depending on n.
+/// >
+/// > [...]
+/// >
+/// > * `scalbn(±0, n)` returns `±0`.
+/// > * `scalbn(x, 0)` returns `x`.
+/// > * `scalbn(±∞, n)` returns `±∞`.
+/// >
+/// > If the calculation does not overflow or underflow, the returned value is exact and
+/// > independent of the current rounding direction mode.
+#[inline]
+pub fn scalbn<F: Float>(mut x: F, mut n: i32) -> F
+where
+    u32: CastInto<F::Int>,
+    F::Int: CastFrom<i32>,
+    F::Int: CastFrom<u32>,
+{
+    let zero = IntTy::<F>::ZERO;
+
+    // Bits including the implicit bit
+    let sig_total_bits = F::SIG_BITS + 1;
+
+    // Maximum and minimum values when biased
+    let exp_max = F::EXP_MAX;
+    let exp_min = F::EXP_MIN;
+
+    // 2 ^ Emax, maximum positive with null significand (0x1p1023 for f64)
+    let f_exp_max = F::from_parts(false, F::EXP_BIAS << 1, zero);
+
+    // 2 ^ Emin, minimum positive normal with null significand (0x1p-1022 for f64)
+    let f_exp_min = F::from_parts(false, 1, zero);
+
+    // 2 ^ sig_total_bits, moltiplier to normalize subnormals (0x1p53 for f64)
+    let f_pow_subnorm = F::from_parts(false, sig_total_bits + F::EXP_BIAS, zero);
+
+    /*
+     * The goal is to multiply `x` by a scale factor that applies `n`. However, there are cases
+     * where `2^n` is not representable by `F` but the result should be, e.g. `x = 2^Emin` with
+     * `n = -EMin + 2` (one out of range of 2^Emax). To get around this, reduce the magnitude of
+     * the final scale operation by prescaling by the max/min power representable by `F`.
+     */
+
+    if n > exp_max {
+        // Worse case positive `n`: `x`  is the minimum subnormal value, the result is `F::MAX`.
+        // This can be reached by three scaling multiplications (two here and one final).
+        debug_assert!(-exp_min + F::SIG_BITS as i32 + exp_max <= exp_max * 3);
+
+        x *= f_exp_max;
+        n -= exp_max;
+        if n > exp_max {
+            x *= f_exp_max;
+            n -= exp_max;
+            if n > exp_max {
+                n = exp_max;
+            }
+        }
+    } else if n < exp_min {
+        // When scaling toward 0, the prescaling is limited to a value that does not allow `x` to
+        // go subnormal. This avoids double rounding.
+        if F::BITS > 16 {
+            // `mul` s.t. `!(x * mul).is_subnormal() ∀ x`
+            let mul = f_exp_min * f_pow_subnorm;
+            let add = -exp_min - sig_total_bits as i32;
+
+            // Worse case negative `n`: `x`  is the maximum positive value, the result is `F::MIN`.
+            // This must be reachable by three scaling multiplications (two here and one final).
+            debug_assert!(-exp_min + F::SIG_BITS as i32 + exp_max <= add * 2 + -exp_min);
+
+            x *= mul;
+            n += add;
+
+            if n < exp_min {
+                x *= mul;
+                n += add;
+
+                if n < exp_min {
+                    n = exp_min;
+                }
+            }
+        } else {
+            // `f16` is unique compared to other float types in that the difference between the
+            // minimum exponent and the significand bits (`add = -exp_min - sig_total_bits`) is
+            // small, only three. The above method depend on decrementing `n` by `add` two times;
+            // for other float types this works out because `add` is a substantial fraction of
+            // the exponent range. For `f16`, however, 3 is relatively small compared to the
+            // exponent range (which is 39), so that requires ~10 prescale rounds rather than two.
+            //
+            // Work aroudn this by using a different algorithm that calculates the prescale
+            // dynamically based on the maximum possible value. This adds more operations per round
+            // since it needs to construct the scale, but works better in the general case.
+            let add = -(n + sig_total_bits as i32).clamp(exp_min, sig_total_bits as i32);
+            let mul = F::from_parts(false, (F::EXP_BIAS as i32 - add) as u32, zero);
+
+            x *= mul;
+            n += add;
+
+            if n < exp_min {
+                let add = -(n + sig_total_bits as i32).clamp(exp_min, sig_total_bits as i32);
+                let mul = F::from_parts(false, (F::EXP_BIAS as i32 - add) as u32, zero);
+
+                x *= mul;
+                n += add;
+
+                if n < exp_min {
+                    n = exp_min;
+                }
+            }
+        }
+    }
+
+    let scale = F::from_parts(false, (F::EXP_BIAS as i32 + n) as u32, zero);
+    x * scale
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/sqrt.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/sqrt.rs
new file mode 100644
index 0000000..c52560bd
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/sqrt.rs
@@ -0,0 +1,540 @@
+/* SPDX-License-Identifier: MIT */
+/* origin: musl src/math/sqrt.c. Ported to generic Rust algorithm in 2025, TG. */
+
+//! Generic square root algorithm.
+//!
+//! This routine operates around `m_u2`, a U.2 (fixed point with two integral bits) mantissa
+//! within the range [1, 4). A table lookup provides an initial estimate, then goldschmidt
+//! iterations at various widths are used to approach the real values.
+//!
+//! For the iterations, `r` is a U0 number that approaches `1/sqrt(m_u2)`, and `s` is a U2 number
+//! that approaches `sqrt(m_u2)`. Recall that m_u2 ∈ [1, 4).
+//!
+//! With Newton-Raphson iterations, this would be:
+//!
+//! - `w = r * r           w ~ 1 / m`
+//! - `u = 3 - m * w       u ~ 3 - m * w = 3 - m / m = 2`
+//! - `r = r * u / 2       r ~ r`
+//!
+//! (Note that the righthand column does not show anything analytically meaningful (i.e. r ~ r),
+//! since the value of performing one iteration is in reducing the error representable by `~`).
+//!
+//! Instead of Newton-Raphson iterations, Goldschmidt iterations are used to calculate
+//! `s = m * r`:
+//!
+//! - `s = m * r           s ~ m / sqrt(m)`
+//! - `u = 3 - s * r       u ~ 3 - (m / sqrt(m)) * (1 / sqrt(m)) = 3 - m / m = 2`
+//! - `r = r * u / 2       r ~ r`
+//! - `s = s * u / 2       s ~ s`
+//!
+//! The above is precise because it uses the original value `m`. There is also a faster version
+//! that performs fewer steps but does not use `m`:
+//!
+//! - `u = 3 - s * r       u ~ 3 - 1`
+//! - `r = r * u / 2       r ~ r`
+//! - `s = s * u / 2       s ~ s`
+//!
+//! Rounding errors accumulate faster with the second version, so it is only used for subsequent
+//! iterations within the same width integer. The first version is always used for the first
+//! iteration at a new width in order to avoid this accumulation.
+//!
+//! Goldschmidt has the advantage over Newton-Raphson that `sqrt(x)` and `1/sqrt(x)` are
+//! computed at the same time, i.e. there is no need to calculate `1/sqrt(x)` and invert it.
+
+use super::super::support::{FpResult, IntTy, Round, Status, cold_path};
+use super::super::{CastFrom, CastInto, DInt, Float, HInt, Int, MinInt};
+
+#[inline]
+pub fn sqrt<F>(x: F) -> F
+where
+    F: Float + SqrtHelper,
+    F::Int: HInt,
+    F::Int: From<u8>,
+    F::Int: From<F::ISet2>,
+    F::Int: CastInto<F::ISet1>,
+    F::Int: CastInto<F::ISet2>,
+    u32: CastInto<F::Int>,
+{
+    sqrt_round(x, Round::Nearest).val
+}
+
+#[inline]
+pub fn sqrt_round<F>(x: F, _round: Round) -> FpResult<F>
+where
+    F: Float + SqrtHelper,
+    F::Int: HInt,
+    F::Int: From<u8>,
+    F::Int: From<F::ISet2>,
+    F::Int: CastInto<F::ISet1>,
+    F::Int: CastInto<F::ISet2>,
+    u32: CastInto<F::Int>,
+{
+    let zero = IntTy::<F>::ZERO;
+    let one = IntTy::<F>::ONE;
+
+    let mut ix = x.to_bits();
+
+    // Top is the exponent and sign, which may or may not be shifted. If the float fits into a
+    // `u32`, we can get by without paying shifting costs.
+    let noshift = F::BITS <= u32::BITS;
+    let (mut top, special_case) = if noshift {
+        let exp_lsb = one << F::SIG_BITS;
+        let special_case = ix.wrapping_sub(exp_lsb) >= F::EXP_MASK - exp_lsb;
+        (Exp::NoShift(()), special_case)
+    } else {
+        let top = u32::cast_from(ix >> F::SIG_BITS);
+        let special_case = top.wrapping_sub(1) >= F::EXP_SAT - 1;
+        (Exp::Shifted(top), special_case)
+    };
+
+    // Handle NaN, zero, and out of domain (<= 0)
+    if special_case {
+        cold_path();
+
+        // +/-0
+        if ix << 1 == zero {
+            return FpResult::ok(x);
+        }
+
+        // Positive infinity
+        if ix == F::EXP_MASK {
+            return FpResult::ok(x);
+        }
+
+        // NaN or negative
+        if ix > F::EXP_MASK {
+            return FpResult::new(F::NAN, Status::INVALID);
+        }
+
+        // Normalize subnormals by multiplying by 1.0 << SIG_BITS (e.g. 0x1p52 for doubles).
+        let scaled = x * F::from_parts(false, F::SIG_BITS + F::EXP_BIAS, zero);
+        ix = scaled.to_bits();
+        match top {
+            Exp::Shifted(ref mut v) => {
+                *v = scaled.ex();
+                *v = (*v).wrapping_sub(F::SIG_BITS);
+            }
+            Exp::NoShift(()) => {
+                ix = ix.wrapping_sub((F::SIG_BITS << F::SIG_BITS).cast());
+            }
+        }
+    }
+
+    // Reduce arguments such that `x = 4^e * m`:
+    //
+    // - m_u2 ∈ [1, 4), a fixed point U2.BITS number
+    // - 2^e is the exponent part of the result
+    let (m_u2, exp) = match top {
+        Exp::Shifted(top) => {
+            // We now know `x` is positive, so `top` is just its (biased) exponent
+            let mut e = top;
+            // Construct a fixed point representation of the mantissa.
+            let mut m_u2 = (ix | F::IMPLICIT_BIT) << F::EXP_BITS;
+            let even = (e & 1) != 0;
+            if even {
+                m_u2 >>= 1;
+            }
+            e = (e.wrapping_add(F::EXP_SAT >> 1)) >> 1;
+            (m_u2, Exp::Shifted(e))
+        }
+        Exp::NoShift(()) => {
+            let even = ix & (one << F::SIG_BITS) != zero;
+
+            // Exponent part of the return value
+            let mut e_noshift = ix >> 1;
+            // ey &= (F::EXP_MASK << 2) >> 2; // clear the top exponent bit (result = 1.0)
+            e_noshift += (F::EXP_MASK ^ (F::SIGN_MASK >> 1)) >> 1;
+            e_noshift &= F::EXP_MASK;
+
+            let m1 = (ix << F::EXP_BITS) | F::SIGN_MASK;
+            let m0 = (ix << (F::EXP_BITS - 1)) & !F::SIGN_MASK;
+            let m_u2 = if even { m0 } else { m1 };
+
+            (m_u2, Exp::NoShift(e_noshift))
+        }
+    };
+
+    // Extract the top 6 bits of the significand with the lowest bit of the exponent.
+    let i = usize::cast_from(ix >> (F::SIG_BITS - 6)) & 0b1111111;
+
+    // Start with an initial guess for `r = 1 / sqrt(m)` from the table, and shift `m` as an
+    // initial value for `s = sqrt(m)`. See the module documentation for details.
+    let r1_u0: F::ISet1 = F::ISet1::cast_from(RSQRT_TAB[i]) << (F::ISet1::BITS - 16);
+    let s1_u2: F::ISet1 = ((m_u2) >> (F::BITS - F::ISet1::BITS)).cast();
+
+    // Perform iterations, if any, at quarter width (used for `f128`).
+    let (r1_u0, _s1_u2) = goldschmidt::<F, F::ISet1>(r1_u0, s1_u2, F::SET1_ROUNDS, false);
+
+    // Widen values and perform iterations at half width (used for `f64` and `f128`).
+    let r2_u0: F::ISet2 = F::ISet2::from(r1_u0) << (F::ISet2::BITS - F::ISet1::BITS);
+    let s2_u2: F::ISet2 = ((m_u2) >> (F::BITS - F::ISet2::BITS)).cast();
+    let (r2_u0, _s2_u2) = goldschmidt::<F, F::ISet2>(r2_u0, s2_u2, F::SET2_ROUNDS, false);
+
+    // Perform final iterations at full width (used for all float types).
+    let r_u0: F::Int = F::Int::from(r2_u0) << (F::BITS - F::ISet2::BITS);
+    let s_u2: F::Int = m_u2;
+    let (_r_u0, s_u2) = goldschmidt::<F, F::Int>(r_u0, s_u2, F::FINAL_ROUNDS, true);
+
+    // Shift back to mantissa position.
+    let mut m = s_u2 >> (F::EXP_BITS - 2);
+
+    // The musl source includes the following comment (with literals replaced):
+    //
+    // > s < sqrt(m) < s + 0x1.09p-SIG_BITS
+    // > compute nearest rounded result: the nearest result to SIG_BITS bits is either s or
+    // > s+0x1p-SIG_BITS, we can decide by comparing (2^SIG_BITS s + 0.5)^2 to 2^(2*SIG_BITS) m.
+    //
+    // Expanding this with , with `SIG_BITS = p` and adjusting based on the operations done to
+    // `d0` and `d1`:
+    //
+    // - `2^(2p)m ≟ ((2^p)m + 0.5)^2`
+    // - `2^(2p)m ≟ 2^(2p)m^2 + (2^p)m + 0.25`
+    // - `2^(2p)m - m^2 ≟ (2^(2p) - 1)m^2 + (2^p)m + 0.25`
+    // - `(1 - 2^(2p))m + m^2 ≟ (1 - 2^(2p))m^2 + (1 - 2^p)m + 0.25` (?)
+    //
+    // I do not follow how the rounding bit is extracted from this comparison with the below
+    // operations. In any case, the algorithm is well tested.
+
+    // The value needed to shift `m_u2` by to create `m*2^(2p)`. `2p = 2 * F::SIG_BITS`,
+    // `F::BITS - 2` accounts for the offset that `m_u2` already has.
+    let shift = 2 * F::SIG_BITS - (F::BITS - 2);
+
+    // `2^(2p)m - m^2`
+    let d0 = (m_u2 << shift).wrapping_sub(m.wrapping_mul(m));
+    // `m - 2^(2p)m + m^2`
+    let d1 = m.wrapping_sub(d0);
+    m += d1 >> (F::BITS - 1);
+    m &= F::SIG_MASK;
+
+    match exp {
+        Exp::Shifted(e) => m |= IntTy::<F>::cast_from(e) << F::SIG_BITS,
+        Exp::NoShift(e) => m |= e,
+    };
+
+    let mut y = F::from_bits(m);
+
+    // FIXME(f16): the fenv math does not work for `f16`
+    if F::BITS > 16 {
+        // Handle rounding and inexact. `(m + 1)^2 == 2^shift m` is exact; for all other cases, add
+        // a tiny value to cause fenv effects.
+        let d2 = d1.wrapping_add(m).wrapping_add(one);
+        let mut tiny = if d2 == zero {
+            cold_path();
+            zero
+        } else {
+            F::IMPLICIT_BIT
+        };
+
+        tiny |= (d1 ^ d2) & F::SIGN_MASK;
+        let t = F::from_bits(tiny);
+        y = y + t;
+    }
+
+    FpResult::ok(y)
+}
+
+/// Multiply at the wider integer size, returning the high half.
+fn wmulh<I: HInt>(a: I, b: I) -> I {
+    a.widen_mul(b).hi()
+}
+
+/// Perform `count` goldschmidt iterations, returning `(r_u0, s_u?)`.
+///
+/// - `r_u0` is the reciprocal `r ~ 1 / sqrt(m)`, as U0.
+/// - `s_u2` is the square root, `s ~ sqrt(m)`, as U2.
+/// - `count` is the number of iterations to perform.
+/// - `final_set` should be true if this is the last round (same-sized integer). If so, the
+///   returned `s` will be U3, for later shifting. Otherwise, the returned `s` is U2.
+///
+/// Note that performance relies on the optimizer being able to unroll these loops (reasonably
+/// trivial, `count` is a constant when called).
+#[inline]
+fn goldschmidt<F, I>(mut r_u0: I, mut s_u2: I, count: u32, final_set: bool) -> (I, I)
+where
+    F: SqrtHelper,
+    I: HInt + From<u8>,
+{
+    let three_u2 = I::from(0b11u8) << (I::BITS - 2);
+    let mut u_u0 = r_u0;
+
+    for i in 0..count {
+        // First iteration: `s = m*r` (`u_u0 = r_u0` set above)
+        // Subsequent iterations: `s=s*u/2`
+        s_u2 = wmulh(s_u2, u_u0);
+
+        // Perform `s /= 2` if:
+        //
+        // 1. This is not the first iteration (the first iteration is `s = m*r`)...
+        // 2. ... and this is not the last set of iterations
+        // 3. ... or, if this is the last set, it is not the last iteration
+        //
+        // This step is not performed for the final iteration because the shift is combined with
+        // a later shift (moving `s` into the mantissa).
+        if i > 0 && (!final_set || i + 1 < count) {
+            s_u2 <<= 1;
+        }
+
+        // u = 3 - s*r
+        let d_u2 = wmulh(s_u2, r_u0);
+        u_u0 = three_u2.wrapping_sub(d_u2);
+
+        // r = r*u/2
+        r_u0 = wmulh(r_u0, u_u0) << 1;
+    }
+
+    (r_u0, s_u2)
+}
+
+/// Representation of whether we shift the exponent into a `u32`, or modify it in place to save
+/// the shift operations.
+enum Exp<T> {
+    /// The exponent has been shifted to a `u32` and is LSB-aligned.
+    Shifted(u32),
+    /// The exponent is in its natural position in integer repr.
+    NoShift(T),
+}
+
+/// Size-specific constants related to the square root routine.
+pub trait SqrtHelper: Float {
+    /// Integer for the first set of rounds. If unused, set to the same type as the next set.
+    type ISet1: HInt + Into<Self::ISet2> + CastFrom<Self::Int> + From<u8>;
+    /// Integer for the second set of rounds. If unused, set to the same type as the next set.
+    type ISet2: HInt + From<Self::ISet1> + From<u8>;
+
+    /// Number of rounds at `ISet1`.
+    const SET1_ROUNDS: u32 = 0;
+    /// Number of rounds at `ISet2`.
+    const SET2_ROUNDS: u32 = 0;
+    /// Number of rounds at `Self::Int`.
+    const FINAL_ROUNDS: u32;
+}
+
+#[cfg(f16_enabled)]
+impl SqrtHelper for f16 {
+    type ISet1 = u16; // unused
+    type ISet2 = u16; // unused
+
+    const FINAL_ROUNDS: u32 = 2;
+}
+
+impl SqrtHelper for f32 {
+    type ISet1 = u32; // unused
+    type ISet2 = u32; // unused
+
+    const FINAL_ROUNDS: u32 = 3;
+}
+
+impl SqrtHelper for f64 {
+    type ISet1 = u32; // unused
+    type ISet2 = u32;
+
+    const SET2_ROUNDS: u32 = 2;
+    const FINAL_ROUNDS: u32 = 2;
+}
+
+#[cfg(f128_enabled)]
+impl SqrtHelper for f128 {
+    type ISet1 = u32;
+    type ISet2 = u64;
+
+    const SET1_ROUNDS: u32 = 1;
+    const SET2_ROUNDS: u32 = 2;
+    const FINAL_ROUNDS: u32 = 2;
+}
+
+/// A U0.16 representation of `1/sqrt(x)`.
+///
+/// The index is a 7-bit number consisting of a single exponent bit and 6 bits of significand.
+#[rustfmt::skip]
+static RSQRT_TAB: [u16; 128] = [
+    0xb451, 0xb2f0, 0xb196, 0xb044, 0xaef9, 0xadb6, 0xac79, 0xab43,
+    0xaa14, 0xa8eb, 0xa7c8, 0xa6aa, 0xa592, 0xa480, 0xa373, 0xa26b,
+    0xa168, 0xa06a, 0x9f70, 0x9e7b, 0x9d8a, 0x9c9d, 0x9bb5, 0x9ad1,
+    0x99f0, 0x9913, 0x983a, 0x9765, 0x9693, 0x95c4, 0x94f8, 0x9430,
+    0x936b, 0x92a9, 0x91ea, 0x912e, 0x9075, 0x8fbe, 0x8f0a, 0x8e59,
+    0x8daa, 0x8cfe, 0x8c54, 0x8bac, 0x8b07, 0x8a64, 0x89c4, 0x8925,
+    0x8889, 0x87ee, 0x8756, 0x86c0, 0x862b, 0x8599, 0x8508, 0x8479,
+    0x83ec, 0x8361, 0x82d8, 0x8250, 0x81c9, 0x8145, 0x80c2, 0x8040,
+    0xff02, 0xfd0e, 0xfb25, 0xf947, 0xf773, 0xf5aa, 0xf3ea, 0xf234,
+    0xf087, 0xeee3, 0xed47, 0xebb3, 0xea27, 0xe8a3, 0xe727, 0xe5b2,
+    0xe443, 0xe2dc, 0xe17a, 0xe020, 0xdecb, 0xdd7d, 0xdc34, 0xdaf1,
+    0xd9b3, 0xd87b, 0xd748, 0xd61a, 0xd4f1, 0xd3cd, 0xd2ad, 0xd192,
+    0xd07b, 0xcf69, 0xce5b, 0xcd51, 0xcc4a, 0xcb48, 0xca4a, 0xc94f,
+    0xc858, 0xc764, 0xc674, 0xc587, 0xc49d, 0xc3b7, 0xc2d4, 0xc1f4,
+    0xc116, 0xc03c, 0xbf65, 0xbe90, 0xbdbe, 0xbcef, 0xbc23, 0xbb59,
+    0xba91, 0xb9cc, 0xb90a, 0xb84a, 0xb78c, 0xb6d0, 0xb617, 0xb560,
+];
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    /// Test behavior specified in IEEE 754 `squareRoot`.
+    fn spec_test<F>()
+    where
+        F: Float + SqrtHelper,
+        F::Int: HInt,
+        F::Int: From<u8>,
+        F::Int: From<F::ISet2>,
+        F::Int: CastInto<F::ISet1>,
+        F::Int: CastInto<F::ISet2>,
+        u32: CastInto<F::Int>,
+    {
+        // Values that should return a NaN and raise invalid
+        let nan = [F::NEG_INFINITY, F::NEG_ONE, F::NAN, F::MIN];
+
+        // Values that return unaltered
+        let roundtrip = [F::ZERO, F::NEG_ZERO, F::INFINITY];
+
+        for x in nan {
+            let FpResult { val, status } = sqrt_round(x, Round::Nearest);
+            assert!(val.is_nan());
+            assert!(status == Status::INVALID);
+        }
+
+        for x in roundtrip {
+            let FpResult { val, status } = sqrt_round(x, Round::Nearest);
+            assert_biteq!(val, x);
+            assert!(status == Status::OK);
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn sanity_check_f16() {
+        assert_biteq!(sqrt(100.0f16), 10.0);
+        assert_biteq!(sqrt(4.0f16), 2.0);
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        spec_test::<f16>();
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    #[allow(clippy::approx_constant)]
+    fn conformance_tests_f16() {
+        let cases = [
+            (f16::PI, 0x3f17_u16),
+            // 10_000.0, using a hex literal for MSRV hack (Rust < 1.67 checks literal widths as
+            // part of the AST, so the `cfg` is irrelevant here).
+            (f16::from_bits(0x70e2), 0x5640_u16),
+            (f16::from_bits(0x0000000f), 0x13bf_u16),
+            (f16::INFINITY, f16::INFINITY.to_bits()),
+        ];
+
+        for (input, output) in cases {
+            assert_biteq!(
+                sqrt(input),
+                f16::from_bits(output),
+                "input: {input:?} ({:#018x})",
+                input.to_bits()
+            );
+        }
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_biteq!(sqrt(100.0f32), 10.0);
+        assert_biteq!(sqrt(4.0f32), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        spec_test::<f32>();
+    }
+
+    #[test]
+    #[allow(clippy::approx_constant)]
+    fn conformance_tests_f32() {
+        let cases = [
+            (f32::PI, 0x3fe2dfc5_u32),
+            (10000.0f32, 0x42c80000_u32),
+            (f32::from_bits(0x0000000f), 0x1b2f456f_u32),
+            (f32::INFINITY, f32::INFINITY.to_bits()),
+        ];
+
+        for (input, output) in cases {
+            assert_biteq!(
+                sqrt(input),
+                f32::from_bits(output),
+                "input: {input:?} ({:#018x})",
+                input.to_bits()
+            );
+        }
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_biteq!(sqrt(100.0f64), 10.0);
+        assert_biteq!(sqrt(4.0f64), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        spec_test::<f64>();
+    }
+
+    #[test]
+    #[allow(clippy::approx_constant)]
+    fn conformance_tests_f64() {
+        let cases = [
+            (f64::PI, 0x3ffc5bf891b4ef6a_u64),
+            (10000.0, 0x4059000000000000_u64),
+            (f64::from_bits(0x0000000f), 0x1e7efbdeb14f4eda_u64),
+            (f64::INFINITY, f64::INFINITY.to_bits()),
+        ];
+
+        for (input, output) in cases {
+            assert_biteq!(
+                sqrt(input),
+                f64::from_bits(output),
+                "input: {input:?} ({:#018x})",
+                input.to_bits()
+            );
+        }
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn sanity_check_f128() {
+        assert_biteq!(sqrt(100.0f128), 10.0);
+        assert_biteq!(sqrt(4.0f128), 2.0);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        spec_test::<f128>();
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    #[allow(clippy::approx_constant)]
+    fn conformance_tests_f128() {
+        let cases = [
+            (f128::PI, 0x3fffc5bf891b4ef6aa79c3b0520d5db9_u128),
+            // 10_000.0, see `f16` for reasoning.
+            (
+                f128::from_bits(0x400c3880000000000000000000000000),
+                0x40059000000000000000000000000000_u128,
+            ),
+            (
+                f128::from_bits(0x0000000f),
+                0x1fc9efbdeb14f4ed9b17ae807907e1e9_u128,
+            ),
+            (f128::INFINITY, f128::INFINITY.to_bits()),
+        ];
+
+        for (input, output) in cases {
+            assert_biteq!(
+                sqrt(input),
+                f128::from_bits(output),
+                "input: {input:?} ({:#018x})",
+                input.to_bits()
+            );
+        }
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/trunc.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/trunc.rs
new file mode 100644
index 0000000..29a28f47
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/trunc.rs
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: MIT
+ * origin: musl src/math/trunc.c */
+
+use super::super::support::{FpResult, Status};
+use super::super::{Float, Int, IntTy, MinInt};
+
+#[inline]
+pub fn trunc<F: Float>(x: F) -> F {
+    trunc_status(x).val
+}
+
+#[inline]
+pub fn trunc_status<F: Float>(x: F) -> FpResult<F> {
+    let mut xi: F::Int = x.to_bits();
+    let e: i32 = x.exp_unbiased();
+
+    // C1: The represented value has no fractional part, so no truncation is needed
+    if e >= F::SIG_BITS as i32 {
+        return FpResult::ok(x);
+    }
+
+    let mask = if e < 0 {
+        // C2: If the exponent is negative, the result will be zero so we mask out everything
+        // except the sign.
+        F::SIGN_MASK
+    } else {
+        // C3: Otherwise, we mask out the last `e` bits of the significand.
+        !(F::SIG_MASK >> e.unsigned())
+    };
+
+    // C4: If the to-be-masked-out portion is already zero, we have an exact result
+    if (xi & !mask) == IntTy::<F>::ZERO {
+        return FpResult::ok(x);
+    }
+
+    // C5: Otherwise the result is inexact and we will truncate. Raise `FE_INEXACT`, mask the
+    // result, and return.
+
+    let status = if xi & F::SIG_MASK == F::Int::ZERO {
+        Status::OK
+    } else {
+        Status::INEXACT
+    };
+    xi &= mask;
+    FpResult::new(F::from_bits(xi), status)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::Hexf;
+
+    fn spec_test<F: Float>(cases: &[(F, F, Status)]) {
+        let roundtrip = [
+            F::ZERO,
+            F::ONE,
+            F::NEG_ONE,
+            F::NEG_ZERO,
+            F::INFINITY,
+            F::NEG_INFINITY,
+        ];
+
+        for x in roundtrip {
+            let FpResult { val, status } = trunc_status(x);
+            assert_biteq!(val, x, "{}", Hexf(x));
+            assert_eq!(status, Status::OK, "{}", Hexf(x));
+        }
+
+        for &(x, res, res_stat) in cases {
+            let FpResult { val, status } = trunc_status(x);
+            assert_biteq!(val, res, "{}", Hexf(x));
+            assert_eq!(status, res_stat, "{}", Hexf(x));
+        }
+    }
+
+    /* Skipping f16 / f128 "sanity_check"s and spec cases due to rejected literal lexing at MSRV */
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_tests_f16() {
+        let cases = [];
+        spec_test::<f16>(&cases);
+    }
+
+    #[test]
+    fn sanity_check_f32() {
+        assert_eq!(trunc(0.5f32), 0.0);
+        assert_eq!(trunc(1.1f32), 1.0);
+        assert_eq!(trunc(2.9f32), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f32() {
+        let cases = [
+            (0.1, 0.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 0.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 1.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 1.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f32>(&cases);
+
+        assert_biteq!(trunc(1.1f32), 1.0);
+        assert_biteq!(trunc(1.1f64), 1.0);
+
+        // C1
+        assert_biteq!(trunc(hf32!("0x1p23")), hf32!("0x1p23"));
+        assert_biteq!(trunc(hf64!("0x1p52")), hf64!("0x1p52"));
+        assert_biteq!(trunc(hf32!("-0x1p23")), hf32!("-0x1p23"));
+        assert_biteq!(trunc(hf64!("-0x1p52")), hf64!("-0x1p52"));
+
+        // C2
+        assert_biteq!(trunc(hf32!("0x1p-1")), 0.0);
+        assert_biteq!(trunc(hf64!("0x1p-1")), 0.0);
+        assert_biteq!(trunc(hf32!("-0x1p-1")), -0.0);
+        assert_biteq!(trunc(hf64!("-0x1p-1")), -0.0);
+    }
+
+    #[test]
+    fn sanity_check_f64() {
+        assert_eq!(trunc(1.1f64), 1.0);
+        assert_eq!(trunc(2.9f64), 2.0);
+    }
+
+    #[test]
+    fn spec_tests_f64() {
+        let cases = [
+            (0.1, 0.0, Status::INEXACT),
+            (-0.1, -0.0, Status::INEXACT),
+            (0.9, 0.0, Status::INEXACT),
+            (-0.9, -0.0, Status::INEXACT),
+            (1.1, 1.0, Status::INEXACT),
+            (-1.1, -1.0, Status::INEXACT),
+            (1.9, 1.0, Status::INEXACT),
+            (-1.9, -1.0, Status::INEXACT),
+        ];
+        spec_test::<f64>(&cases);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_tests_f128() {
+        let cases = [];
+        spec_test::<f128>(&cases);
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogb.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogb.rs
index 9d58d06..5b41f7b 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogb.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogb.rs
@@ -21,7 +21,11 @@
         e
     } else if e == 0x7ff {
         force_eval!(0.0 / 0.0);
-        if (i << 12) != 0 { FP_ILOGBNAN } else { i32::max_value() }
+        if (i << 12) != 0 {
+            FP_ILOGBNAN
+        } else {
+            i32::MAX
+        }
     } else {
         e - 0x3ff
     }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogbf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogbf.rs
index 85deb43..3585d6d3 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogbf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogbf.rs
@@ -21,7 +21,7 @@
         e
     } else if e == 0xff {
         force_eval!(0.0 / 0.0);
-        if (i << 9) != 0 { FP_ILOGBNAN } else { i32::max_value() }
+        if (i << 9) != 0 { FP_ILOGBNAN } else { i32::MAX }
     } else {
         e - 0x7f
     }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0.rs
index 5e5e839..99d656f0 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0.rs
@@ -110,6 +110,7 @@
 const S04: f64 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
 
 /// Zeroth order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn j0(mut x: f64) -> f64 {
     let z: f64;
     let r: f64;
@@ -164,6 +165,7 @@
 const V04: f64 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
 
 /// Zeroth order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn y0(x: f64) -> f64 {
     let z: f64;
     let u: f64;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0f.rs
index afb6ee9b..25e5b32 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j0f.rs
@@ -63,6 +63,7 @@
 const S04: f32 = 1.1661400734e-09; /* 0x30a045e8 */
 
 /// Zeroth order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn j0f(mut x: f32) -> f32 {
     let z: f32;
     let r: f32;
@@ -109,6 +110,7 @@
 const V04: f32 = 4.4111031494e-10; /* 0x2ff280c2 */
 
 /// Zeroth order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn y0f(x: f32) -> f32 {
     let z: f32;
     let u: f32;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1.rs
index cef17a63..9b604d9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1.rs
@@ -114,6 +114,7 @@
 const S05: f64 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
 
 /// First order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn j1(x: f64) -> f64 {
     let mut z: f64;
     let r: f64;
@@ -160,6 +161,7 @@
 ];
 
 /// First order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn y1(x: f64) -> f64 {
     let z: f64;
     let u: f64;
@@ -171,10 +173,10 @@
     lx = get_low_word(x);
 
     /* y1(nan)=nan, y1(<0)=nan, y1(0)=-inf, y1(inf)=0 */
-    if (ix << 1 | lx) == 0 {
+    if (ix << 1) | lx == 0 {
         return -1.0 / 0.0;
     }
-    if (ix >> 31) != 0 {
+    if ix >> 31 != 0 {
         return 0.0 / 0.0;
     }
     if ix >= 0x7ff00000 {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1f.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1f.rs
index 02a3efd..a474724 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1f.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/j1f.rs
@@ -64,6 +64,7 @@
 const S05: f32 = 1.2354227016e-11; /* 0x2d59567e */
 
 /// First order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn j1f(x: f32) -> f32 {
     let mut z: f32;
     let r: f32;
@@ -109,6 +110,7 @@
 ];
 
 /// First order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn y1f(x: f32) -> f32 {
     let z: f32;
     let u: f32;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jn.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jn.rs
index aff051f..31f8d9c5 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jn.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jn.rs
@@ -39,6 +39,7 @@
 const INVSQRTPI: f64 = 5.64189583547756279280e-01; /* 0x3FE20DD7, 0x50429B6D */
 
 /// Integer order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn jn(n: i32, mut x: f64) -> f64 {
     let mut ix: u32;
     let lx: u32;
@@ -55,7 +56,7 @@
     ix &= 0x7fffffff;
 
     // -lx == !lx + 1
-    if (ix | (lx | ((!lx).wrapping_add(1))) >> 31) > 0x7ff00000 {
+    if ix | ((lx | (!lx).wrapping_add(1)) >> 31) > 0x7ff00000 {
         /* nan */
         return x;
     }
@@ -104,7 +105,8 @@
                 0 => -cos(x) + sin(x),
                 1 => -cos(x) - sin(x),
                 2 => cos(x) - sin(x),
-                3 | _ => cos(x) + sin(x),
+                // 3
+                _ => cos(x) + sin(x),
             };
             b = INVSQRTPI * temp / sqrt(x);
         } else {
@@ -118,130 +120,128 @@
                 a = temp;
             }
         }
-    } else {
-        if ix < 0x3e100000 {
-            /* x < 2**-29 */
-            /* x is tiny, return the first Taylor expansion of J(n,x)
-             * J(n,x) = 1/n!*(x/2)^n  - ...
-             */
-            if nm1 > 32 {
-                /* underflow */
-                b = 0.0;
-            } else {
-                temp = x * 0.5;
-                b = temp;
-                a = 1.0;
-                i = 2;
-                while i <= nm1 + 1 {
-                    a *= i as f64; /* a = n! */
-                    b *= temp; /* b = (x/2)^n */
-                    i += 1;
-                }
-                b = b / a;
-            }
+    } else if ix < 0x3e100000 {
+        /* x < 2**-29 */
+        /* x is tiny, return the first Taylor expansion of J(n,x)
+         * J(n,x) = 1/n!*(x/2)^n  - ...
+         */
+        if nm1 > 32 {
+            /* underflow */
+            b = 0.0;
         } else {
-            /* use backward recurrence */
-            /*                      x      x^2      x^2
-             *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
-             *                      2n  - 2(n+1) - 2(n+2)
-             *
-             *                      1      1        1
-             *  (for large x)   =  ----  ------   ------   .....
-             *                      2n   2(n+1)   2(n+2)
-             *                      -- - ------ - ------ -
-             *                       x     x         x
-             *
-             * Let w = 2n/x and h=2/x, then the above quotient
-             * is equal to the continued fraction:
-             *                  1
-             *      = -----------------------
-             *                     1
-             *         w - -----------------
-             *                        1
-             *              w+h - ---------
-             *                     w+2h - ...
-             *
-             * To determine how many terms needed, let
-             * Q(0) = w, Q(1) = w(w+h) - 1,
-             * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
-             * When Q(k) > 1e4      good for single
-             * When Q(k) > 1e9      good for double
-             * When Q(k) > 1e17     good for quadruple
-             */
-            /* determine k */
-            let mut t: f64;
-            let mut q0: f64;
-            let mut q1: f64;
-            let mut w: f64;
-            let h: f64;
-            let mut z: f64;
-            let mut tmp: f64;
-            let nf: f64;
-
-            let mut k: i32;
-
-            nf = (nm1 as f64) + 1.0;
-            w = 2.0 * nf / x;
-            h = 2.0 / x;
-            z = w + h;
-            q0 = w;
-            q1 = w * z - 1.0;
-            k = 1;
-            while q1 < 1.0e9 {
-                k += 1;
-                z += h;
-                tmp = z * q1 - q0;
-                q0 = q1;
-                q1 = tmp;
+            temp = x * 0.5;
+            b = temp;
+            a = 1.0;
+            i = 2;
+            while i <= nm1 + 1 {
+                a *= i as f64; /* a = n! */
+                b *= temp; /* b = (x/2)^n */
+                i += 1;
             }
-            t = 0.0;
-            i = k;
-            while i >= 0 {
-                t = 1.0 / (2.0 * ((i as f64) + nf) / x - t);
+            b = b / a;
+        }
+    } else {
+        /* use backward recurrence */
+        /*                      x      x^2      x^2
+         *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+         *                      2n  - 2(n+1) - 2(n+2)
+         *
+         *                      1      1        1
+         *  (for large x)   =  ----  ------   ------   .....
+         *                      2n   2(n+1)   2(n+2)
+         *                      -- - ------ - ------ -
+         *                       x     x         x
+         *
+         * Let w = 2n/x and h=2/x, then the above quotient
+         * is equal to the continued fraction:
+         *                  1
+         *      = -----------------------
+         *                     1
+         *         w - -----------------
+         *                        1
+         *              w+h - ---------
+         *                     w+2h - ...
+         *
+         * To determine how many terms needed, let
+         * Q(0) = w, Q(1) = w(w+h) - 1,
+         * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+         * When Q(k) > 1e4      good for single
+         * When Q(k) > 1e9      good for double
+         * When Q(k) > 1e17     good for quadruple
+         */
+        /* determine k */
+        let mut t: f64;
+        let mut q0: f64;
+        let mut q1: f64;
+        let mut w: f64;
+        let h: f64;
+        let mut z: f64;
+        let mut tmp: f64;
+        let nf: f64;
+
+        let mut k: i32;
+
+        nf = (nm1 as f64) + 1.0;
+        w = 2.0 * nf / x;
+        h = 2.0 / x;
+        z = w + h;
+        q0 = w;
+        q1 = w * z - 1.0;
+        k = 1;
+        while q1 < 1.0e9 {
+            k += 1;
+            z += h;
+            tmp = z * q1 - q0;
+            q0 = q1;
+            q1 = tmp;
+        }
+        t = 0.0;
+        i = k;
+        while i >= 0 {
+            t = 1.0 / (2.0 * ((i as f64) + nf) / x - t);
+            i -= 1;
+        }
+        a = t;
+        b = 1.0;
+        /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+         *  Hence, if n*(log(2n/x)) > ...
+         *  single 8.8722839355e+01
+         *  double 7.09782712893383973096e+02
+         *  long double 1.1356523406294143949491931077970765006170e+04
+         *  then recurrent value may overflow and the result is
+         *  likely underflow to zero
+         */
+        tmp = nf * log(fabs(w));
+        if tmp < 7.09782712893383973096e+02 {
+            i = nm1;
+            while i > 0 {
+                temp = b;
+                b = b * (2.0 * (i as f64)) / x - a;
+                a = temp;
                 i -= 1;
             }
-            a = t;
-            b = 1.0;
-            /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
-             *  Hence, if n*(log(2n/x)) > ...
-             *  single 8.8722839355e+01
-             *  double 7.09782712893383973096e+02
-             *  long double 1.1356523406294143949491931077970765006170e+04
-             *  then recurrent value may overflow and the result is
-             *  likely underflow to zero
-             */
-            tmp = nf * log(fabs(w));
-            if tmp < 7.09782712893383973096e+02 {
-                i = nm1;
-                while i > 0 {
-                    temp = b;
-                    b = b * (2.0 * (i as f64)) / x - a;
-                    a = temp;
-                    i -= 1;
+        } else {
+            i = nm1;
+            while i > 0 {
+                temp = b;
+                b = b * (2.0 * (i as f64)) / x - a;
+                a = temp;
+                /* scale b to avoid spurious overflow */
+                let x1p500 = f64::from_bits(0x5f30000000000000); // 0x1p500 == 2^500
+                if b > x1p500 {
+                    a /= b;
+                    t /= b;
+                    b = 1.0;
                 }
-            } else {
-                i = nm1;
-                while i > 0 {
-                    temp = b;
-                    b = b * (2.0 * (i as f64)) / x - a;
-                    a = temp;
-                    /* scale b to avoid spurious overflow */
-                    let x1p500 = f64::from_bits(0x5f30000000000000); // 0x1p500 == 2^500
-                    if b > x1p500 {
-                        a /= b;
-                        t /= b;
-                        b = 1.0;
-                    }
-                    i -= 1;
-                }
+                i -= 1;
             }
-            z = j0(x);
-            w = j1(x);
-            if fabs(z) >= fabs(w) {
-                b = t * z / b;
-            } else {
-                b = t * w / a;
-            }
+        }
+        z = j0(x);
+        w = j1(x);
+        if fabs(z) >= fabs(w) {
+            b = t * z / b;
+        } else {
+            b = t * w / a;
         }
     }
 
@@ -249,6 +249,7 @@
 }
 
 /// Integer order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f64).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn yn(n: i32, x: f64) -> f64 {
     let mut ix: u32;
     let lx: u32;
@@ -266,7 +267,7 @@
     ix &= 0x7fffffff;
 
     // -lx == !lx + 1
-    if (ix | (lx | ((!lx).wrapping_add(1))) >> 31) > 0x7ff00000 {
+    if ix | ((lx | (!lx).wrapping_add(1)) >> 31) > 0x7ff00000 {
         /* nan */
         return x;
     }
@@ -315,7 +316,8 @@
             0 => -sin(x) - cos(x),
             1 => -sin(x) + cos(x),
             2 => sin(x) + cos(x),
-            3 | _ => sin(x) - cos(x),
+            // 3
+            _ => sin(x) - cos(x),
         };
         b = INVSQRTPI * temp / sqrt(x);
     } else {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jnf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jnf.rs
index e5afda44..52cf7d8 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jnf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/jnf.rs
@@ -16,6 +16,7 @@
 use super::{fabsf, j0f, j1f, logf, y0f, y1f};
 
 /// Integer order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the first kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn jnf(n: i32, mut x: f32) -> f32 {
     let mut ix: u32;
     let mut nm1: i32;
@@ -64,128 +65,126 @@
             b = b * (2.0 * (i as f32) / x) - a;
             a = temp;
         }
+    } else if ix < 0x35800000 {
+        /* x < 2**-20 */
+        /* x is tiny, return the first Taylor expansion of J(n,x)
+         * J(n,x) = 1/n!*(x/2)^n  - ...
+         */
+        if nm1 > 8 {
+            /* underflow */
+            nm1 = 8;
+        }
+        temp = 0.5 * x;
+        b = temp;
+        a = 1.0;
+        i = 2;
+        while i <= nm1 + 1 {
+            a *= i as f32; /* a = n! */
+            b *= temp; /* b = (x/2)^n */
+            i += 1;
+        }
+        b = b / a;
     } else {
-        if ix < 0x35800000 {
-            /* x < 2**-20 */
-            /* x is tiny, return the first Taylor expansion of J(n,x)
-             * J(n,x) = 1/n!*(x/2)^n  - ...
-             */
-            if nm1 > 8 {
-                /* underflow */
-                nm1 = 8;
-            }
-            temp = 0.5 * x;
-            b = temp;
-            a = 1.0;
-            i = 2;
-            while i <= nm1 + 1 {
-                a *= i as f32; /* a = n! */
-                b *= temp; /* b = (x/2)^n */
-                i += 1;
-            }
-            b = b / a;
-        } else {
-            /* use backward recurrence */
-            /*                      x      x^2      x^2
-             *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
-             *                      2n  - 2(n+1) - 2(n+2)
-             *
-             *                      1      1        1
-             *  (for large x)   =  ----  ------   ------   .....
-             *                      2n   2(n+1)   2(n+2)
-             *                      -- - ------ - ------ -
-             *                       x     x         x
-             *
-             * Let w = 2n/x and h=2/x, then the above quotient
-             * is equal to the continued fraction:
-             *                  1
-             *      = -----------------------
-             *                     1
-             *         w - -----------------
-             *                        1
-             *              w+h - ---------
-             *                     w+2h - ...
-             *
-             * To determine how many terms needed, let
-             * Q(0) = w, Q(1) = w(w+h) - 1,
-             * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
-             * When Q(k) > 1e4      good for single
-             * When Q(k) > 1e9      good for double
-             * When Q(k) > 1e17     good for quadruple
-             */
-            /* determine k */
-            let mut t: f32;
-            let mut q0: f32;
-            let mut q1: f32;
-            let mut w: f32;
-            let h: f32;
-            let mut z: f32;
-            let mut tmp: f32;
-            let nf: f32;
-            let mut k: i32;
+        /* use backward recurrence */
+        /*                      x      x^2      x^2
+         *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
+         *                      2n  - 2(n+1) - 2(n+2)
+         *
+         *                      1      1        1
+         *  (for large x)   =  ----  ------   ------   .....
+         *                      2n   2(n+1)   2(n+2)
+         *                      -- - ------ - ------ -
+         *                       x     x         x
+         *
+         * Let w = 2n/x and h=2/x, then the above quotient
+         * is equal to the continued fraction:
+         *                  1
+         *      = -----------------------
+         *                     1
+         *         w - -----------------
+         *                        1
+         *              w+h - ---------
+         *                     w+2h - ...
+         *
+         * To determine how many terms needed, let
+         * Q(0) = w, Q(1) = w(w+h) - 1,
+         * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+         * When Q(k) > 1e4      good for single
+         * When Q(k) > 1e9      good for double
+         * When Q(k) > 1e17     good for quadruple
+         */
+        /* determine k */
+        let mut t: f32;
+        let mut q0: f32;
+        let mut q1: f32;
+        let mut w: f32;
+        let h: f32;
+        let mut z: f32;
+        let mut tmp: f32;
+        let nf: f32;
+        let mut k: i32;
 
-            nf = (nm1 as f32) + 1.0;
-            w = 2.0 * (nf as f32) / x;
-            h = 2.0 / x;
-            z = w + h;
-            q0 = w;
-            q1 = w * z - 1.0;
-            k = 1;
-            while q1 < 1.0e4 {
-                k += 1;
-                z += h;
-                tmp = z * q1 - q0;
-                q0 = q1;
-                q1 = tmp;
-            }
-            t = 0.0;
-            i = k;
-            while i >= 0 {
-                t = 1.0 / (2.0 * ((i as f32) + nf) / x - t);
+        nf = (nm1 as f32) + 1.0;
+        w = 2.0 * nf / x;
+        h = 2.0 / x;
+        z = w + h;
+        q0 = w;
+        q1 = w * z - 1.0;
+        k = 1;
+        while q1 < 1.0e4 {
+            k += 1;
+            z += h;
+            tmp = z * q1 - q0;
+            q0 = q1;
+            q1 = tmp;
+        }
+        t = 0.0;
+        i = k;
+        while i >= 0 {
+            t = 1.0 / (2.0 * ((i as f32) + nf) / x - t);
+            i -= 1;
+        }
+        a = t;
+        b = 1.0;
+        /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+         *  Hence, if n*(log(2n/x)) > ...
+         *  single 8.8722839355e+01
+         *  double 7.09782712893383973096e+02
+         *  long double 1.1356523406294143949491931077970765006170e+04
+         *  then recurrent value may overflow and the result is
+         *  likely underflow to zero
+         */
+        tmp = nf * logf(fabsf(w));
+        if tmp < 88.721679688 {
+            i = nm1;
+            while i > 0 {
+                temp = b;
+                b = 2.0 * (i as f32) * b / x - a;
+                a = temp;
                 i -= 1;
             }
-            a = t;
-            b = 1.0;
-            /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
-             *  Hence, if n*(log(2n/x)) > ...
-             *  single 8.8722839355e+01
-             *  double 7.09782712893383973096e+02
-             *  long double 1.1356523406294143949491931077970765006170e+04
-             *  then recurrent value may overflow and the result is
-             *  likely underflow to zero
-             */
-            tmp = nf * logf(fabsf(w));
-            if tmp < 88.721679688 {
-                i = nm1;
-                while i > 0 {
-                    temp = b;
-                    b = 2.0 * (i as f32) * b / x - a;
-                    a = temp;
-                    i -= 1;
+        } else {
+            i = nm1;
+            while i > 0 {
+                temp = b;
+                b = 2.0 * (i as f32) * b / x - a;
+                a = temp;
+                /* scale b to avoid spurious overflow */
+                let x1p60 = f32::from_bits(0x5d800000); // 0x1p60 == 2^60
+                if b > x1p60 {
+                    a /= b;
+                    t /= b;
+                    b = 1.0;
                 }
-            } else {
-                i = nm1;
-                while i > 0 {
-                    temp = b;
-                    b = 2.0 * (i as f32) * b / x - a;
-                    a = temp;
-                    /* scale b to avoid spurious overflow */
-                    let x1p60 = f32::from_bits(0x5d800000); // 0x1p60 == 2^60
-                    if b > x1p60 {
-                        a /= b;
-                        t /= b;
-                        b = 1.0;
-                    }
-                    i -= 1;
-                }
+                i -= 1;
             }
-            z = j0f(x);
-            w = j1f(x);
-            if fabsf(z) >= fabsf(w) {
-                b = t * z / b;
-            } else {
-                b = t * w / a;
-            }
+        }
+        z = j0f(x);
+        w = j1f(x);
+        if fabsf(z) >= fabsf(w) {
+            b = t * z / b;
+        } else {
+            b = t * w / a;
         }
     }
 
@@ -193,6 +192,7 @@
 }
 
 /// Integer order of the [Bessel function](https://en.wikipedia.org/wiki/Bessel_function) of the second kind (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn ynf(n: i32, x: f32) -> f32 {
     let mut ix: u32;
     let mut ib: u32;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/k_sin.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/k_sin.rs
index 4244145..9dd96c9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/k_sin.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/k_sin.rs
@@ -49,5 +49,9 @@
     let w = z * z;
     let r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6);
     let v = z * x;
-    if iy == 0 { x + v * (S1 + z * r) } else { x - ((z * (0.5 * y - v * r) - y) - v * S1) }
+    if iy == 0 {
+        x + v * (S1 + z * r)
+    } else {
+        x - ((z * (0.5 * y - v * r) - y) - v * S1)
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexp.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexp.rs
index e46242e..24899ba 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexp.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexp.rs
@@ -1,4 +1,21 @@
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ldexpf16(x: f16, n: i32) -> f16 {
+    super::scalbnf16(x, n)
+}
+
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ldexpf(x: f32, n: i32) -> f32 {
+    super::scalbnf(x, n)
+}
+
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn ldexp(x: f64, n: i32) -> f64 {
     super::scalbn(x, n)
 }
+
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ldexpf128(x: f128, n: i32) -> f128 {
+    super::scalbnf128(x, n)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf128.rs
new file mode 100644
index 0000000..b35277d
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf128.rs
@@ -0,0 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ldexpf128(x: f128, n: i32) -> f128 {
+    super::scalbnf128(x, n)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf16.rs
new file mode 100644
index 0000000..8de6cff
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf16.rs
@@ -0,0 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn ldexpf16(x: f16, n: i32) -> f16 {
+    super::scalbnf16(x, n)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma.rs
index a08bc5b..8312dc1 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma.rs
@@ -1,5 +1,7 @@
 use super::lgamma_r;
 
+/// The natural logarithm of the
+/// [Gamma function](https://en.wikipedia.org/wiki/Gamma_function) (f64).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn lgamma(x: f64) -> f64 {
     lgamma_r(x).0
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma_r.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma_r.rs
index b26177e..6becaad 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma_r.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma_r.rs
@@ -160,7 +160,8 @@
         1 => k_cos(x, 0.0),
         2 => k_sin(-x, 0.0, 0),
         3 => -k_cos(x, 0.0),
-        0 | _ => k_sin(x, 0.0, 0),
+        // 0
+        _ => k_sin(x, 0.0, 0),
     }
 }
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf.rs
index a9c2da75..d375123 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf.rs
@@ -1,5 +1,7 @@
 use super::lgammaf_r;
 
+/// The natural logarithm of the
+/// [Gamma function](https://en.wikipedia.org/wiki/Gamma_function) (f32).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn lgammaf(x: f32) -> f32 {
     lgammaf_r(x).0
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf_r.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf_r.rs
index 723c90d..10cecee 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf_r.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf_r.rs
@@ -95,7 +95,8 @@
         1 => k_cosf(y),
         2 => k_sinf(-y),
         3 => -k_cosf(y),
-        0 | _ => k_sinf(y),
+        // 0
+        _ => k_sinf(y),
     }
 }
 
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log10.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log10.rs
index f9d118f..8c9d68c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log10.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log10.rs
@@ -78,7 +78,7 @@
     hx += 0x3ff00000 - 0x3fe6a09e;
     k += (hx >> 20) as i32 - 0x3ff;
     hx = (hx & 0x000fffff) + 0x3fe6a09e;
-    ui = (hx as u64) << 32 | (ui & 0xffffffff);
+    ui = ((hx as u64) << 32) | (ui & 0xffffffff);
     x = f64::from_bits(ui);
 
     f = x - 1.0;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1p.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1p.rs
index 80561ec..65142c0 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1p.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1p.rs
@@ -118,14 +118,18 @@
         k = (hu >> 20) as i32 - 0x3ff;
         /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
         if k < 54 {
-            c = if k >= 2 { 1. - (f64::from_bits(ui) - x) } else { x - (f64::from_bits(ui) - 1.) };
+            c = if k >= 2 {
+                1. - (f64::from_bits(ui) - x)
+            } else {
+                x - (f64::from_bits(ui) - 1.)
+            };
             c /= f64::from_bits(ui);
         } else {
             c = 0.;
         }
         /* reduce u into [sqrt(2)/2, sqrt(2)] */
         hu = (hu & 0x000fffff) + 0x3fe6a09e;
-        ui = (hu as u64) << 32 | (ui & 0xffffffff);
+        ui = ((hu as u64) << 32) | (ui & 0xffffffff);
         f = f64::from_bits(ui) - 1.;
     }
     hfsq = 0.5 * f * f;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1pf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1pf.rs
index bba5b8a..23978e6 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1pf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log1pf.rs
@@ -73,7 +73,11 @@
         k = (iu >> 23) as i32 - 0x7f;
         /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
         if k < 25 {
-            c = if k >= 2 { 1. - (f32::from_bits(ui) - x) } else { x - (f32::from_bits(ui) - 1.) };
+            c = if k >= 2 {
+                1. - (f32::from_bits(ui) - x)
+            } else {
+                x - (f32::from_bits(ui) - 1.)
+            };
             c /= f32::from_bits(ui);
         } else {
             c = 0.;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log2.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log2.rs
index 5953334..701f63c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log2.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/log2.rs
@@ -75,7 +75,7 @@
     hx += 0x3ff00000 - 0x3fe6a09e;
     k += (hx >> 20) as i32 - 0x3ff;
     hx = (hx & 0x000fffff) + 0x3fe6a09e;
-    ui = (hx as u64) << 32 | (ui & 0xffffffff);
+    ui = ((hx as u64) << 32) | (ui & 0xffffffff);
     x = f64::from_bits(ui);
 
     f = x - 1.0;
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/mod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/mod.rs
index 85c9fc5..949c18b40 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/mod.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/mod.rs
@@ -60,250 +60,40 @@
 // the time of this writing this is only used in a few places, and once
 // rust-lang/rust#72751 is fixed then this macro will no longer be necessary and
 // the native `/` operator can be used and panics won't be codegen'd.
-#[cfg(any(debug_assertions, not(feature = "unstable")))]
+#[cfg(any(debug_assertions, not(intrinsics_enabled)))]
 macro_rules! div {
     ($a:expr, $b:expr) => {
         $a / $b
     };
 }
 
-#[cfg(all(not(debug_assertions), feature = "unstable"))]
+#[cfg(all(not(debug_assertions), intrinsics_enabled))]
 macro_rules! div {
     ($a:expr, $b:expr) => {
         unsafe { core::intrinsics::unchecked_div($a, $b) }
     };
 }
 
-macro_rules! llvm_intrinsically_optimized {
-    (#[cfg($($clause:tt)*)] $e:expr) => {
-        #[cfg(all(feature = "unstable", not(feature = "force-soft-floats"), $($clause)*))]
-        {
-            if true { // thwart the dead code lint
-                $e
-            }
-        }
-    };
+// `support` may be public for testing
+#[macro_use]
+#[cfg(feature = "unstable-public-internals")]
+pub mod support;
+
+#[macro_use]
+#[cfg(not(feature = "unstable-public-internals"))]
+pub(crate) mod support;
+
+cfg_if! {
+    if #[cfg(feature = "unstable-public-internals")] {
+        pub mod generic;
+    } else {
+        mod generic;
+    }
 }
 
-// Public modules
-mod acos;
-mod acosf;
-mod acosh;
-mod acoshf;
-mod asin;
-mod asinf;
-mod asinh;
-mod asinhf;
-mod atan;
-mod atan2;
-mod atan2f;
-mod atanf;
-mod atanh;
-mod atanhf;
-mod cbrt;
-mod cbrtf;
-mod ceil;
-mod ceilf;
-mod copysign;
-mod copysignf;
-mod cos;
-mod cosf;
-mod cosh;
-mod coshf;
-mod erf;
-mod erff;
-mod exp;
-mod exp10;
-mod exp10f;
-mod exp2;
-mod exp2f;
-mod expf;
-mod expm1;
-mod expm1f;
-mod fabs;
-mod fabsf;
-mod fdim;
-mod fdimf;
-mod floor;
-mod floorf;
-mod fma;
-mod fmaf;
-mod fmax;
-mod fmaxf;
-mod fmin;
-mod fminf;
-mod fmod;
-mod fmodf;
-mod frexp;
-mod frexpf;
-mod hypot;
-mod hypotf;
-mod ilogb;
-mod ilogbf;
-mod j0;
-mod j0f;
-mod j1;
-mod j1f;
-mod jn;
-mod jnf;
-mod ldexp;
-mod ldexpf;
-mod lgamma;
-mod lgamma_r;
-mod lgammaf;
-mod lgammaf_r;
-mod log;
-mod log10;
-mod log10f;
-mod log1p;
-mod log1pf;
-mod log2;
-mod log2f;
-mod logf;
-mod modf;
-mod modff;
-mod nextafter;
-mod nextafterf;
-mod pow;
-mod powf;
-mod remainder;
-mod remainderf;
-mod remquo;
-mod remquof;
-mod rint;
-mod rintf;
-mod round;
-mod roundf;
-mod scalbn;
-mod scalbnf;
-mod sin;
-mod sincos;
-mod sincosf;
-mod sinf;
-mod sinh;
-mod sinhf;
-mod sqrt;
-mod sqrtf;
-mod tan;
-mod tanf;
-mod tanh;
-mod tanhf;
-mod tgamma;
-mod tgammaf;
-mod trunc;
-mod truncf;
-
-// Use separated imports instead of {}-grouped imports for easier merging.
-pub use self::acos::acos;
-pub use self::acosf::acosf;
-pub use self::acosh::acosh;
-pub use self::acoshf::acoshf;
-pub use self::asin::asin;
-pub use self::asinf::asinf;
-pub use self::asinh::asinh;
-pub use self::asinhf::asinhf;
-pub use self::atan::atan;
-pub use self::atan2::atan2;
-pub use self::atan2f::atan2f;
-pub use self::atanf::atanf;
-pub use self::atanh::atanh;
-pub use self::atanhf::atanhf;
-pub use self::cbrt::cbrt;
-pub use self::cbrtf::cbrtf;
-pub use self::ceil::ceil;
-pub use self::ceilf::ceilf;
-pub use self::copysign::copysign;
-pub use self::copysignf::copysignf;
-pub use self::cos::cos;
-pub use self::cosf::cosf;
-pub use self::cosh::cosh;
-pub use self::coshf::coshf;
-pub use self::erf::{erf, erfc};
-pub use self::erff::{erfcf, erff};
-pub use self::exp::exp;
-pub use self::exp2::exp2;
-pub use self::exp2f::exp2f;
-pub use self::exp10::exp10;
-pub use self::exp10f::exp10f;
-pub use self::expf::expf;
-pub use self::expm1::expm1;
-pub use self::expm1f::expm1f;
-pub use self::fabs::fabs;
-pub use self::fabsf::fabsf;
-pub use self::fdim::fdim;
-pub use self::fdimf::fdimf;
-pub use self::floor::floor;
-pub use self::floorf::floorf;
-pub use self::fma::fma;
-pub use self::fmaf::fmaf;
-pub use self::fmax::fmax;
-pub use self::fmaxf::fmaxf;
-pub use self::fmin::fmin;
-pub use self::fminf::fminf;
-pub use self::fmod::fmod;
-pub use self::fmodf::fmodf;
-pub use self::frexp::frexp;
-pub use self::frexpf::frexpf;
-pub use self::hypot::hypot;
-pub use self::hypotf::hypotf;
-pub use self::ilogb::ilogb;
-pub use self::ilogbf::ilogbf;
-pub use self::j0::{j0, y0};
-pub use self::j0f::{j0f, y0f};
-pub use self::j1::{j1, y1};
-pub use self::j1f::{j1f, y1f};
-pub use self::jn::{jn, yn};
-pub use self::jnf::{jnf, ynf};
-pub use self::ldexp::ldexp;
-pub use self::ldexpf::ldexpf;
-pub use self::lgamma::lgamma;
-pub use self::lgamma_r::lgamma_r;
-pub use self::lgammaf::lgammaf;
-pub use self::lgammaf_r::lgammaf_r;
-pub use self::log::log;
-pub use self::log1p::log1p;
-pub use self::log1pf::log1pf;
-pub use self::log2::log2;
-pub use self::log2f::log2f;
-pub use self::log10::log10;
-pub use self::log10f::log10f;
-pub use self::logf::logf;
-pub use self::modf::modf;
-pub use self::modff::modff;
-pub use self::nextafter::nextafter;
-pub use self::nextafterf::nextafterf;
-pub use self::pow::pow;
-pub use self::powf::powf;
-pub use self::remainder::remainder;
-pub use self::remainderf::remainderf;
-pub use self::remquo::remquo;
-pub use self::remquof::remquof;
-pub use self::rint::rint;
-pub use self::rintf::rintf;
-pub use self::round::round;
-pub use self::roundf::roundf;
-pub use self::scalbn::scalbn;
-pub use self::scalbnf::scalbnf;
-pub use self::sin::sin;
-pub use self::sincos::sincos;
-pub use self::sincosf::sincosf;
-pub use self::sinf::sinf;
-pub use self::sinh::sinh;
-pub use self::sinhf::sinhf;
-pub use self::sqrt::sqrt;
-pub use self::sqrtf::sqrtf;
-pub use self::tan::tan;
-pub use self::tanf::tanf;
-pub use self::tanh::tanh;
-pub use self::tanhf::tanhf;
-pub use self::tgamma::tgamma;
-pub use self::tgammaf::tgammaf;
-pub use self::trunc::trunc;
-pub use self::truncf::truncf;
-
 // Private modules
+mod arch;
 mod expo2;
-mod fenv;
 mod k_cos;
 mod k_cosf;
 mod k_expo2;
@@ -329,6 +119,250 @@
 use self::rem_pio2::rem_pio2;
 use self::rem_pio2_large::rem_pio2_large;
 use self::rem_pio2f::rem_pio2f;
+#[allow(unused_imports)]
+use self::support::{CastFrom, CastInto, DFloat, DInt, Float, HFloat, HInt, Int, IntTy, MinInt};
+
+// Public modules
+mod acos;
+mod acosf;
+mod acosh;
+mod acoshf;
+mod asin;
+mod asinf;
+mod asinh;
+mod asinhf;
+mod atan;
+mod atan2;
+mod atan2f;
+mod atanf;
+mod atanh;
+mod atanhf;
+mod cbrt;
+mod cbrtf;
+mod ceil;
+mod copysign;
+mod cos;
+mod cosf;
+mod cosh;
+mod coshf;
+mod erf;
+mod erff;
+mod exp;
+mod exp10;
+mod exp10f;
+mod exp2;
+mod exp2f;
+mod expf;
+mod expm1;
+mod expm1f;
+mod fabs;
+mod fdim;
+mod floor;
+mod fma;
+mod fma_wide;
+mod fmin_fmax;
+mod fminimum_fmaximum;
+mod fminimum_fmaximum_num;
+mod fmod;
+mod frexp;
+mod frexpf;
+mod hypot;
+mod hypotf;
+mod ilogb;
+mod ilogbf;
+mod j0;
+mod j0f;
+mod j1;
+mod j1f;
+mod jn;
+mod jnf;
+mod ldexp;
+mod lgamma;
+mod lgamma_r;
+mod lgammaf;
+mod lgammaf_r;
+mod log;
+mod log10;
+mod log10f;
+mod log1p;
+mod log1pf;
+mod log2;
+mod log2f;
+mod logf;
+mod modf;
+mod modff;
+mod nextafter;
+mod nextafterf;
+mod pow;
+mod powf;
+mod remainder;
+mod remainderf;
+mod remquo;
+mod remquof;
+mod rint;
+mod round;
+mod roundeven;
+mod scalbn;
+mod sin;
+mod sincos;
+mod sincosf;
+mod sinf;
+mod sinh;
+mod sinhf;
+mod sqrt;
+mod tan;
+mod tanf;
+mod tanh;
+mod tanhf;
+mod tgamma;
+mod tgammaf;
+mod trunc;
+
+// Use separated imports instead of {}-grouped imports for easier merging.
+pub use self::acos::acos;
+pub use self::acosf::acosf;
+pub use self::acosh::acosh;
+pub use self::acoshf::acoshf;
+pub use self::asin::asin;
+pub use self::asinf::asinf;
+pub use self::asinh::asinh;
+pub use self::asinhf::asinhf;
+pub use self::atan::atan;
+pub use self::atan2::atan2;
+pub use self::atan2f::atan2f;
+pub use self::atanf::atanf;
+pub use self::atanh::atanh;
+pub use self::atanhf::atanhf;
+pub use self::cbrt::cbrt;
+pub use self::cbrtf::cbrtf;
+pub use self::ceil::{ceil, ceilf};
+pub use self::copysign::{copysign, copysignf};
+pub use self::cos::cos;
+pub use self::cosf::cosf;
+pub use self::cosh::cosh;
+pub use self::coshf::coshf;
+pub use self::erf::{erf, erfc};
+pub use self::erff::{erfcf, erff};
+pub use self::exp::exp;
+pub use self::exp2::exp2;
+pub use self::exp2f::exp2f;
+pub use self::exp10::exp10;
+pub use self::exp10f::exp10f;
+pub use self::expf::expf;
+pub use self::expm1::expm1;
+pub use self::expm1f::expm1f;
+pub use self::fabs::{fabs, fabsf};
+pub use self::fdim::{fdim, fdimf};
+pub use self::floor::{floor, floorf};
+pub use self::fma::fma;
+pub use self::fma_wide::fmaf;
+pub use self::fmin_fmax::{fmax, fmaxf, fmin, fminf};
+pub use self::fminimum_fmaximum::{fmaximum, fmaximumf, fminimum, fminimumf};
+pub use self::fminimum_fmaximum_num::{fmaximum_num, fmaximum_numf, fminimum_num, fminimum_numf};
+pub use self::fmod::{fmod, fmodf};
+pub use self::frexp::frexp;
+pub use self::frexpf::frexpf;
+pub use self::hypot::hypot;
+pub use self::hypotf::hypotf;
+pub use self::ilogb::ilogb;
+pub use self::ilogbf::ilogbf;
+pub use self::j0::{j0, y0};
+pub use self::j0f::{j0f, y0f};
+pub use self::j1::{j1, y1};
+pub use self::j1f::{j1f, y1f};
+pub use self::jn::{jn, yn};
+pub use self::jnf::{jnf, ynf};
+pub use self::ldexp::{ldexp, ldexpf};
+pub use self::lgamma::lgamma;
+pub use self::lgamma_r::lgamma_r;
+pub use self::lgammaf::lgammaf;
+pub use self::lgammaf_r::lgammaf_r;
+pub use self::log::log;
+pub use self::log1p::log1p;
+pub use self::log1pf::log1pf;
+pub use self::log2::log2;
+pub use self::log2f::log2f;
+pub use self::log10::log10;
+pub use self::log10f::log10f;
+pub use self::logf::logf;
+pub use self::modf::modf;
+pub use self::modff::modff;
+pub use self::nextafter::nextafter;
+pub use self::nextafterf::nextafterf;
+pub use self::pow::pow;
+pub use self::powf::powf;
+pub use self::remainder::remainder;
+pub use self::remainderf::remainderf;
+pub use self::remquo::remquo;
+pub use self::remquof::remquof;
+pub use self::rint::{rint, rintf};
+pub use self::round::{round, roundf};
+pub use self::roundeven::{roundeven, roundevenf};
+pub use self::scalbn::{scalbn, scalbnf};
+pub use self::sin::sin;
+pub use self::sincos::sincos;
+pub use self::sincosf::sincosf;
+pub use self::sinf::sinf;
+pub use self::sinh::sinh;
+pub use self::sinhf::sinhf;
+pub use self::sqrt::{sqrt, sqrtf};
+pub use self::tan::tan;
+pub use self::tanf::tanf;
+pub use self::tanh::tanh;
+pub use self::tanhf::tanhf;
+pub use self::tgamma::tgamma;
+pub use self::tgammaf::tgammaf;
+pub use self::trunc::{trunc, truncf};
+
+cfg_if! {
+    if #[cfg(f16_enabled)] {
+        // verify-sorted-start
+        pub use self::ceil::ceilf16;
+        pub use self::copysign::copysignf16;
+        pub use self::fabs::fabsf16;
+        pub use self::fdim::fdimf16;
+        pub use self::floor::floorf16;
+        pub use self::fmin_fmax::{fmaxf16, fminf16};
+        pub use self::fminimum_fmaximum::{fmaximumf16, fminimumf16};
+        pub use self::fminimum_fmaximum_num::{fmaximum_numf16, fminimum_numf16};
+        pub use self::fmod::fmodf16;
+        pub use self::ldexp::ldexpf16;
+        pub use self::rint::rintf16;
+        pub use self::round::roundf16;
+        pub use self::roundeven::roundevenf16;
+        pub use self::scalbn::scalbnf16;
+        pub use self::sqrt::sqrtf16;
+        pub use self::trunc::truncf16;
+        // verify-sorted-end
+
+        #[allow(unused_imports)]
+        pub(crate) use self::fma_wide::fmaf16;
+    }
+}
+
+cfg_if! {
+    if #[cfg(f128_enabled)] {
+        // verify-sorted-start
+        pub use self::ceil::ceilf128;
+        pub use self::copysign::copysignf128;
+        pub use self::fabs::fabsf128;
+        pub use self::fdim::fdimf128;
+        pub use self::floor::floorf128;
+        pub use self::fma::fmaf128;
+        pub use self::fmin_fmax::{fmaxf128, fminf128};
+        pub use self::fminimum_fmaximum::{fmaximumf128, fminimumf128};
+        pub use self::fminimum_fmaximum_num::{fmaximum_numf128, fminimum_numf128};
+        pub use self::fmod::fmodf128;
+        pub use self::ldexp::ldexpf128;
+        pub use self::rint::rintf128;
+        pub use self::round::roundf128;
+        pub use self::roundeven::roundevenf128;
+        pub use self::scalbn::scalbnf128;
+        pub use self::sqrt::sqrtf128;
+        pub use self::trunc::truncf128;
+        // verify-sorted-end
+    }
+}
 
 #[inline]
 fn get_high_word(x: f64) -> u32 {
@@ -358,5 +392,5 @@
 
 #[inline]
 fn combine_words(hi: u32, lo: u32) -> f64 {
-    f64::from_bits((hi as u64) << 32 | lo as u64)
+    f64::from_bits(((hi as u64) << 32) | lo as u64)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modf.rs
index bcab33a..6541862 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modf.rs
@@ -1,8 +1,9 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn modf(x: f64) -> (f64, f64) {
     let rv2: f64;
     let mut u = x.to_bits();
     let mask: u64;
-    let e = ((u >> 52 & 0x7ff) as i32) - 0x3ff;
+    let e = (((u >> 52) & 0x7ff) as i32) - 0x3ff;
 
     /* no fractional part */
     if e >= 52 {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modff.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modff.rs
index 56ece12e..90c6bca7 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modff.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/modff.rs
@@ -1,8 +1,9 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn modff(x: f32) -> (f32, f32) {
     let rv2: f32;
     let mut u: u32 = x.to_bits();
     let mask: u32;
-    let e = ((u >> 23 & 0xff) as i32) - 0x7f;
+    let e = (((u >> 23) & 0xff) as i32) - 0x7f;
 
     /* no fractional part */
     if e >= 23 {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/nextafter.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/nextafter.rs
index 0576261..c991ff6 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/nextafter.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/nextafter.rs
@@ -10,20 +10,20 @@
         return y;
     }
 
-    let ax = ux_i & !1_u64 / 2;
-    let ay = uy_i & !1_u64 / 2;
+    let ax = ux_i & (!1_u64 / 2);
+    let ay = uy_i & (!1_u64 / 2);
     if ax == 0 {
         if ay == 0 {
             return y;
         }
-        ux_i = (uy_i & 1_u64 << 63) | 1;
-    } else if ax > ay || ((ux_i ^ uy_i) & 1_u64 << 63) != 0 {
+        ux_i = (uy_i & (1_u64 << 63)) | 1;
+    } else if ax > ay || ((ux_i ^ uy_i) & (1_u64 << 63)) != 0 {
         ux_i -= 1;
     } else {
         ux_i += 1;
     }
 
-    let e = ux_i >> 52 & 0x7ff;
+    let e = (ux_i >> 52) & 0x7ff;
     // raise overflow if ux.f is infinite and x is finite
     if e == 0x7ff {
         force_eval!(x + x);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/pow.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/pow.rs
index 7ecad29..7e7d049 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/pow.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/pow.rs
@@ -98,8 +98,8 @@
     let (hx, lx): (i32, u32) = ((x.to_bits() >> 32) as i32, x.to_bits() as u32);
     let (hy, ly): (i32, u32) = ((y.to_bits() >> 32) as i32, y.to_bits() as u32);
 
-    let mut ix: i32 = (hx & 0x7fffffff) as i32;
-    let iy: i32 = (hy & 0x7fffffff) as i32;
+    let mut ix: i32 = hx & 0x7fffffff_i32;
+    let iy: i32 = hy & 0x7fffffff_i32;
 
     /* x**0 = 1, even if x is NaN */
     if ((iy as u32) | ly) == 0 {
@@ -239,10 +239,18 @@
 
         /* over/underflow if x is not close to one */
         if ix < 0x3fefffff {
-            return if hy < 0 { s * HUGE * HUGE } else { s * TINY * TINY };
+            return if hy < 0 {
+                s * HUGE * HUGE
+            } else {
+                s * TINY * TINY
+            };
         }
         if ix > 0x3ff00000 {
-            return if hy > 0 { s * HUGE * HUGE } else { s * TINY * TINY };
+            return if hy > 0 {
+                s * HUGE * HUGE
+            } else {
+                s * TINY * TINY
+            };
         }
 
         /* now |1-x| is TINY <= 2**-20, suffice to compute
@@ -355,7 +363,7 @@
     }
 
     /* compute 2**(p_h+p_l) */
-    let i: i32 = j & (0x7fffffff as i32);
+    let i: i32 = j & 0x7fffffff_i32;
     k = (i >> 20) - 0x3ff;
     let mut n: i32 = 0;
 
@@ -398,7 +406,6 @@
     extern crate core;
 
     use self::core::f64::consts::{E, PI};
-    use self::core::f64::{EPSILON, INFINITY, MAX, MIN, MIN_POSITIVE, NAN, NEG_INFINITY};
     use super::pow;
 
     const POS_ZERO: &[f64] = &[0.0];
@@ -407,15 +414,15 @@
     const NEG_ONE: &[f64] = &[-1.0];
     const POS_FLOATS: &[f64] = &[99.0 / 70.0, E, PI];
     const NEG_FLOATS: &[f64] = &[-99.0 / 70.0, -E, -PI];
-    const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), MIN_POSITIVE, EPSILON];
-    const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -MIN_POSITIVE, -EPSILON];
-    const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, MAX];
-    const NEG_EVENS: &[f64] = &[MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0];
+    const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), f64::MIN_POSITIVE, f64::EPSILON];
+    const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -f64::MIN_POSITIVE, -f64::EPSILON];
+    const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, f64::MAX];
+    const NEG_EVENS: &[f64] = &[f64::MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0];
     const POS_ODDS: &[f64] = &[3.0, 7.0];
     const NEG_ODDS: &[f64] = &[-7.0, -3.0];
-    const NANS: &[f64] = &[NAN];
-    const POS_INF: &[f64] = &[INFINITY];
-    const NEG_INF: &[f64] = &[NEG_INFINITY];
+    const NANS: &[f64] = &[f64::NAN];
+    const POS_INF: &[f64] = &[f64::INFINITY];
+    const NEG_INF: &[f64] = &[f64::NEG_INFINITY];
 
     const ALL: &[&[f64]] = &[
         POS_ZERO,
@@ -440,7 +447,11 @@
     fn pow_test(base: f64, exponent: f64, expected: f64) {
         let res = pow(base, exponent);
         assert!(
-            if expected.is_nan() { res.is_nan() } else { pow(base, exponent) == expected },
+            if expected.is_nan() {
+                res.is_nan()
+            } else {
+                pow(base, exponent) == expected
+            },
             "{} ** {} was {} instead of {}",
             base,
             exponent,
@@ -450,11 +461,13 @@
     }
 
     fn test_sets_as_base(sets: &[&[f64]], exponent: f64, expected: f64) {
-        sets.iter().for_each(|s| s.iter().for_each(|val| pow_test(*val, exponent, expected)));
+        sets.iter()
+            .for_each(|s| s.iter().for_each(|val| pow_test(*val, exponent, expected)));
     }
 
     fn test_sets_as_exponent(base: f64, sets: &[&[f64]], expected: f64) {
-        sets.iter().for_each(|s| s.iter().for_each(|val| pow_test(base, *val, expected)));
+        sets.iter()
+            .for_each(|s| s.iter().for_each(|val| pow_test(base, *val, expected)));
     }
 
     fn test_sets(sets: &[&[f64]], computed: &dyn Fn(f64) -> f64, expected: &dyn Fn(f64) -> f64) {
@@ -468,7 +481,11 @@
                 #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
                 let res = force_eval!(res);
                 assert!(
-                    if exp.is_nan() { res.is_nan() } else { exp == res },
+                    if exp.is_nan() {
+                        res.is_nan()
+                    } else {
+                        exp == res
+                    },
                     "test for {} was {} instead of {}",
                     val,
                     res,
@@ -492,83 +509,85 @@
     #[test]
     fn nan_inputs() {
         // NAN as the base:
-        // (NAN ^ anything *but 0* should be NAN)
-        test_sets_as_exponent(NAN, &ALL[2..], NAN);
+        // (f64::NAN ^ anything *but 0* should be f64::NAN)
+        test_sets_as_exponent(f64::NAN, &ALL[2..], f64::NAN);
 
-        // NAN as the exponent:
-        // (anything *but 1* ^ NAN should be NAN)
-        test_sets_as_base(&ALL[..(ALL.len() - 2)], NAN, NAN);
+        // f64::NAN as the exponent:
+        // (anything *but 1* ^ f64::NAN should be f64::NAN)
+        test_sets_as_base(&ALL[..(ALL.len() - 2)], f64::NAN, f64::NAN);
     }
 
     #[test]
     fn infinity_as_base() {
         // Positive Infinity as the base:
-        // (+Infinity ^ positive anything but 0 and NAN should be +Infinity)
-        test_sets_as_exponent(INFINITY, &POS[1..], INFINITY);
+        // (+Infinity ^ positive anything but 0 and f64::NAN should be +Infinity)
+        test_sets_as_exponent(f64::INFINITY, &POS[1..], f64::INFINITY);
 
-        // (+Infinity ^ negative anything except 0 and NAN should be 0.0)
-        test_sets_as_exponent(INFINITY, &NEG[1..], 0.0);
+        // (+Infinity ^ negative anything except 0 and f64::NAN should be 0.0)
+        test_sets_as_exponent(f64::INFINITY, &NEG[1..], 0.0);
 
         // Negative Infinity as the base:
         // (-Infinity ^ positive odd ints should be -Infinity)
-        test_sets_as_exponent(NEG_INFINITY, &[POS_ODDS], NEG_INFINITY);
+        test_sets_as_exponent(f64::NEG_INFINITY, &[POS_ODDS], f64::NEG_INFINITY);
 
         // (-Infinity ^ anything but odd ints should be == -0 ^ (-anything))
         // We can lump in pos/neg odd ints here because they don't seem to
         // cause panics (div by zero) in release mode (I think).
-        test_sets(ALL, &|v: f64| pow(NEG_INFINITY, v), &|v: f64| pow(-0.0, -v));
+        test_sets(ALL, &|v: f64| pow(f64::NEG_INFINITY, v), &|v: f64| {
+            pow(-0.0, -v)
+        });
     }
 
     #[test]
     fn infinity_as_exponent() {
         // Positive/Negative base greater than 1:
-        // (pos/neg > 1 ^ Infinity should be Infinity - note this excludes NAN as the base)
-        test_sets_as_base(&ALL[5..(ALL.len() - 2)], INFINITY, INFINITY);
+        // (pos/neg > 1 ^ Infinity should be Infinity - note this excludes f64::NAN as the base)
+        test_sets_as_base(&ALL[5..(ALL.len() - 2)], f64::INFINITY, f64::INFINITY);
 
         // (pos/neg > 1 ^ -Infinity should be 0.0)
-        test_sets_as_base(&ALL[5..ALL.len() - 2], NEG_INFINITY, 0.0);
+        test_sets_as_base(&ALL[5..ALL.len() - 2], f64::NEG_INFINITY, 0.0);
 
         // Positive/Negative base less than 1:
         let base_below_one = &[POS_ZERO, NEG_ZERO, NEG_SMALL_FLOATS, POS_SMALL_FLOATS];
 
-        // (pos/neg < 1 ^ Infinity should be 0.0 - this also excludes NAN as the base)
-        test_sets_as_base(base_below_one, INFINITY, 0.0);
+        // (pos/neg < 1 ^ Infinity should be 0.0 - this also excludes f64::NAN as the base)
+        test_sets_as_base(base_below_one, f64::INFINITY, 0.0);
 
         // (pos/neg < 1 ^ -Infinity should be Infinity)
-        test_sets_as_base(base_below_one, NEG_INFINITY, INFINITY);
+        test_sets_as_base(base_below_one, f64::NEG_INFINITY, f64::INFINITY);
 
         // Positive/Negative 1 as the base:
         // (pos/neg 1 ^ Infinity should be 1)
-        test_sets_as_base(&[NEG_ONE, POS_ONE], INFINITY, 1.0);
+        test_sets_as_base(&[NEG_ONE, POS_ONE], f64::INFINITY, 1.0);
 
         // (pos/neg 1 ^ -Infinity should be 1)
-        test_sets_as_base(&[NEG_ONE, POS_ONE], NEG_INFINITY, 1.0);
+        test_sets_as_base(&[NEG_ONE, POS_ONE], f64::NEG_INFINITY, 1.0);
     }
 
     #[test]
     fn zero_as_base() {
         // Positive Zero as the base:
-        // (+0 ^ anything positive but 0 and NAN should be +0)
+        // (+0 ^ anything positive but 0 and f64::NAN should be +0)
         test_sets_as_exponent(0.0, &POS[1..], 0.0);
 
-        // (+0 ^ anything negative but 0 and NAN should be Infinity)
+        // (+0 ^ anything negative but 0 and f64::NAN should be Infinity)
         // (this should panic because we're dividing by zero)
-        test_sets_as_exponent(0.0, &NEG[1..], INFINITY);
+        test_sets_as_exponent(0.0, &NEG[1..], f64::INFINITY);
 
         // Negative Zero as the base:
-        // (-0 ^ anything positive but 0, NAN, and odd ints should be +0)
+        // (-0 ^ anything positive but 0, f64::NAN, and odd ints should be +0)
         test_sets_as_exponent(-0.0, &POS[3..], 0.0);
 
-        // (-0 ^ anything negative but 0, NAN, and odd ints should be Infinity)
+        // (-0 ^ anything negative but 0, f64::NAN, and odd ints should be Infinity)
         // (should panic because of divide by zero)
-        test_sets_as_exponent(-0.0, &NEG[3..], INFINITY);
+        test_sets_as_exponent(-0.0, &NEG[3..], f64::INFINITY);
 
         // (-0 ^ positive odd ints should be -0)
         test_sets_as_exponent(-0.0, &[POS_ODDS], -0.0);
 
         // (-0 ^ negative odd ints should be -Infinity)
         // (should panic because of divide by zero)
-        test_sets_as_exponent(-0.0, &[NEG_ODDS], NEG_INFINITY);
+        test_sets_as_exponent(-0.0, &[NEG_ODDS], f64::NEG_INFINITY);
     }
 
     #[test]
@@ -583,21 +602,21 @@
 
         // Factoring -1 out:
         // (negative anything ^ integer should be (-1 ^ integer) * (positive anything ^ integer))
-        (&[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS]).iter().for_each(
-            |int_set| {
+        [POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS]
+            .iter()
+            .for_each(|int_set| {
                 int_set.iter().for_each(|int| {
                     test_sets(ALL, &|v: f64| pow(-v, *int), &|v: f64| {
                         pow(-1.0, *int) * pow(v, *int)
                     });
                 })
-            },
-        );
+            });
 
         // Negative base (imaginary results):
         // (-anything except 0 and Infinity ^ non-integer should be NAN)
-        (&NEG[1..(NEG.len() - 1)]).iter().for_each(|set| {
+        NEG[1..(NEG.len() - 1)].iter().for_each(|set| {
             set.iter().for_each(|val| {
-                test_sets(&ALL[3..7], &|v: f64| pow(*val, v), &|_| NAN);
+                test_sets(&ALL[3..7], &|v: f64| pow(*val, v), &|_| f64::NAN);
             })
         });
     }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/powf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/powf.rs
index 2d9d1e4..11c7a7c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/powf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/powf.rs
@@ -13,6 +13,8 @@
  * ====================================================
  */
 
+use core::cmp::Ordering;
+
 use super::{fabsf, scalbnf, sqrtf};
 
 const BP: [f32; 2] = [1.0, 1.5];
@@ -115,15 +117,13 @@
     /* special value of y */
     if iy == 0x7f800000 {
         /* y is +-inf */
-        if ix == 0x3f800000 {
+        match ix.cmp(&0x3f800000) {
             /* (-1)**+-inf is 1 */
-            return 1.0;
-        } else if ix > 0x3f800000 {
+            Ordering::Equal => return 1.0,
             /* (|x|>1)**+-inf = inf,0 */
-            return if hy >= 0 { y } else { 0.0 };
-        } else {
+            Ordering::Greater => return if hy >= 0 { y } else { 0.0 },
             /* (|x|<1)**+-inf = 0,inf */
-            return if hy >= 0 { 0.0 } else { -y };
+            Ordering::Less => return if hy >= 0 { 0.0 } else { -y },
         }
     }
     if iy == 0x3f800000 {
@@ -182,11 +182,19 @@
         /* if |y| > 2**27 */
         /* over/underflow if x is not close to one */
         if ix < 0x3f7ffff8 {
-            return if hy < 0 { sn * HUGE * HUGE } else { sn * TINY * TINY };
+            return if hy < 0 {
+                sn * HUGE * HUGE
+            } else {
+                sn * TINY * TINY
+            };
         }
 
         if ix > 0x3f800007 {
-            return if hy > 0 { sn * HUGE * HUGE } else { sn * TINY * TINY };
+            return if hy > 0 {
+                sn * HUGE * HUGE
+            } else {
+                sn * TINY * TINY
+            };
         }
 
         /* now |1-x| is TINY <= 2**-20, suffice to compute
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2.rs
index 4dfb8c6..d677fd9d 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2.rs
@@ -50,7 +50,7 @@
 
     fn medium(x: f64, ix: u32) -> (i32, f64, f64) {
         /* rint(x/(pi/2)), Assume round-to-nearest. */
-        let tmp = x as f64 * INV_PIO2 + TO_INT;
+        let tmp = x * INV_PIO2 + TO_INT;
         // force rounding of tmp to it's storage format on x87 to avoid
         // excess precision issues.
         #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
@@ -199,16 +199,28 @@
     fn test_near_pi() {
         let arg = 3.141592025756836;
         let arg = force_eval!(arg);
-        assert_eq!(rem_pio2(arg), (2, -6.278329573009626e-7, -2.1125998133974653e-23));
+        assert_eq!(
+            rem_pio2(arg),
+            (2, -6.278329573009626e-7, -2.1125998133974653e-23)
+        );
         let arg = 3.141592033207416;
         let arg = force_eval!(arg);
-        assert_eq!(rem_pio2(arg), (2, -6.20382377148128e-7, -2.1125998133974653e-23));
+        assert_eq!(
+            rem_pio2(arg),
+            (2, -6.20382377148128e-7, -2.1125998133974653e-23)
+        );
         let arg = 3.141592144966125;
         let arg = force_eval!(arg);
-        assert_eq!(rem_pio2(arg), (2, -5.086236681942706e-7, -2.1125998133974653e-23));
+        assert_eq!(
+            rem_pio2(arg),
+            (2, -5.086236681942706e-7, -2.1125998133974653e-23)
+        );
         let arg = 3.141592979431152;
         let arg = force_eval!(arg);
-        assert_eq!(rem_pio2(arg), (2, 3.2584135866119817e-7, -2.1125998133974653e-23));
+        assert_eq!(
+            rem_pio2(arg),
+            (2, 3.2584135866119817e-7, -2.1125998133974653e-23)
+        );
     }
 
     #[test]
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2_large.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2_large.rs
index 1dfbba3b..6d679bb 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2_large.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rem_pio2_large.rs
@@ -226,8 +226,9 @@
     let x1p24 = f64::from_bits(0x4170000000000000); // 0x1p24 === 2 ^ 24
     let x1p_24 = f64::from_bits(0x3e70000000000000); // 0x1p_24 === 2 ^ (-24)
 
-    #[cfg(all(target_pointer_width = "64", feature = "checked"))]
-    assert!(e0 <= 16360);
+    if cfg!(target_pointer_width = "64") {
+        debug_assert!(e0 <= 16360);
+    }
 
     let nx = x.len();
 
@@ -425,8 +426,6 @@
             for i in (0..=jz).rev() {
                 fw += i!(fq, i);
             }
-            // TODO: drop excess precision here once double_t is used
-            fw = fw as f64;
             i!(y, 0, =, if ih == 0 { fw } else { -fw });
             fw = i!(fq, 0) - fw;
             for i in 1..=jz {
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rint.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rint.rs
index 618b26e..e1c32c94 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rint.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rint.rs
@@ -1,50 +1,51 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn rint(x: f64) -> f64 {
-    let one_over_e = 1.0 / f64::EPSILON;
-    let as_u64: u64 = x.to_bits();
-    let exponent: u64 = as_u64 >> 52 & 0x7ff;
-    let is_positive = (as_u64 >> 63) == 0;
-    if exponent >= 0x3ff + 52 {
-        x
-    } else {
-        let ans = if is_positive {
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let x = force_eval!(x);
-            let xplusoneovere = x + one_over_e;
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let xplusoneovere = force_eval!(xplusoneovere);
-            xplusoneovere - one_over_e
-        } else {
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let x = force_eval!(x);
-            let xminusoneovere = x - one_over_e;
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let xminusoneovere = force_eval!(xminusoneovere);
-            xminusoneovere + one_over_e
-        };
+use super::support::Round;
 
-        if ans == 0.0 { if is_positive { 0.0 } else { -0.0 } } else { ans }
+/// Round `x` to the nearest integer, breaking ties toward even.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn rintf16(x: f16) -> f16 {
+    select_implementation! {
+        name: rintf16,
+        use_arch: all(target_arch = "aarch64", target_feature = "fp16"),
+        args: x,
     }
+
+    super::generic::rint_round(x, Round::Nearest).val
 }
 
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use super::rint;
-
-    #[test]
-    fn negative_zero() {
-        assert_eq!(rint(-0.0_f64).to_bits(), (-0.0_f64).to_bits());
+/// Round `x` to the nearest integer, breaking ties toward even.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn rintf(x: f32) -> f32 {
+    select_implementation! {
+        name: rintf,
+        use_arch: any(
+            all(target_arch = "aarch64", target_feature = "neon"),
+            all(target_arch = "wasm32", intrinsics_enabled),
+        ),
+        args: x,
     }
 
-    #[test]
-    fn sanity_check() {
-        assert_eq!(rint(-1.0), -1.0);
-        assert_eq!(rint(2.8), 3.0);
-        assert_eq!(rint(-0.5), -0.0);
-        assert_eq!(rint(0.5), 0.0);
-        assert_eq!(rint(-1.5), -2.0);
-        assert_eq!(rint(1.5), 2.0);
+    super::generic::rint_round(x, Round::Nearest).val
+}
+
+/// Round `x` to the nearest integer, breaking ties toward even.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn rint(x: f64) -> f64 {
+    select_implementation! {
+        name: rint,
+        use_arch: any(
+            all(target_arch = "aarch64", target_feature = "neon"),
+            all(target_arch = "wasm32", intrinsics_enabled),
+        ),
+        args: x,
     }
+
+    super::generic::rint_round(x, Round::Nearest).val
+}
+
+/// Round `x` to the nearest integer, breaking ties toward even.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn rintf128(x: f128) -> f128 {
+    super::generic::rint_round(x, Round::Nearest).val
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rintf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rintf.rs
deleted file mode 100644
index 0726d83ba..0000000
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rintf.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn rintf(x: f32) -> f32 {
-    let one_over_e = 1.0 / f32::EPSILON;
-    let as_u32: u32 = x.to_bits();
-    let exponent: u32 = as_u32 >> 23 & 0xff;
-    let is_positive = (as_u32 >> 31) == 0;
-    if exponent >= 0x7f + 23 {
-        x
-    } else {
-        let ans = if is_positive {
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let x = force_eval!(x);
-            let xplusoneovere = x + one_over_e;
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let xplusoneovere = force_eval!(xplusoneovere);
-            xplusoneovere - one_over_e
-        } else {
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let x = force_eval!(x);
-            let xminusoneovere = x - one_over_e;
-            #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-            let xminusoneovere = force_eval!(xminusoneovere);
-            xminusoneovere + one_over_e
-        };
-
-        if ans == 0.0 { if is_positive { 0.0 } else { -0.0 } } else { ans }
-    }
-}
-
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use super::rintf;
-
-    #[test]
-    fn negative_zero() {
-        assert_eq!(rintf(-0.0_f32).to_bits(), (-0.0_f32).to_bits());
-    }
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(rintf(-1.0), -1.0);
-        assert_eq!(rintf(2.8), 3.0);
-        assert_eq!(rintf(-0.5), -0.0);
-        assert_eq!(rintf(0.5), 0.0);
-        assert_eq!(rintf(-1.5), -2.0);
-        assert_eq!(rintf(1.5), 2.0);
-    }
-}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/round.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/round.rs
index b81ebaa1..6cd091c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/round.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/round.rs
@@ -1,28 +1,25 @@
-use core::f64;
-
-use super::{copysign, trunc};
-
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg(f16_enabled)]
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn round(x: f64) -> f64 {
-    trunc(x + copysign(0.5 - 0.25 * f64::EPSILON, x))
+pub fn roundf16(x: f16) -> f16 {
+    super::generic::round(x)
 }
 
-#[cfg(test)]
-mod tests {
-    use super::round;
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundf(x: f32) -> f32 {
+    super::generic::round(x)
+}
 
-    #[test]
-    fn negative_zero() {
-        assert_eq!(round(-0.0_f64).to_bits(), (-0.0_f64).to_bits());
-    }
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn round(x: f64) -> f64 {
+    super::generic::round(x)
+}
 
-    #[test]
-    fn sanity_check() {
-        assert_eq!(round(-1.0), -1.0);
-        assert_eq!(round(2.8), 3.0);
-        assert_eq!(round(-0.5), -1.0);
-        assert_eq!(round(0.5), 1.0);
-        assert_eq!(round(-1.5), -2.0);
-        assert_eq!(round(1.5), 2.0);
-    }
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundf128(x: f128) -> f128 {
+    super::generic::round(x)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundeven.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundeven.rs
new file mode 100644
index 0000000..6e621d7
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundeven.rs
@@ -0,0 +1,36 @@
+use super::support::{Float, Round};
+
+/// Round `x` to the nearest integer, breaking ties toward even. This is IEEE 754
+/// `roundToIntegralTiesToEven`.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundevenf16(x: f16) -> f16 {
+    roundeven_impl(x)
+}
+
+/// Round `x` to the nearest integer, breaking ties toward even. This is IEEE 754
+/// `roundToIntegralTiesToEven`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundevenf(x: f32) -> f32 {
+    roundeven_impl(x)
+}
+
+/// Round `x` to the nearest integer, breaking ties toward even. This is IEEE 754
+/// `roundToIntegralTiesToEven`.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundeven(x: f64) -> f64 {
+    roundeven_impl(x)
+}
+
+/// Round `x` to the nearest integer, breaking ties toward even. This is IEEE 754
+/// `roundToIntegralTiesToEven`.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundevenf128(x: f128) -> f128 {
+    roundeven_impl(x)
+}
+
+#[inline]
+pub fn roundeven_impl<F: Float>(x: F) -> F {
+    super::generic::rint_round(x, Round::Nearest).val
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf.rs
index fb974bb..b5d7c9d6 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf.rs
@@ -1,30 +1,5 @@
-use core::f32;
-
-use super::{copysignf, truncf};
-
+/// Round `x` to the nearest integer, breaking ties away from zero.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn roundf(x: f32) -> f32 {
-    truncf(x + copysignf(0.5 - 0.25 * f32::EPSILON, x))
-}
-
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use super::roundf;
-
-    #[test]
-    fn negative_zero() {
-        assert_eq!(roundf(-0.0_f32).to_bits(), (-0.0_f32).to_bits());
-    }
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(roundf(-1.0), -1.0);
-        assert_eq!(roundf(2.8), 3.0);
-        assert_eq!(roundf(-0.5), -1.0);
-        assert_eq!(roundf(0.5), 1.0);
-        assert_eq!(roundf(-1.5), -2.0);
-        assert_eq!(roundf(1.5), 2.0);
-    }
+    super::generic::round(x)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf128.rs
new file mode 100644
index 0000000..fc31649
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf128.rs
@@ -0,0 +1,5 @@
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundf128(x: f128) -> f128 {
+    super::generic::round(x)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf16.rs
new file mode 100644
index 0000000..8b356ea
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf16.rs
@@ -0,0 +1,5 @@
+/// Round `x` to the nearest integer, breaking ties away from zero.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn roundf16(x: f16) -> f16 {
+    super::generic::round(x)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbn.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbn.rs
index 00c455a..ed73c3f9 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbn.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbn.rs
@@ -1,33 +1,87 @@
+#[cfg(f16_enabled)]
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn scalbn(x: f64, mut n: i32) -> f64 {
-    let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023
-    let x1p53 = f64::from_bits(0x4340000000000000); // 0x1p53 === 2 ^ 53
-    let x1p_1022 = f64::from_bits(0x0010000000000000); // 0x1p-1022 === 2 ^ (-1022)
+pub fn scalbnf16(x: f16, n: i32) -> f16 {
+    super::generic::scalbn(x, n)
+}
 
-    let mut y = x;
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn scalbnf(x: f32, n: i32) -> f32 {
+    super::generic::scalbn(x, n)
+}
 
-    if n > 1023 {
-        y *= x1p1023;
-        n -= 1023;
-        if n > 1023 {
-            y *= x1p1023;
-            n -= 1023;
-            if n > 1023 {
-                n = 1023;
-            }
-        }
-    } else if n < -1022 {
-        /* make sure final n < -53 to avoid double
-        rounding in the subnormal range */
-        y *= x1p_1022 * x1p53;
-        n += 1022 - 53;
-        if n < -1022 {
-            y *= x1p_1022 * x1p53;
-            n += 1022 - 53;
-            if n < -1022 {
-                n = -1022;
-            }
-        }
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn scalbn(x: f64, n: i32) -> f64 {
+    super::generic::scalbn(x, n)
+}
+
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn scalbnf128(x: f128, n: i32) -> f128 {
+    super::generic::scalbn(x, n)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::support::{CastFrom, CastInto, Float};
+
+    // Tests against N3220
+    fn spec_test<F: Float>(f: impl Fn(F, i32) -> F)
+    where
+        u32: CastInto<F::Int>,
+        F::Int: CastFrom<i32>,
+        F::Int: CastFrom<u32>,
+    {
+        // `scalbn(±0, n)` returns `±0`.
+        assert_biteq!(f(F::NEG_ZERO, 10), F::NEG_ZERO);
+        assert_biteq!(f(F::NEG_ZERO, 0), F::NEG_ZERO);
+        assert_biteq!(f(F::NEG_ZERO, -10), F::NEG_ZERO);
+        assert_biteq!(f(F::ZERO, 10), F::ZERO);
+        assert_biteq!(f(F::ZERO, 0), F::ZERO);
+        assert_biteq!(f(F::ZERO, -10), F::ZERO);
+
+        // `scalbn(x, 0)` returns `x`.
+        assert_biteq!(f(F::MIN, 0), F::MIN);
+        assert_biteq!(f(F::MAX, 0), F::MAX);
+        assert_biteq!(f(F::INFINITY, 0), F::INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY, 0), F::NEG_INFINITY);
+        assert_biteq!(f(F::ZERO, 0), F::ZERO);
+        assert_biteq!(f(F::NEG_ZERO, 0), F::NEG_ZERO);
+
+        // `scalbn(±∞, n)` returns `±∞`.
+        assert_biteq!(f(F::INFINITY, 10), F::INFINITY);
+        assert_biteq!(f(F::INFINITY, -10), F::INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY, 10), F::NEG_INFINITY);
+        assert_biteq!(f(F::NEG_INFINITY, -10), F::NEG_INFINITY);
+
+        // NaN should remain NaNs.
+        assert!(f(F::NAN, 10).is_nan());
+        assert!(f(F::NAN, 0).is_nan());
+        assert!(f(F::NAN, -10).is_nan());
+        assert!(f(-F::NAN, 10).is_nan());
+        assert!(f(-F::NAN, 0).is_nan());
+        assert!(f(-F::NAN, -10).is_nan());
     }
-    y * f64::from_bits(((0x3ff + n) as u64) << 52)
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn spec_test_f16() {
+        spec_test::<f16>(scalbnf16);
+    }
+
+    #[test]
+    fn spec_test_f32() {
+        spec_test::<f32>(scalbnf);
+    }
+
+    #[test]
+    fn spec_test_f64() {
+        spec_test::<f64>(scalbn);
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn spec_test_f128() {
+        spec_test::<f128>(scalbnf128);
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf.rs
index 73f4bb57..57e7ba7 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf.rs
@@ -1,29 +1,4 @@
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn scalbnf(mut x: f32, mut n: i32) -> f32 {
-    let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127
-    let x1p_126 = f32::from_bits(0x800000); // 0x1p-126f === 2 ^ -126
-    let x1p24 = f32::from_bits(0x4b800000); // 0x1p24f === 2 ^ 24
-
-    if n > 127 {
-        x *= x1p127;
-        n -= 127;
-        if n > 127 {
-            x *= x1p127;
-            n -= 127;
-            if n > 127 {
-                n = 127;
-            }
-        }
-    } else if n < -126 {
-        x *= x1p_126 * x1p24;
-        n += 126 - 24;
-        if n < -126 {
-            x *= x1p_126 * x1p24;
-            n += 126 - 24;
-            if n < -126 {
-                n = -126;
-            }
-        }
-    }
-    x * f32::from_bits(((0x7f + n) as u32) << 23)
+pub fn scalbnf(x: f32, n: i32) -> f32 {
+    super::generic::scalbn(x, n)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf128.rs
new file mode 100644
index 0000000..c1d2b48
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf128.rs
@@ -0,0 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn scalbnf128(x: f128, n: i32) -> f128 {
+    super::generic::scalbn(x, n)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf16.rs
new file mode 100644
index 0000000..2209e1a1
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf16.rs
@@ -0,0 +1,4 @@
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn scalbnf16(x: f16, n: i32) -> f16 {
+    super::generic::scalbn(x, n)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sin.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sin.rs
index e04e0d6a..229fa4be 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sin.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sin.rs
@@ -81,12 +81,15 @@
     }
 }
 
-#[test]
-fn test_near_pi() {
-    let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707
-    let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7
-    let result = sin(x);
-    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
-    let result = force_eval!(result);
-    assert_eq!(result, sx);
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    #[cfg_attr(x86_no_sse, ignore = "FIXME(i586): possible incorrect rounding")]
+    fn test_near_pi() {
+        let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707
+        let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7
+        assert_eq!(sin(x), sx);
+    }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincosf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincosf.rs
index 423845e4..f33607676 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincosf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincosf.rs
@@ -67,14 +67,12 @@
             }
         }
         /* -sin(x+c) is not correct if x+c could be 0: -0 vs +0 */
-        else {
-            if sign {
-                s = -k_sinf(x as f64 + S2PIO2);
-                c = -k_cosf(x as f64 + S2PIO2);
-            } else {
-                s = -k_sinf(x as f64 - S2PIO2);
-                c = -k_cosf(x as f64 - S2PIO2);
-            }
+        else if sign {
+            s = -k_sinf(x as f64 + S2PIO2);
+            c = -k_cosf(x as f64 + S2PIO2);
+        } else {
+            s = -k_sinf(x as f64 - S2PIO2);
+            c = -k_cosf(x as f64 - S2PIO2);
         }
 
         return (s, c);
@@ -91,14 +89,12 @@
                 s = -k_cosf(x as f64 - S3PIO2);
                 c = k_sinf(x as f64 - S3PIO2);
             }
+        } else if sign {
+            s = k_sinf(x as f64 + S4PIO2);
+            c = k_cosf(x as f64 + S4PIO2);
         } else {
-            if sign {
-                s = k_sinf(x as f64 + S4PIO2);
-                c = k_cosf(x as f64 + S4PIO2);
-            } else {
-                s = k_sinf(x as f64 - S4PIO2);
-                c = k_cosf(x as f64 - S4PIO2);
-            }
+            s = k_sinf(x as f64 - S4PIO2);
+            c = k_cosf(x as f64 - S4PIO2);
         }
 
         return (s, c);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sinf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sinf.rs
index b8fae2c9..709b63fc 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sinf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sinf.rs
@@ -42,7 +42,11 @@
         if ix < 0x39800000 {
             /* |x| < 2**-12 */
             /* raise inexact if x!=0 and underflow if subnormal */
-            force_eval!(if ix < 0x00800000 { x / x1p120 } else { x + x1p120 });
+            force_eval!(if ix < 0x00800000 {
+                x / x1p120
+            } else {
+                x + x1p120
+            });
             return x;
         }
         return k_sinf(x64);
@@ -57,7 +61,11 @@
                 return k_cosf(x64 - S1_PIO2);
             }
         }
-        return k_sinf(if sign { -(x64 + S2_PIO2) } else { -(x64 - S2_PIO2) });
+        return k_sinf(if sign {
+            -(x64 + S2_PIO2)
+        } else {
+            -(x64 - S2_PIO2)
+        });
     }
     if ix <= 0x40e231d5 {
         /* |x| ~<= 9*pi/4 */
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrt.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrt.rs
index e290738..76bc240c 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrt.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrt.rs
@@ -1,282 +1,51 @@
-/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunSoft, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-/* sqrt(x)
- * Return correctly rounded sqrt.
- *           ------------------------------------------
- *           |  Use the hardware sqrt if you have one |
- *           ------------------------------------------
- * Method:
- *   Bit by bit method using integer arithmetic. (Slow, but portable)
- *   1. Normalization
- *      Scale x to y in [1,4) with even powers of 2:
- *      find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
- *              sqrt(x) = 2^k * sqrt(y)
- *   2. Bit by bit computation
- *      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
- *           i                                                   0
- *                                     i+1         2
- *          s  = 2*q , and      y  =  2   * ( y - q  ).         (1)
- *           i      i            i                 i
- *
- *      To compute q    from q , one checks whether
- *                  i+1       i
- *
- *                            -(i+1) 2
- *                      (q + 2      ) <= y.                     (2)
- *                        i
- *                                                            -(i+1)
- *      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
- *                             i+1   i             i+1   i
- *
- *      With some algebraic manipulation, it is not difficult to see
- *      that (2) is equivalent to
- *                             -(i+1)
- *                      s  +  2       <= y                      (3)
- *                       i                i
- *
- *      The advantage of (3) is that s  and y  can be computed by
- *                                    i      i
- *      the following recurrence formula:
- *          if (3) is false
- *
- *          s     =  s  ,       y    = y   ;                    (4)
- *           i+1      i          i+1    i
- *
- *          otherwise,
- *                         -i                     -(i+1)
- *          s     =  s  + 2  ,  y    = y  -  s  - 2             (5)
- *           i+1      i          i+1    i     i
- *
- *      One may easily use induction to prove (4) and (5).
- *      Note. Since the left hand side of (3) contain only i+2 bits,
- *            it does not necessary to do a full (53-bit) comparison
- *            in (3).
- *   3. Final rounding
- *      After generating the 53 bits result, we compute one more bit.
- *      Together with the remainder, we can decide whether the
- *      result is exact, bigger than 1/2ulp, or less than 1/2ulp
- *      (it will never equal to 1/2ulp).
- *      The rounding mode can be detected by checking whether
- *      huge + tiny is equal to huge, and whether huge - tiny is
- *      equal to huge for some floating point number "huge" and "tiny".
- *
- * Special cases:
- *      sqrt(+-0) = +-0         ... exact
- *      sqrt(inf) = inf
- *      sqrt(-ve) = NaN         ... with invalid signal
- *      sqrt(NaN) = NaN         ... with invalid signal for signaling NaN
- */
+/// The square root of `x` (f16).
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn sqrtf16(x: f16) -> f16 {
+    select_implementation! {
+        name: sqrtf16,
+        use_arch: all(target_arch = "aarch64", target_feature = "fp16"),
+        args: x,
+    }
 
-use core::f64;
+    return super::generic::sqrt(x);
+}
+
+/// The square root of `x` (f32).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn sqrtf(x: f32) -> f32 {
+    select_implementation! {
+        name: sqrtf,
+        use_arch: any(
+            all(target_arch = "aarch64", target_feature = "neon"),
+            all(target_arch = "wasm32", intrinsics_enabled),
+            target_feature = "sse2"
+        ),
+        args: x,
+    }
+
+    super::generic::sqrt(x)
+}
 
 /// The square root of `x` (f64).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn sqrt(x: f64) -> f64 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f64.sqrt` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return if x < 0.0 {
-                f64::NAN
-            } else {
-                unsafe { ::core::intrinsics::sqrtf64(x) }
-            }
-        }
+    select_implementation! {
+        name: sqrt,
+        use_arch: any(
+            all(target_arch = "aarch64", target_feature = "neon"),
+            all(target_arch = "wasm32", intrinsics_enabled),
+            target_feature = "sse2"
+        ),
+        args: x,
     }
-    #[cfg(all(target_feature = "sse2", not(feature = "force-soft-floats")))]
-    {
-        // Note: This path is unlikely since LLVM will usually have already
-        // optimized sqrt calls into hardware instructions if sse2 is available,
-        // but if someone does end up here they'll appreciate the speed increase.
-        #[cfg(target_arch = "x86")]
-        use core::arch::x86::*;
-        #[cfg(target_arch = "x86_64")]
-        use core::arch::x86_64::*;
-        unsafe {
-            let m = _mm_set_sd(x);
-            let m_sqrt = _mm_sqrt_pd(m);
-            _mm_cvtsd_f64(m_sqrt)
-        }
-    }
-    #[cfg(any(not(target_feature = "sse2"), feature = "force-soft-floats"))]
-    {
-        use core::num::Wrapping;
 
-        const TINY: f64 = 1.0e-300;
-
-        let mut z: f64;
-        let sign: Wrapping<u32> = Wrapping(0x80000000);
-        let mut ix0: i32;
-        let mut s0: i32;
-        let mut q: i32;
-        let mut m: i32;
-        let mut t: i32;
-        let mut i: i32;
-        let mut r: Wrapping<u32>;
-        let mut t1: Wrapping<u32>;
-        let mut s1: Wrapping<u32>;
-        let mut ix1: Wrapping<u32>;
-        let mut q1: Wrapping<u32>;
-
-        ix0 = (x.to_bits() >> 32) as i32;
-        ix1 = Wrapping(x.to_bits() as u32);
-
-        /* take care of Inf and NaN */
-        if (ix0 & 0x7ff00000) == 0x7ff00000 {
-            return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
-        }
-        /* take care of zero */
-        if ix0 <= 0 {
-            if ((ix0 & !(sign.0 as i32)) | ix1.0 as i32) == 0 {
-                return x; /* sqrt(+-0) = +-0 */
-            }
-            if ix0 < 0 {
-                return (x - x) / (x - x); /* sqrt(-ve) = sNaN */
-            }
-        }
-        /* normalize x */
-        m = ix0 >> 20;
-        if m == 0 {
-            /* subnormal x */
-            while ix0 == 0 {
-                m -= 21;
-                ix0 |= (ix1 >> 11).0 as i32;
-                ix1 <<= 21;
-            }
-            i = 0;
-            while (ix0 & 0x00100000) == 0 {
-                i += 1;
-                ix0 <<= 1;
-            }
-            m -= i - 1;
-            ix0 |= (ix1 >> (32 - i) as usize).0 as i32;
-            ix1 = ix1 << i as usize;
-        }
-        m -= 1023; /* unbias exponent */
-        ix0 = (ix0 & 0x000fffff) | 0x00100000;
-        if (m & 1) == 1 {
-            /* odd m, double x to make it even */
-            ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32;
-            ix1 += ix1;
-        }
-        m >>= 1; /* m = [m/2] */
-
-        /* generate sqrt(x) bit by bit */
-        ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32;
-        ix1 += ix1;
-        q = 0; /* [q,q1] = sqrt(x) */
-        q1 = Wrapping(0);
-        s0 = 0;
-        s1 = Wrapping(0);
-        r = Wrapping(0x00200000); /* r = moving bit from right to left */
-
-        while r != Wrapping(0) {
-            t = s0 + r.0 as i32;
-            if t <= ix0 {
-                s0 = t + r.0 as i32;
-                ix0 -= t;
-                q += r.0 as i32;
-            }
-            ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32;
-            ix1 += ix1;
-            r >>= 1;
-        }
-
-        r = sign;
-        while r != Wrapping(0) {
-            t1 = s1 + r;
-            t = s0;
-            if t < ix0 || (t == ix0 && t1 <= ix1) {
-                s1 = t1 + r;
-                if (t1 & sign) == sign && (s1 & sign) == Wrapping(0) {
-                    s0 += 1;
-                }
-                ix0 -= t;
-                if ix1 < t1 {
-                    ix0 -= 1;
-                }
-                ix1 -= t1;
-                q1 += r;
-            }
-            ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32;
-            ix1 += ix1;
-            r >>= 1;
-        }
-
-        /* use floating add to find out rounding direction */
-        if (ix0 as u32 | ix1.0) != 0 {
-            z = 1.0 - TINY; /* raise inexact flag */
-            if z >= 1.0 {
-                z = 1.0 + TINY;
-                if q1.0 == 0xffffffff {
-                    q1 = Wrapping(0);
-                    q += 1;
-                } else if z > 1.0 {
-                    if q1.0 == 0xfffffffe {
-                        q += 1;
-                    }
-                    q1 += Wrapping(2);
-                } else {
-                    q1 += q1 & Wrapping(1);
-                }
-            }
-        }
-        ix0 = (q >> 1) + 0x3fe00000;
-        ix1 = q1 >> 1;
-        if (q & 1) == 1 {
-            ix1 |= sign;
-        }
-        ix0 += m << 20;
-        f64::from_bits((ix0 as u64) << 32 | ix1.0 as u64)
-    }
+    super::generic::sqrt(x)
 }
 
-#[cfg(test)]
-mod tests {
-    use core::f64::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(sqrt(100.0), 10.0);
-        assert_eq!(sqrt(4.0), 2.0);
-    }
-
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: FE_INVALID exception is raised if argument is negative.
-        assert!(sqrt(-1.0).is_nan());
-        assert!(sqrt(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY].iter().copied() {
-            assert_eq!(sqrt(f), f);
-        }
-    }
-
-    #[test]
-    fn conformance_tests() {
-        let values = [3.14159265359, 10000.0, f64::from_bits(0x0000000f), INFINITY];
-        let results = [
-            4610661241675116657u64,
-            4636737291354636288u64,
-            2197470602079456986u64,
-            9218868437227405312u64,
-        ];
-
-        for i in 0..values.len() {
-            let bits = f64::to_bits(sqrt(values[i]));
-            assert_eq!(results[i], bits);
-        }
-    }
+/// The square root of `x` (f128).
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn sqrtf128(x: f128) -> f128 {
+    return super::generic::sqrt(x);
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf.rs
index a738fc0b..c28a705e 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf.rs
@@ -1,167 +1,15 @@
-/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */
-/*
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
 /// The square root of `x` (f32).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn sqrtf(x: f32) -> f32 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f32.sqrt` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return if x < 0.0 {
-                ::core::f32::NAN
-            } else {
-                unsafe { ::core::intrinsics::sqrtf32(x) }
-            }
-        }
-    }
-    #[cfg(all(target_feature = "sse", not(feature = "force-soft-floats")))]
-    {
-        // Note: This path is unlikely since LLVM will usually have already
-        // optimized sqrt calls into hardware instructions if sse is available,
-        // but if someone does end up here they'll appreciate the speed increase.
-        #[cfg(target_arch = "x86")]
-        use core::arch::x86::*;
-        #[cfg(target_arch = "x86_64")]
-        use core::arch::x86_64::*;
-        unsafe {
-            let m = _mm_set_ss(x);
-            let m_sqrt = _mm_sqrt_ss(m);
-            _mm_cvtss_f32(m_sqrt)
-        }
-    }
-    #[cfg(any(not(target_feature = "sse"), feature = "force-soft-floats"))]
-    {
-        const TINY: f32 = 1.0e-30;
-
-        let mut z: f32;
-        let sign: i32 = 0x80000000u32 as i32;
-        let mut ix: i32;
-        let mut s: i32;
-        let mut q: i32;
-        let mut m: i32;
-        let mut t: i32;
-        let mut i: i32;
-        let mut r: u32;
-
-        ix = x.to_bits() as i32;
-
-        /* take care of Inf and NaN */
-        if (ix as u32 & 0x7f800000) == 0x7f800000 {
-            return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
-        }
-
-        /* take care of zero */
-        if ix <= 0 {
-            if (ix & !sign) == 0 {
-                return x; /* sqrt(+-0) = +-0 */
-            }
-            if ix < 0 {
-                return (x - x) / (x - x); /* sqrt(-ve) = sNaN */
-            }
-        }
-
-        /* normalize x */
-        m = ix >> 23;
-        if m == 0 {
-            /* subnormal x */
-            i = 0;
-            while ix & 0x00800000 == 0 {
-                ix <<= 1;
-                i = i + 1;
-            }
-            m -= i - 1;
-        }
-        m -= 127; /* unbias exponent */
-        ix = (ix & 0x007fffff) | 0x00800000;
-        if m & 1 == 1 {
-            /* odd m, double x to make it even */
-            ix += ix;
-        }
-        m >>= 1; /* m = [m/2] */
-
-        /* generate sqrt(x) bit by bit */
-        ix += ix;
-        q = 0;
-        s = 0;
-        r = 0x01000000; /* r = moving bit from right to left */
-
-        while r != 0 {
-            t = s + r as i32;
-            if t <= ix {
-                s = t + r as i32;
-                ix -= t;
-                q += r as i32;
-            }
-            ix += ix;
-            r >>= 1;
-        }
-
-        /* use floating add to find out rounding direction */
-        if ix != 0 {
-            z = 1.0 - TINY; /* raise inexact flag */
-            if z >= 1.0 {
-                z = 1.0 + TINY;
-                if z > 1.0 {
-                    q += 2;
-                } else {
-                    q += q & 1;
-                }
-            }
-        }
-
-        ix = (q >> 1) + 0x3f000000;
-        ix += m << 23;
-        f32::from_bits(ix as u32)
-    }
-}
-
-// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
-#[cfg(not(target_arch = "powerpc64"))]
-#[cfg(test)]
-mod tests {
-    use core::f32::*;
-
-    use super::*;
-
-    #[test]
-    fn sanity_check() {
-        assert_eq!(sqrtf(100.0), 10.0);
-        assert_eq!(sqrtf(4.0), 2.0);
+    select_implementation! {
+        name: sqrtf,
+        use_arch: any(
+            all(target_arch = "aarch64", target_feature = "neon"),
+            all(target_arch = "wasm32", intrinsics_enabled),
+            target_feature = "sse2"
+        ),
+        args: x,
     }
 
-    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt
-    #[test]
-    fn spec_tests() {
-        // Not Asserted: FE_INVALID exception is raised if argument is negative.
-        assert!(sqrtf(-1.0).is_nan());
-        assert!(sqrtf(NAN).is_nan());
-        for f in [0.0, -0.0, INFINITY].iter().copied() {
-            assert_eq!(sqrtf(f), f);
-        }
-    }
-
-    #[test]
-    fn conformance_tests() {
-        let values = [3.14159265359f32, 10000.0f32, f32::from_bits(0x0000000f), INFINITY];
-        let results = [1071833029u32, 1120403456u32, 456082799u32, 2139095040u32];
-
-        for i in 0..values.len() {
-            let bits = f32::to_bits(sqrtf(values[i]));
-            assert_eq!(results[i], bits);
-        }
-    }
+    super::generic::sqrt(x)
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf128.rs
new file mode 100644
index 0000000..eaef6ae
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf128.rs
@@ -0,0 +1,5 @@
+/// The square root of `x` (f128).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn sqrtf128(x: f128) -> f128 {
+    return super::generic::sqrt(x);
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf16.rs
new file mode 100644
index 0000000..7bedb7f8
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf16.rs
@@ -0,0 +1,11 @@
+/// The square root of `x` (f16).
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn sqrtf16(x: f16) -> f16 {
+    select_implementation! {
+        name: sqrtf16,
+        use_arch: all(target_arch = "aarch64", target_feature = "fp16"),
+        args: x,
+    }
+
+    return super::generic::sqrt(x);
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big.rs
new file mode 100644
index 0000000..f24c063
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big.rs
@@ -0,0 +1,257 @@
+//! Integers used for wide operations, larger than `u128`.
+
+#[cfg(test)]
+mod tests;
+
+use core::ops;
+
+use super::{DInt, HInt, Int, MinInt};
+
+const U128_LO_MASK: u128 = u64::MAX as u128;
+
+/// A 256-bit unsigned integer represented as two 128-bit native-endian limbs.
+#[allow(non_camel_case_types)]
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
+pub struct u256 {
+    pub lo: u128,
+    pub hi: u128,
+}
+
+impl u256 {
+    #[cfg(any(test, feature = "unstable-public-internals"))]
+    pub const MAX: Self = Self {
+        lo: u128::MAX,
+        hi: u128::MAX,
+    };
+
+    /// Reinterpret as a signed integer
+    pub fn signed(self) -> i256 {
+        i256 {
+            lo: self.lo,
+            hi: self.hi,
+        }
+    }
+}
+
+/// A 256-bit signed integer represented as two 128-bit native-endian limbs.
+#[allow(non_camel_case_types)]
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
+pub struct i256 {
+    pub lo: u128,
+    pub hi: u128,
+}
+
+impl i256 {
+    /// Reinterpret as an unsigned integer
+    #[cfg(any(test, feature = "unstable-public-internals"))]
+    pub fn unsigned(self) -> u256 {
+        u256 {
+            lo: self.lo,
+            hi: self.hi,
+        }
+    }
+}
+
+impl MinInt for u256 {
+    type OtherSign = i256;
+
+    type Unsigned = u256;
+
+    const SIGNED: bool = false;
+    const BITS: u32 = 256;
+    const ZERO: Self = Self { lo: 0, hi: 0 };
+    const ONE: Self = Self { lo: 1, hi: 0 };
+    const MIN: Self = Self { lo: 0, hi: 0 };
+    const MAX: Self = Self {
+        lo: u128::MAX,
+        hi: u128::MAX,
+    };
+}
+
+impl MinInt for i256 {
+    type OtherSign = u256;
+
+    type Unsigned = u256;
+
+    const SIGNED: bool = false;
+    const BITS: u32 = 256;
+    const ZERO: Self = Self { lo: 0, hi: 0 };
+    const ONE: Self = Self { lo: 1, hi: 0 };
+    const MIN: Self = Self {
+        lo: 0,
+        hi: 1 << 127,
+    };
+    const MAX: Self = Self {
+        lo: u128::MAX,
+        hi: u128::MAX << 1,
+    };
+}
+
+macro_rules! impl_common {
+    ($ty:ty) => {
+        impl ops::BitOr for $ty {
+            type Output = Self;
+
+            fn bitor(mut self, rhs: Self) -> Self::Output {
+                self.lo |= rhs.lo;
+                self.hi |= rhs.hi;
+                self
+            }
+        }
+
+        impl ops::Not for $ty {
+            type Output = Self;
+
+            fn not(mut self) -> Self::Output {
+                self.lo = !self.lo;
+                self.hi = !self.hi;
+                self
+            }
+        }
+
+        impl ops::Shl<u32> for $ty {
+            type Output = Self;
+
+            fn shl(self, _rhs: u32) -> Self::Output {
+                unimplemented!("only used to meet trait bounds")
+            }
+        }
+    };
+}
+
+impl_common!(i256);
+impl_common!(u256);
+
+impl ops::Add<Self> for u256 {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        let (lo, carry) = self.lo.overflowing_add(rhs.lo);
+        let hi = self.hi.wrapping_add(carry as u128).wrapping_add(rhs.hi);
+
+        Self { lo, hi }
+    }
+}
+
+impl ops::Shr<u32> for u256 {
+    type Output = Self;
+
+    fn shr(mut self, rhs: u32) -> Self::Output {
+        debug_assert!(rhs < Self::BITS, "attempted to shift right with overflow");
+        if rhs >= Self::BITS {
+            return Self::ZERO;
+        }
+
+        if rhs == 0 {
+            return self;
+        }
+
+        if rhs < 128 {
+            self.lo >>= rhs;
+            self.lo |= self.hi << (128 - rhs);
+        } else {
+            self.lo = self.hi >> (rhs - 128);
+        }
+
+        if rhs < 128 {
+            self.hi >>= rhs;
+        } else {
+            self.hi = 0;
+        }
+
+        self
+    }
+}
+
+impl HInt for u128 {
+    type D = u256;
+
+    fn widen(self) -> Self::D {
+        u256 { lo: self, hi: 0 }
+    }
+
+    fn zero_widen(self) -> Self::D {
+        self.widen()
+    }
+
+    fn zero_widen_mul(self, rhs: Self) -> Self::D {
+        let l0 = self & U128_LO_MASK;
+        let l1 = rhs & U128_LO_MASK;
+        let h0 = self >> 64;
+        let h1 = rhs >> 64;
+
+        let p_ll: u128 = l0.overflowing_mul(l1).0;
+        let p_lh: u128 = l0.overflowing_mul(h1).0;
+        let p_hl: u128 = h0.overflowing_mul(l1).0;
+        let p_hh: u128 = h0.overflowing_mul(h1).0;
+
+        let s0 = p_hl + (p_ll >> 64);
+        let s1 = (p_ll & U128_LO_MASK) + (s0 << 64);
+        let s2 = p_lh + (s1 >> 64);
+
+        let lo = (p_ll & U128_LO_MASK) + (s2 << 64);
+        let hi = p_hh + (s0 >> 64) + (s2 >> 64);
+
+        u256 { lo, hi }
+    }
+
+    fn widen_mul(self, rhs: Self) -> Self::D {
+        self.zero_widen_mul(rhs)
+    }
+
+    fn widen_hi(self) -> Self::D {
+        self.widen() << <Self as MinInt>::BITS
+    }
+}
+
+impl HInt for i128 {
+    type D = i256;
+
+    fn widen(self) -> Self::D {
+        let mut ret = self.unsigned().zero_widen().signed();
+        if self.is_negative() {
+            ret.hi = u128::MAX;
+        }
+        ret
+    }
+
+    fn zero_widen(self) -> Self::D {
+        self.unsigned().zero_widen().signed()
+    }
+
+    fn zero_widen_mul(self, rhs: Self) -> Self::D {
+        self.unsigned().zero_widen_mul(rhs.unsigned()).signed()
+    }
+
+    fn widen_mul(self, _rhs: Self) -> Self::D {
+        unimplemented!("signed i128 widening multiply is not used")
+    }
+
+    fn widen_hi(self) -> Self::D {
+        self.widen() << <Self as MinInt>::BITS
+    }
+}
+
+impl DInt for u256 {
+    type H = u128;
+
+    fn lo(self) -> Self::H {
+        self.lo
+    }
+
+    fn hi(self) -> Self::H {
+        self.hi
+    }
+}
+
+impl DInt for i256 {
+    type H = i128;
+
+    fn lo(self) -> Self::H {
+        self.lo as i128
+    }
+
+    fn hi(self) -> Self::H {
+        self.hi as i128
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big/tests.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big/tests.rs
new file mode 100644
index 0000000..d2010f02
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big/tests.rs
@@ -0,0 +1,277 @@
+extern crate std;
+use std::string::String;
+use std::{eprintln, format};
+
+use super::{HInt, MinInt, i256, u256};
+
+const LOHI_SPLIT: u128 = 0xaaaaaaaaaaaaaaaaffffffffffffffff;
+
+/// Print a `u256` as hex since we can't add format implementations
+fn hexu(v: u256) -> String {
+    format!("0x{:032x}{:032x}", v.hi, v.lo)
+}
+
+#[test]
+fn widen_u128() {
+    assert_eq!(
+        u128::MAX.widen(),
+        u256 {
+            lo: u128::MAX,
+            hi: 0
+        }
+    );
+    assert_eq!(
+        LOHI_SPLIT.widen(),
+        u256 {
+            lo: LOHI_SPLIT,
+            hi: 0
+        }
+    );
+}
+
+#[test]
+fn widen_i128() {
+    assert_eq!((-1i128).widen(), u256::MAX.signed());
+    assert_eq!(
+        (LOHI_SPLIT as i128).widen(),
+        i256 {
+            lo: LOHI_SPLIT,
+            hi: u128::MAX
+        }
+    );
+    assert_eq!((-1i128).zero_widen().unsigned(), (u128::MAX).widen());
+}
+
+#[test]
+fn widen_mul_u128() {
+    let tests = [
+        (
+            u128::MAX / 2,
+            2_u128,
+            u256 {
+                lo: u128::MAX - 1,
+                hi: 0,
+            },
+        ),
+        (
+            u128::MAX,
+            2_u128,
+            u256 {
+                lo: u128::MAX - 1,
+                hi: 1,
+            },
+        ),
+        (
+            u128::MAX,
+            u128::MAX,
+            u256 {
+                lo: 1,
+                hi: u128::MAX - 1,
+            },
+        ),
+        (0, 0, u256::ZERO),
+        (1234u128, 0, u256::ZERO),
+        (0, 1234, u256::ZERO),
+    ];
+
+    let mut has_errors = false;
+    let mut add_error = |i, a, b, expected, actual| {
+        has_errors = true;
+        eprintln!(
+            "\
+            FAILURE ({i}): {a:#034x} * {b:#034x}\n\
+            expected: {}\n\
+            got:      {}\
+            ",
+            hexu(expected),
+            hexu(actual)
+        );
+    };
+
+    for (i, (a, b, exp)) in tests.iter().copied().enumerate() {
+        let res = a.widen_mul(b);
+        let res_z = a.zero_widen_mul(b);
+        assert_eq!(res, res_z);
+        if res != exp {
+            add_error(i, a, b, exp, res);
+        }
+    }
+
+    assert!(!has_errors);
+}
+
+#[test]
+fn not_u256() {
+    assert_eq!(!u256::ZERO, u256::MAX);
+}
+
+#[test]
+fn shr_u256() {
+    let only_low = [
+        1,
+        u16::MAX.into(),
+        u32::MAX.into(),
+        u64::MAX.into(),
+        u128::MAX,
+    ];
+    let mut has_errors = false;
+
+    let mut add_error = |a, b, expected, actual| {
+        has_errors = true;
+        eprintln!(
+            "\
+            FAILURE:  {} >> {b}\n\
+            expected: {}\n\
+            actual:   {}\
+            ",
+            hexu(a),
+            hexu(expected),
+            hexu(actual),
+        );
+    };
+
+    for a in only_low {
+        for perturb in 0..10 {
+            let a = a.saturating_add(perturb);
+            for shift in 0..128 {
+                let res = a.widen() >> shift;
+                let expected = (a >> shift).widen();
+                if res != expected {
+                    add_error(a.widen(), shift, expected, res);
+                }
+            }
+        }
+    }
+
+    let check = [
+        (
+            u256::MAX,
+            1,
+            u256 {
+                lo: u128::MAX,
+                hi: u128::MAX >> 1,
+            },
+        ),
+        (
+            u256::MAX,
+            5,
+            u256 {
+                lo: u128::MAX,
+                hi: u128::MAX >> 5,
+            },
+        ),
+        (
+            u256::MAX,
+            63,
+            u256 {
+                lo: u128::MAX,
+                hi: u64::MAX as u128 | (1 << 64),
+            },
+        ),
+        (
+            u256::MAX,
+            64,
+            u256 {
+                lo: u128::MAX,
+                hi: u64::MAX as u128,
+            },
+        ),
+        (
+            u256::MAX,
+            65,
+            u256 {
+                lo: u128::MAX,
+                hi: (u64::MAX >> 1) as u128,
+            },
+        ),
+        (
+            u256::MAX,
+            127,
+            u256 {
+                lo: u128::MAX,
+                hi: 1,
+            },
+        ),
+        (
+            u256::MAX,
+            128,
+            u256 {
+                lo: u128::MAX,
+                hi: 0,
+            },
+        ),
+        (
+            u256::MAX,
+            129,
+            u256 {
+                lo: u128::MAX >> 1,
+                hi: 0,
+            },
+        ),
+        (
+            u256::MAX,
+            191,
+            u256 {
+                lo: u64::MAX as u128 | 1 << 64,
+                hi: 0,
+            },
+        ),
+        (
+            u256::MAX,
+            192,
+            u256 {
+                lo: u64::MAX as u128,
+                hi: 0,
+            },
+        ),
+        (
+            u256::MAX,
+            193,
+            u256 {
+                lo: u64::MAX as u128 >> 1,
+                hi: 0,
+            },
+        ),
+        (u256::MAX, 254, u256 { lo: 0b11, hi: 0 }),
+        (u256::MAX, 255, u256 { lo: 1, hi: 0 }),
+        (
+            u256 {
+                hi: LOHI_SPLIT,
+                lo: 0,
+            },
+            64,
+            u256 {
+                lo: 0xffffffffffffffff0000000000000000,
+                hi: 0xaaaaaaaaaaaaaaaa,
+            },
+        ),
+    ];
+
+    for (input, shift, expected) in check {
+        let res = input >> shift;
+        if res != expected {
+            add_error(input, shift, expected, res);
+        }
+    }
+
+    assert!(!has_errors);
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+// FIXME(ppc): ppc64le seems to have issues with `should_panic` tests.
+#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
+fn shr_u256_overflow() {
+    // Like regular shr, panic on overflow with debug assertions
+    let _ = u256::MAX >> 256;
+}
+
+#[test]
+#[cfg(not(debug_assertions))]
+fn shr_u256_overflow() {
+    // No panic without debug assertions
+    assert_eq!(u256::MAX >> 256, u256::ZERO);
+    assert_eq!(u256::MAX >> 257, u256::ZERO);
+    assert_eq!(u256::MAX >> u32::MAX, u256::ZERO);
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/env.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/env.rs
new file mode 100644
index 0000000..53ae32f
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/env.rs
@@ -0,0 +1,130 @@
+//! Support for rounding directions and status flags as specified by IEEE 754.
+//!
+//! Rust does not support the floating point environment so rounding mode is passed as an argument
+//! and status flags are returned as part of the result. There is currently not much support for
+//! this; most existing ports from musl use a form of `force_eval!` to raise exceptions, but this
+//! has no side effects in Rust. Further, correct behavior relies on elementary operations making
+//! use of the correct rounding and raising relevant exceptions, which is not the case for Rust.
+//!
+//! This module exists so no functionality is lost when porting algorithms that respect floating
+//! point environment, and so that some functionality may be tested (that which does not rely on
+//! side effects from elementary operations). Full support would require wrappers around basic
+//! operations, but there is no plan to add this at the current time.
+
+/// A value combined with a floating point status.
+pub struct FpResult<T> {
+    pub val: T,
+    #[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+    pub status: Status,
+}
+
+impl<T> FpResult<T> {
+    pub fn new(val: T, status: Status) -> Self {
+        Self { val, status }
+    }
+
+    /// Return `val` with `Status::OK`.
+    pub fn ok(val: T) -> Self {
+        Self {
+            val,
+            status: Status::OK,
+        }
+    }
+}
+
+/// IEEE 754 rounding mode, excluding the optional `roundTiesToAway` version of nearest.
+///
+/// Integer representation comes from what CORE-MATH uses for indexing.
+#[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum Round {
+    /// IEEE 754 nearest, `roundTiesToEven`.
+    Nearest = 0,
+    /// IEEE 754 `roundTowardNegative`.
+    Negative = 1,
+    /// IEEE 754 `roundTowardPositive`.
+    Positive = 2,
+    /// IEEE 754 `roundTowardZero`.
+    Zero = 3,
+}
+
+/// IEEE 754 exception status flags.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct Status(u8);
+
+impl Status {
+    /// Default status indicating no errors.
+    pub const OK: Self = Self(0);
+
+    /// No definable result.
+    ///
+    /// Includes:
+    /// - Any ops on sNaN, with a few exceptions.
+    /// - `0 * inf`, `inf * 0`.
+    /// - `fma(0, inf, c)` or `fma(inf, 0, c)`, possibly excluding `c = qNaN`.
+    /// - `+inf + -inf` and similar (includes subtraction and fma).
+    /// - `0.0 / 0.0`, `inf / inf`
+    /// - `remainder(x, y)` if `y == 0.0` or `x == inf`, and neither is NaN.
+    /// - `sqrt(x)` with `x < 0.0`.
+    pub const INVALID: Self = Self(1);
+
+    /// Division by zero.
+    ///
+    /// The default result for division is +/-inf based on operand sign. For `logB`, the default
+    /// result is -inf.
+    /// `x / y` when `x != 0.0` and `y == 0.0`,
+    #[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+    pub const DIVIDE_BY_ZERO: Self = Self(1 << 2);
+
+    /// The result exceeds the maximum finite value.
+    ///
+    /// The default result depends on rounding mode. `Nearest*` rounds to +/- infinity, sign based
+    /// on the intermediate result. `Zero` rounds to the signed maximum finite. `Positive` and
+    /// `Negative` round to signed maximum finite in one direction, signed infinity in the other.
+    #[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+    pub const OVERFLOW: Self = Self(1 << 3);
+
+    /// The result is subnormal and lost precision.
+    pub const UNDERFLOW: Self = Self(1 << 4);
+
+    /// The finite-precision result does not match that of infinite precision, and the reason
+    /// is not represented by one of the other flags.
+    pub const INEXACT: Self = Self(1 << 5);
+
+    /// True if `UNDERFLOW` is set.
+    #[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+    pub const fn underflow(self) -> bool {
+        self.0 & Self::UNDERFLOW.0 != 0
+    }
+
+    /// True if `OVERFLOW` is set.
+    #[cfg_attr(not(feature = "unstable-public-internals"), allow(dead_code))]
+    pub const fn overflow(self) -> bool {
+        self.0 & Self::OVERFLOW.0 != 0
+    }
+
+    pub fn set_underflow(&mut self, val: bool) {
+        self.set_flag(val, Self::UNDERFLOW);
+    }
+
+    /// True if `INEXACT` is set.
+    pub const fn inexact(self) -> bool {
+        self.0 & Self::INEXACT.0 != 0
+    }
+
+    pub fn set_inexact(&mut self, val: bool) {
+        self.set_flag(val, Self::INEXACT);
+    }
+
+    fn set_flag(&mut self, val: bool, mask: Self) {
+        if val {
+            self.0 |= mask.0;
+        } else {
+            self.0 &= !mask.0;
+        }
+    }
+
+    pub(crate) const fn with(self, rhs: Self) -> Self {
+        Self(self.0 | rhs.0)
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/float_traits.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/float_traits.rs
new file mode 100644
index 0000000..8094a7b8
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/float_traits.rs
@@ -0,0 +1,545 @@
+use core::{fmt, mem, ops};
+
+use super::int_traits::{CastFrom, Int, MinInt};
+
+/// Trait for some basic operations on floats
+// #[allow(dead_code)]
+pub trait Float:
+    Copy
+    + fmt::Debug
+    + PartialEq
+    + PartialOrd
+    + ops::AddAssign
+    + ops::MulAssign
+    + ops::Add<Output = Self>
+    + ops::Sub<Output = Self>
+    + ops::Mul<Output = Self>
+    + ops::Div<Output = Self>
+    + ops::Rem<Output = Self>
+    + ops::Neg<Output = Self>
+    + 'static
+{
+    /// A uint of the same width as the float
+    type Int: Int<OtherSign = Self::SignedInt, Unsigned = Self::Int>;
+
+    /// A int of the same width as the float
+    type SignedInt: Int
+        + MinInt<OtherSign = Self::Int, Unsigned = Self::Int>
+        + ops::Neg<Output = Self::SignedInt>;
+
+    const ZERO: Self;
+    const NEG_ZERO: Self;
+    const ONE: Self;
+    const NEG_ONE: Self;
+    const INFINITY: Self;
+    const NEG_INFINITY: Self;
+    const NAN: Self;
+    const NEG_NAN: Self;
+    const MAX: Self;
+    const MIN: Self;
+    const EPSILON: Self;
+    const PI: Self;
+    const NEG_PI: Self;
+    const FRAC_PI_2: Self;
+
+    const MIN_POSITIVE_NORMAL: Self;
+
+    /// The bitwidth of the float type
+    const BITS: u32;
+
+    /// The bitwidth of the significand
+    const SIG_BITS: u32;
+
+    /// The bitwidth of the exponent
+    const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
+
+    /// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
+    /// representation.
+    ///
+    /// This shifted fully right, use `EXP_MASK` for the shifted value.
+    const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
+
+    /// The exponent bias value
+    const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
+
+    /// Maximum unbiased exponent value.
+    const EXP_MAX: i32 = Self::EXP_BIAS as i32;
+
+    /// Minimum *NORMAL* unbiased exponent value.
+    const EXP_MIN: i32 = -(Self::EXP_MAX - 1);
+
+    /// Minimum subnormal exponent value.
+    const EXP_MIN_SUBNORM: i32 = Self::EXP_MIN - Self::SIG_BITS as i32;
+
+    /// A mask for the sign bit
+    const SIGN_MASK: Self::Int;
+
+    /// A mask for the significand
+    const SIG_MASK: Self::Int;
+
+    /// A mask for the exponent
+    const EXP_MASK: Self::Int;
+
+    /// The implicit bit of the float format
+    const IMPLICIT_BIT: Self::Int;
+
+    /// Returns `self` transmuted to `Self::Int`
+    fn to_bits(self) -> Self::Int;
+
+    /// Returns `self` transmuted to `Self::SignedInt`
+    #[allow(dead_code)]
+    fn to_bits_signed(self) -> Self::SignedInt {
+        self.to_bits().signed()
+    }
+
+    /// Check bitwise equality.
+    #[allow(dead_code)]
+    fn biteq(self, rhs: Self) -> bool {
+        self.to_bits() == rhs.to_bits()
+    }
+
+    /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
+    /// represented in multiple different ways.
+    ///
+    /// This method returns `true` if two NaNs are compared. Use [`biteq`](Self::biteq) instead
+    /// if `NaN` should not be treated separately.
+    #[allow(dead_code)]
+    fn eq_repr(self, rhs: Self) -> bool {
+        if self.is_nan() && rhs.is_nan() {
+            true
+        } else {
+            self.biteq(rhs)
+        }
+    }
+
+    /// Returns true if the value is NaN.
+    fn is_nan(self) -> bool;
+
+    /// Returns true if the value is +inf or -inf.
+    fn is_infinite(self) -> bool;
+
+    /// Returns true if the sign is negative. Extracts the sign bit regardless of zero or NaN.
+    fn is_sign_negative(self) -> bool;
+
+    /// Returns true if the sign is positive. Extracts the sign bit regardless of zero or NaN.
+    fn is_sign_positive(self) -> bool {
+        !self.is_sign_negative()
+    }
+
+    /// Returns if `self` is subnormal.
+    #[allow(dead_code)]
+    fn is_subnormal(self) -> bool {
+        (self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
+    }
+
+    /// Returns the exponent, not adjusting for bias, not accounting for subnormals or zero.
+    fn ex(self) -> u32 {
+        u32::cast_from(self.to_bits() >> Self::SIG_BITS) & Self::EXP_SAT
+    }
+
+    /// Extract the exponent and adjust it for bias, not accounting for subnormals or zero.
+    fn exp_unbiased(self) -> i32 {
+        self.ex().signed() - (Self::EXP_BIAS as i32)
+    }
+
+    /// Returns the significand with no implicit bit (or the "fractional" part)
+    #[allow(dead_code)]
+    fn frac(self) -> Self::Int {
+        self.to_bits() & Self::SIG_MASK
+    }
+
+    /// Returns a `Self::Int` transmuted back to `Self`
+    fn from_bits(a: Self::Int) -> Self;
+
+    /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
+    fn from_parts(negative: bool, exponent: u32, significand: Self::Int) -> Self {
+        let sign = if negative {
+            Self::Int::ONE
+        } else {
+            Self::Int::ZERO
+        };
+        Self::from_bits(
+            (sign << (Self::BITS - 1))
+                | (Self::Int::cast_from(exponent & Self::EXP_SAT) << Self::SIG_BITS)
+                | (significand & Self::SIG_MASK),
+        )
+    }
+
+    #[allow(dead_code)]
+    fn abs(self) -> Self;
+
+    /// Returns a number composed of the magnitude of self and the sign of sign.
+    fn copysign(self, other: Self) -> Self;
+
+    /// Fused multiply add, rounding once.
+    fn fma(self, y: Self, z: Self) -> Self;
+
+    /// Returns (normalized exponent, normalized significand)
+    #[allow(dead_code)]
+    fn normalize(significand: Self::Int) -> (i32, Self::Int);
+
+    /// Returns a number that represents the sign of self.
+    #[allow(dead_code)]
+    fn signum(self) -> Self {
+        if self.is_nan() {
+            self
+        } else {
+            Self::ONE.copysign(self)
+        }
+    }
+}
+
+/// Access the associated `Int` type from a float (helper to avoid ambiguous associated types).
+pub type IntTy<F> = <F as Float>::Int;
+
+macro_rules! float_impl {
+    (
+        $ty:ident,
+        $ity:ident,
+        $sity:ident,
+        $bits:expr,
+        $significand_bits:expr,
+        $from_bits:path,
+        $to_bits:path,
+        $fma_fn:ident,
+        $fma_intrinsic:ident
+    ) => {
+        impl Float for $ty {
+            type Int = $ity;
+            type SignedInt = $sity;
+
+            const ZERO: Self = 0.0;
+            const NEG_ZERO: Self = -0.0;
+            const ONE: Self = 1.0;
+            const NEG_ONE: Self = -1.0;
+            const INFINITY: Self = Self::INFINITY;
+            const NEG_INFINITY: Self = Self::NEG_INFINITY;
+            const NAN: Self = Self::NAN;
+            // NAN isn't guaranteed to be positive but it usually is. We only use this for
+            // tests.
+            const NEG_NAN: Self = $from_bits($to_bits(Self::NAN) | Self::SIGN_MASK);
+            const MAX: Self = -Self::MIN;
+            // Sign bit set, saturated mantissa, saturated exponent with last bit zeroed
+            const MIN: Self = $from_bits(Self::Int::MAX & !(1 << Self::SIG_BITS));
+            const EPSILON: Self = <$ty>::EPSILON;
+
+            // Exponent is a 1 in the LSB
+            const MIN_POSITIVE_NORMAL: Self = $from_bits(1 << Self::SIG_BITS);
+
+            const PI: Self = core::$ty::consts::PI;
+            const NEG_PI: Self = -Self::PI;
+            const FRAC_PI_2: Self = core::$ty::consts::FRAC_PI_2;
+
+            const BITS: u32 = $bits;
+            const SIG_BITS: u32 = $significand_bits;
+
+            const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
+            const SIG_MASK: Self::Int = (1 << Self::SIG_BITS) - 1;
+            const EXP_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIG_MASK);
+            const IMPLICIT_BIT: Self::Int = 1 << Self::SIG_BITS;
+
+            fn to_bits(self) -> Self::Int {
+                self.to_bits()
+            }
+            fn is_nan(self) -> bool {
+                self.is_nan()
+            }
+            fn is_infinite(self) -> bool {
+                self.is_infinite()
+            }
+            fn is_sign_negative(self) -> bool {
+                self.is_sign_negative()
+            }
+            fn from_bits(a: Self::Int) -> Self {
+                Self::from_bits(a)
+            }
+            fn abs(self) -> Self {
+                cfg_if! {
+                    // FIXME(msrv): `abs` is available in `core` starting with 1.85.
+                    if #[cfg(intrinsics_enabled)] {
+                        self.abs()
+                    } else {
+                        super::super::generic::fabs(self)
+                    }
+                }
+            }
+            fn copysign(self, other: Self) -> Self {
+                cfg_if! {
+                    // FIXME(msrv): `copysign` is available in `core` starting with 1.85.
+                    if #[cfg(intrinsics_enabled)] {
+                        self.copysign(other)
+                    } else {
+                        super::super::generic::copysign(self, other)
+                    }
+                }
+            }
+            fn fma(self, y: Self, z: Self) -> Self {
+                cfg_if! {
+                    // fma is not yet available in `core`
+                    if #[cfg(intrinsics_enabled)] {
+                        unsafe{ core::intrinsics::$fma_intrinsic(self, y, z) }
+                    } else {
+                        super::super::$fma_fn(self, y, z)
+                    }
+                }
+            }
+            fn normalize(significand: Self::Int) -> (i32, Self::Int) {
+                let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
+                (
+                    1i32.wrapping_sub(shift as i32),
+                    significand << shift as Self::Int,
+                )
+            }
+        }
+    };
+}
+
+#[cfg(f16_enabled)]
+float_impl!(
+    f16,
+    u16,
+    i16,
+    16,
+    10,
+    f16::from_bits,
+    f16::to_bits,
+    fmaf16,
+    fmaf16
+);
+float_impl!(
+    f32,
+    u32,
+    i32,
+    32,
+    23,
+    f32_from_bits,
+    f32_to_bits,
+    fmaf,
+    fmaf32
+);
+float_impl!(
+    f64,
+    u64,
+    i64,
+    64,
+    52,
+    f64_from_bits,
+    f64_to_bits,
+    fma,
+    fmaf64
+);
+#[cfg(f128_enabled)]
+float_impl!(
+    f128,
+    u128,
+    i128,
+    128,
+    112,
+    f128::from_bits,
+    f128::to_bits,
+    fmaf128,
+    fmaf128
+);
+
+/* FIXME(msrv): vendor some things that are not const stable at our MSRV */
+
+/// `f32::from_bits`
+pub const fn f32_from_bits(bits: u32) -> f32 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<u32, f32>(bits) }
+}
+
+/// `f32::to_bits`
+pub const fn f32_to_bits(x: f32) -> u32 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<f32, u32>(x) }
+}
+
+/// `f64::from_bits`
+pub const fn f64_from_bits(bits: u64) -> f64 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<u64, f64>(bits) }
+}
+
+/// `f64::to_bits`
+pub const fn f64_to_bits(x: f64) -> u64 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<f64, u64>(x) }
+}
+
+/// Trait for floats twice the bit width of another integer.
+pub trait DFloat: Float {
+    /// Float that is half the bit width of the floatthis trait is implemented for.
+    type H: HFloat<D = Self>;
+
+    /// Narrow the float type.
+    fn narrow(self) -> Self::H;
+}
+
+/// Trait for floats half the bit width of another float.
+pub trait HFloat: Float {
+    /// Float that is double the bit width of the float this trait is implemented for.
+    type D: DFloat<H = Self>;
+
+    /// Widen the float type.
+    fn widen(self) -> Self::D;
+}
+
+macro_rules! impl_d_float {
+    ($($X:ident $D:ident),*) => {
+        $(
+            impl DFloat for $D {
+                type H = $X;
+
+                fn narrow(self) -> Self::H {
+                    self as $X
+                }
+            }
+        )*
+    };
+}
+
+macro_rules! impl_h_float {
+    ($($H:ident $X:ident),*) => {
+        $(
+            impl HFloat for $H {
+                type D = $X;
+
+                fn widen(self) -> Self::D {
+                    self as $X
+                }
+            }
+        )*
+    };
+}
+
+impl_d_float!(f32 f64);
+#[cfg(f16_enabled)]
+impl_d_float!(f16 f32);
+#[cfg(f128_enabled)]
+impl_d_float!(f64 f128);
+
+impl_h_float!(f32 f64);
+#[cfg(f16_enabled)]
+impl_h_float!(f16 f32);
+#[cfg(f128_enabled)]
+impl_h_float!(f64 f128);
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn check_f16() {
+        // Constants
+        assert_eq!(f16::EXP_SAT, 0b11111);
+        assert_eq!(f16::EXP_BIAS, 15);
+        assert_eq!(f16::EXP_MAX, 15);
+        assert_eq!(f16::EXP_MIN, -14);
+        assert_eq!(f16::EXP_MIN_SUBNORM, -24);
+
+        // `exp_unbiased`
+        assert_eq!(f16::FRAC_PI_2.exp_unbiased(), 0);
+        assert_eq!((1.0f16 / 2.0).exp_unbiased(), -1);
+        assert_eq!(f16::MAX.exp_unbiased(), 15);
+        assert_eq!(f16::MIN.exp_unbiased(), 15);
+        assert_eq!(f16::MIN_POSITIVE.exp_unbiased(), -14);
+        // This is a convenience method and not ldexp, `exp_unbiased` does not return correct
+        // results for zero and subnormals.
+        assert_eq!(f16::ZERO.exp_unbiased(), -15);
+        assert_eq!(f16::from_bits(0x1).exp_unbiased(), -15);
+        assert_eq!(f16::MIN_POSITIVE, f16::MIN_POSITIVE_NORMAL);
+
+        // `from_parts`
+        assert_biteq!(f16::from_parts(true, f16::EXP_BIAS, 0), -1.0f16);
+        assert_biteq!(f16::from_parts(false, 0, 1), f16::from_bits(0x1));
+    }
+
+    #[test]
+    fn check_f32() {
+        // Constants
+        assert_eq!(f32::EXP_SAT, 0b11111111);
+        assert_eq!(f32::EXP_BIAS, 127);
+        assert_eq!(f32::EXP_MAX, 127);
+        assert_eq!(f32::EXP_MIN, -126);
+        assert_eq!(f32::EXP_MIN_SUBNORM, -149);
+
+        // `exp_unbiased`
+        assert_eq!(f32::FRAC_PI_2.exp_unbiased(), 0);
+        assert_eq!((1.0f32 / 2.0).exp_unbiased(), -1);
+        assert_eq!(f32::MAX.exp_unbiased(), 127);
+        assert_eq!(f32::MIN.exp_unbiased(), 127);
+        assert_eq!(f32::MIN_POSITIVE.exp_unbiased(), -126);
+        // This is a convenience method and not ldexp, `exp_unbiased` does not return correct
+        // results for zero and subnormals.
+        assert_eq!(f32::ZERO.exp_unbiased(), -127);
+        assert_eq!(f32::from_bits(0x1).exp_unbiased(), -127);
+        assert_eq!(f32::MIN_POSITIVE, f32::MIN_POSITIVE_NORMAL);
+
+        // `from_parts`
+        assert_biteq!(f32::from_parts(true, f32::EXP_BIAS, 0), -1.0f32);
+        assert_biteq!(
+            f32::from_parts(false, 10 + f32::EXP_BIAS, 0),
+            hf32!("0x1p10")
+        );
+        assert_biteq!(f32::from_parts(false, 0, 1), f32::from_bits(0x1));
+    }
+
+    #[test]
+    fn check_f64() {
+        // Constants
+        assert_eq!(f64::EXP_SAT, 0b11111111111);
+        assert_eq!(f64::EXP_BIAS, 1023);
+        assert_eq!(f64::EXP_MAX, 1023);
+        assert_eq!(f64::EXP_MIN, -1022);
+        assert_eq!(f64::EXP_MIN_SUBNORM, -1074);
+
+        // `exp_unbiased`
+        assert_eq!(f64::FRAC_PI_2.exp_unbiased(), 0);
+        assert_eq!((1.0f64 / 2.0).exp_unbiased(), -1);
+        assert_eq!(f64::MAX.exp_unbiased(), 1023);
+        assert_eq!(f64::MIN.exp_unbiased(), 1023);
+        assert_eq!(f64::MIN_POSITIVE.exp_unbiased(), -1022);
+        // This is a convenience method and not ldexp, `exp_unbiased` does not return correct
+        // results for zero and subnormals.
+        assert_eq!(f64::ZERO.exp_unbiased(), -1023);
+        assert_eq!(f64::from_bits(0x1).exp_unbiased(), -1023);
+        assert_eq!(f64::MIN_POSITIVE, f64::MIN_POSITIVE_NORMAL);
+
+        // `from_parts`
+        assert_biteq!(f64::from_parts(true, f64::EXP_BIAS, 0), -1.0f64);
+        assert_biteq!(
+            f64::from_parts(false, 10 + f64::EXP_BIAS, 0),
+            hf64!("0x1p10")
+        );
+        assert_biteq!(f64::from_parts(false, 0, 1), f64::from_bits(0x1));
+    }
+
+    #[test]
+    #[cfg(f128_enabled)]
+    fn check_f128() {
+        // Constants
+        assert_eq!(f128::EXP_SAT, 0b111111111111111);
+        assert_eq!(f128::EXP_BIAS, 16383);
+        assert_eq!(f128::EXP_MAX, 16383);
+        assert_eq!(f128::EXP_MIN, -16382);
+        assert_eq!(f128::EXP_MIN_SUBNORM, -16494);
+
+        // `exp_unbiased`
+        assert_eq!(f128::FRAC_PI_2.exp_unbiased(), 0);
+        assert_eq!((1.0f128 / 2.0).exp_unbiased(), -1);
+        assert_eq!(f128::MAX.exp_unbiased(), 16383);
+        assert_eq!(f128::MIN.exp_unbiased(), 16383);
+        assert_eq!(f128::MIN_POSITIVE.exp_unbiased(), -16382);
+        // This is a convenience method and not ldexp, `exp_unbiased` does not return correct
+        // results for zero and subnormals.
+        assert_eq!(f128::ZERO.exp_unbiased(), -16383);
+        assert_eq!(f128::from_bits(0x1).exp_unbiased(), -16383);
+        assert_eq!(f128::MIN_POSITIVE, f128::MIN_POSITIVE_NORMAL);
+
+        // `from_parts`
+        assert_biteq!(f128::from_parts(true, f128::EXP_BIAS, 0), -1.0f128);
+        assert_biteq!(f128::from_parts(false, 0, 1), f128::from_bits(0x1));
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/hex_float.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/hex_float.rs
new file mode 100644
index 0000000..85569d9
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/hex_float.rs
@@ -0,0 +1,1181 @@
+//! Utilities for working with hex float formats.
+
+use core::fmt;
+
+use super::{Float, Round, Status, f32_from_bits, f64_from_bits};
+
+/// Construct a 16-bit float from hex float representation (C-style)
+#[cfg(f16_enabled)]
+pub const fn hf16(s: &str) -> f16 {
+    match parse_hex_exact(s, 16, 10) {
+        Ok(bits) => f16::from_bits(bits as u16),
+        Err(HexFloatParseError(s)) => panic!("{}", s),
+    }
+}
+
+/// Construct a 32-bit float from hex float representation (C-style)
+#[allow(unused)]
+pub const fn hf32(s: &str) -> f32 {
+    match parse_hex_exact(s, 32, 23) {
+        Ok(bits) => f32_from_bits(bits as u32),
+        Err(HexFloatParseError(s)) => panic!("{}", s),
+    }
+}
+
+/// Construct a 64-bit float from hex float representation (C-style)
+pub const fn hf64(s: &str) -> f64 {
+    match parse_hex_exact(s, 64, 52) {
+        Ok(bits) => f64_from_bits(bits as u64),
+        Err(HexFloatParseError(s)) => panic!("{}", s),
+    }
+}
+
+/// Construct a 128-bit float from hex float representation (C-style)
+#[cfg(f128_enabled)]
+pub const fn hf128(s: &str) -> f128 {
+    match parse_hex_exact(s, 128, 112) {
+        Ok(bits) => f128::from_bits(bits),
+        Err(HexFloatParseError(s)) => panic!("{}", s),
+    }
+}
+#[derive(Copy, Clone, Debug)]
+pub struct HexFloatParseError(&'static str);
+
+/// Parses any float to its bitwise representation, returning an error if it cannot be represented exactly
+pub const fn parse_hex_exact(
+    s: &str,
+    bits: u32,
+    sig_bits: u32,
+) -> Result<u128, HexFloatParseError> {
+    match parse_any(s, bits, sig_bits, Round::Nearest) {
+        Err(e) => Err(e),
+        Ok((bits, Status::OK)) => Ok(bits),
+        Ok((_, status)) if status.overflow() => Err(HexFloatParseError("the value is too huge")),
+        Ok((_, status)) if status.underflow() => Err(HexFloatParseError("the value is too tiny")),
+        Ok((_, status)) if status.inexact() => Err(HexFloatParseError("the value is too precise")),
+        Ok(_) => unreachable!(),
+    }
+}
+
+/// Parse any float from hex to its bitwise representation.
+pub const fn parse_any(
+    s: &str,
+    bits: u32,
+    sig_bits: u32,
+    round: Round,
+) -> Result<(u128, Status), HexFloatParseError> {
+    let mut b = s.as_bytes();
+
+    if sig_bits > 119 || bits > 128 || bits < sig_bits + 3 || bits > sig_bits + 30 {
+        return Err(HexFloatParseError("unsupported target float configuration"));
+    }
+
+    let neg = matches!(b, [b'-', ..]);
+    if let &[b'-' | b'+', ref rest @ ..] = b {
+        b = rest;
+    }
+
+    let sign_bit = 1 << (bits - 1);
+    let quiet_bit = 1 << (sig_bits - 1);
+    let nan = sign_bit - quiet_bit;
+    let inf = nan - quiet_bit;
+
+    let (mut x, status) = match *b {
+        [b'i' | b'I', b'n' | b'N', b'f' | b'F'] => (inf, Status::OK),
+        [b'n' | b'N', b'a' | b'A', b'n' | b'N'] => (nan, Status::OK),
+        [b'0', b'x' | b'X', ref rest @ ..] => {
+            let round = match (neg, round) {
+                // parse("-x", Round::Positive) == -parse("x", Round::Negative)
+                (true, Round::Positive) => Round::Negative,
+                (true, Round::Negative) => Round::Positive,
+                // rounding toward nearest or zero are symmetric
+                (true, Round::Nearest | Round::Zero) | (false, _) => round,
+            };
+            match parse_finite(rest, bits, sig_bits, round) {
+                Err(e) => return Err(e),
+                Ok(res) => res,
+            }
+        }
+        _ => return Err(HexFloatParseError("no hex indicator")),
+    };
+
+    if neg {
+        x ^= sign_bit;
+    }
+
+    Ok((x, status))
+}
+
+const fn parse_finite(
+    b: &[u8],
+    bits: u32,
+    sig_bits: u32,
+    rounding_mode: Round,
+) -> Result<(u128, Status), HexFloatParseError> {
+    let exp_bits: u32 = bits - sig_bits - 1;
+    let max_msb: i32 = (1 << (exp_bits - 1)) - 1;
+    // The exponent of one ULP in the subnormals
+    let min_lsb: i32 = 1 - max_msb - sig_bits as i32;
+
+    let (mut sig, mut exp) = match parse_hex(b) {
+        Err(e) => return Err(e),
+        Ok(Parsed { sig: 0, .. }) => return Ok((0, Status::OK)),
+        Ok(Parsed { sig, exp }) => (sig, exp),
+    };
+
+    let mut round_bits = u128_ilog2(sig) as i32 - sig_bits as i32;
+
+    // Round at least up to min_lsb
+    if exp < min_lsb - round_bits {
+        round_bits = min_lsb - exp;
+    }
+
+    let mut status = Status::OK;
+
+    exp += round_bits;
+
+    if round_bits > 0 {
+        // first, prepare for rounding exactly two bits
+        if round_bits == 1 {
+            sig <<= 1;
+        } else if round_bits > 2 {
+            sig = shr_odd_rounding(sig, (round_bits - 2) as u32);
+        }
+
+        if sig & 0b11 != 0 {
+            status = Status::INEXACT;
+        }
+
+        sig = shr2_round(sig, rounding_mode);
+    } else if round_bits < 0 {
+        sig <<= -round_bits;
+    }
+
+    // The parsed value is X = sig * 2^exp
+    // Expressed as a multiple U of the smallest subnormal value:
+    // X = U * 2^min_lsb, so U = sig * 2^(exp-min_lsb)
+    let uexp = (exp - min_lsb) as u128;
+    let uexp = uexp << sig_bits;
+
+    // Note that it is possible for the exponent bits to equal 2 here
+    // if the value rounded up, but that means the mantissa is all zeroes
+    // so the value is still correct
+    debug_assert!(sig <= 2 << sig_bits);
+
+    let inf = ((1 << exp_bits) - 1) << sig_bits;
+
+    let bits = match sig.checked_add(uexp) {
+        Some(bits) if bits < inf => {
+            // inexact subnormal or zero?
+            if status.inexact() && bits < (1 << sig_bits) {
+                status = status.with(Status::UNDERFLOW);
+            }
+            bits
+        }
+        _ => {
+            // overflow to infinity
+            status = status.with(Status::OVERFLOW).with(Status::INEXACT);
+            match rounding_mode {
+                Round::Positive | Round::Nearest => inf,
+                Round::Negative | Round::Zero => inf - 1,
+            }
+        }
+    };
+    Ok((bits, status))
+}
+
+/// Shift right, rounding all inexact divisions to the nearest odd number
+/// E.g. (0 >> 4) -> 0, (1..=31 >> 4) -> 1, (32 >> 4) -> 2, ...
+///
+/// Useful for reducing a number before rounding the last two bits, since
+/// the result of the final rounding is preserved for all rounding modes.
+const fn shr_odd_rounding(x: u128, k: u32) -> u128 {
+    if k < 128 {
+        let inexact = x.trailing_zeros() < k;
+        (x >> k) | (inexact as u128)
+    } else {
+        (x != 0) as u128
+    }
+}
+
+/// Divide by 4, rounding with the given mode
+const fn shr2_round(mut x: u128, round: Round) -> u128 {
+    let t = (x as u32) & 0b111;
+    x >>= 2;
+    match round {
+        // Look-up-table on the last three bits for when to round up
+        Round::Nearest => x + ((0b11001000_u8 >> t) & 1) as u128,
+
+        Round::Negative => x,
+        Round::Zero => x,
+        Round::Positive => x + (t & 0b11 != 0) as u128,
+    }
+}
+
+/// A parsed finite and unsigned floating point number.
+struct Parsed {
+    /// Absolute value sig * 2^exp
+    sig: u128,
+    exp: i32,
+}
+
+/// Parse a hexadecimal float x
+const fn parse_hex(mut b: &[u8]) -> Result<Parsed, HexFloatParseError> {
+    let mut sig: u128 = 0;
+    let mut exp: i32 = 0;
+
+    let mut seen_point = false;
+    let mut some_digits = false;
+    let mut inexact = false;
+
+    while let &[c, ref rest @ ..] = b {
+        b = rest;
+
+        match c {
+            b'.' => {
+                if seen_point {
+                    return Err(HexFloatParseError(
+                        "unexpected '.' parsing fractional digits",
+                    ));
+                }
+                seen_point = true;
+                continue;
+            }
+            b'p' | b'P' => break,
+            c => {
+                let digit = match hex_digit(c) {
+                    Some(d) => d,
+                    None => return Err(HexFloatParseError("expected hexadecimal digit")),
+                };
+                some_digits = true;
+
+                if (sig >> 124) == 0 {
+                    sig <<= 4;
+                    sig |= digit as u128;
+                } else {
+                    // FIXME: it is technically possible for exp to overflow if parsing a string with >500M digits
+                    exp += 4;
+                    inexact |= digit != 0;
+                }
+                // Up until the fractional point, the value grows
+                // with more digits, but after it the exponent is
+                // compensated to match.
+                if seen_point {
+                    exp -= 4;
+                }
+            }
+        }
+    }
+    // If we've set inexact, the exact value has more than 125
+    // significant bits, and lies somewhere between sig and sig + 1.
+    // Because we'll round off at least two of the trailing bits,
+    // setting the last bit gives correct rounding for inexact values.
+    sig |= inexact as u128;
+
+    if !some_digits {
+        return Err(HexFloatParseError("at least one digit is required"));
+    };
+
+    some_digits = false;
+
+    let negate_exp = matches!(b, [b'-', ..]);
+    if let &[b'-' | b'+', ref rest @ ..] = b {
+        b = rest;
+    }
+
+    let mut pexp: u32 = 0;
+    while let &[c, ref rest @ ..] = b {
+        b = rest;
+        let digit = match dec_digit(c) {
+            Some(d) => d,
+            None => return Err(HexFloatParseError("expected decimal digit")),
+        };
+        some_digits = true;
+        pexp = pexp.saturating_mul(10);
+        pexp += digit as u32;
+    }
+
+    if !some_digits {
+        return Err(HexFloatParseError(
+            "at least one exponent digit is required",
+        ));
+    };
+
+    {
+        let e;
+        if negate_exp {
+            e = (exp as i64) - (pexp as i64);
+        } else {
+            e = (exp as i64) + (pexp as i64);
+        };
+
+        exp = if e < i32::MIN as i64 {
+            i32::MIN
+        } else if e > i32::MAX as i64 {
+            i32::MAX
+        } else {
+            e as i32
+        };
+    }
+    /* FIXME(msrv): once MSRV >= 1.66, replace the above workaround block with:
+    if negate_exp {
+        exp = exp.saturating_sub_unsigned(pexp);
+    } else {
+        exp = exp.saturating_add_unsigned(pexp);
+    };
+    */
+
+    Ok(Parsed { sig, exp })
+}
+
+const fn dec_digit(c: u8) -> Option<u8> {
+    match c {
+        b'0'..=b'9' => Some(c - b'0'),
+        _ => None,
+    }
+}
+
+const fn hex_digit(c: u8) -> Option<u8> {
+    match c {
+        b'0'..=b'9' => Some(c - b'0'),
+        b'a'..=b'f' => Some(c - b'a' + 10),
+        b'A'..=b'F' => Some(c - b'A' + 10),
+        _ => None,
+    }
+}
+
+/* FIXME(msrv): vendor some things that are not const stable at our MSRV */
+
+/// `u128::ilog2`
+const fn u128_ilog2(v: u128) -> u32 {
+    assert!(v != 0);
+    u128::BITS - 1 - v.leading_zeros()
+}
+
+/// Format a floating point number as its IEEE hex (`%a`) representation.
+pub struct Hexf<F>(pub F);
+
+// Adapted from https://github.com/ericseppanen/hexfloat2/blob/a5c27932f0ff/src/format.rs
+#[cfg(not(feature = "compiler-builtins"))]
+fn fmt_any_hex<F: Float>(x: &F, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    if x.is_sign_negative() {
+        write!(f, "-")?;
+    }
+
+    if x.is_nan() {
+        return write!(f, "NaN");
+    } else if x.is_infinite() {
+        return write!(f, "inf");
+    } else if *x == F::ZERO {
+        return write!(f, "0x0p+0");
+    }
+
+    let mut exponent = x.exp_unbiased();
+    let sig = x.to_bits() & F::SIG_MASK;
+
+    let bias = F::EXP_BIAS as i32;
+    // The mantissa MSB needs to be shifted up to the nearest nibble.
+    let mshift = (4 - (F::SIG_BITS % 4)) % 4;
+    let sig = sig << mshift;
+    // The width is rounded up to the nearest char (4 bits)
+    let mwidth = (F::SIG_BITS as usize + 3) / 4;
+    let leading = if exponent == -bias {
+        // subnormal number means we shift our output by 1 bit.
+        exponent += 1;
+        "0."
+    } else {
+        "1."
+    };
+
+    write!(f, "0x{leading}{sig:0mwidth$x}p{exponent:+}")
+}
+
+#[cfg(feature = "compiler-builtins")]
+fn fmt_any_hex<F: Float>(_x: &F, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    unimplemented!()
+}
+
+impl<F: Float> fmt::LowerHex for Hexf<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                fmt_any_hex(&self.0, f)
+            }
+        }
+    }
+}
+
+impl<F: Float> fmt::LowerHex for Hexf<(F, F)> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1))
+            }
+        }
+    }
+}
+
+impl<F: Float> fmt::LowerHex for Hexf<(F, i32)> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                write!(f, "({:x}, {:x})", Hexf(self.0.0), Hexf(self.0.1))
+            }
+        }
+    }
+}
+
+impl fmt::LowerHex for Hexf<i32> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                fmt::LowerHex::fmt(&self.0, f)
+            }
+        }
+    }
+}
+
+impl<T> fmt::Debug for Hexf<T>
+where
+    Hexf<T>: fmt::LowerHex,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                fmt::LowerHex::fmt(self, f)
+            }
+        }
+    }
+}
+
+impl<T> fmt::Display for Hexf<T>
+where
+    Hexf<T>: fmt::LowerHex,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        cfg_if! {
+            if #[cfg(feature = "compiler-builtins")] {
+                let _ = f;
+                unimplemented!()
+            } else {
+                fmt::LowerHex::fmt(self, f)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod parse_tests {
+    extern crate std;
+    use std::{format, println};
+
+    use super::*;
+
+    #[cfg(f16_enabled)]
+    fn rounding_properties(s: &str) -> Result<(), HexFloatParseError> {
+        let (xd, s0) = parse_any(s, 16, 10, Round::Negative)?;
+        let (xu, s1) = parse_any(s, 16, 10, Round::Positive)?;
+        let (xz, s2) = parse_any(s, 16, 10, Round::Zero)?;
+        let (xn, s3) = parse_any(s, 16, 10, Round::Nearest)?;
+
+        // FIXME: A value between the least normal and largest subnormal
+        // could have underflow status depend on rounding mode.
+
+        if let Status::OK = s0 {
+            // an exact result is the same for all rounding modes
+            assert_eq!(s0, s1);
+            assert_eq!(s0, s2);
+            assert_eq!(s0, s3);
+
+            assert_eq!(xd, xu);
+            assert_eq!(xd, xz);
+            assert_eq!(xd, xn);
+        } else {
+            assert!([s0, s1, s2, s3].into_iter().all(Status::inexact));
+
+            let xd = f16::from_bits(xd as u16);
+            let xu = f16::from_bits(xu as u16);
+            let xz = f16::from_bits(xz as u16);
+            let xn = f16::from_bits(xn as u16);
+
+            assert_biteq!(xd.next_up(), xu, "s={s}, xd={xd:?}, xu={xu:?}");
+
+            let signs = [xd, xu, xz, xn].map(f16::is_sign_negative);
+
+            if signs == [true; 4] {
+                assert_biteq!(xz, xu);
+            } else {
+                assert_eq!(signs, [false; 4]);
+                assert_biteq!(xz, xd);
+            }
+
+            if xn.to_bits() != xd.to_bits() {
+                assert_biteq!(xn, xu);
+            }
+        }
+        Ok(())
+    }
+    #[test]
+    #[cfg(f16_enabled)]
+    fn test_rounding() {
+        let n = 1_i32 << 14;
+        for i in -n..n {
+            let u = i.rotate_right(11) as u32;
+            let s = format!("{}", Hexf(f32::from_bits(u)));
+            assert!(rounding_properties(&s).is_ok());
+        }
+    }
+
+    #[test]
+    fn test_parse_any() {
+        for k in -149..=127 {
+            let s = format!("0x1p{k}");
+            let x = hf32(&s);
+            let y = if k < 0 {
+                0.5f32.powi(-k)
+            } else {
+                2.0f32.powi(k)
+            };
+            assert_eq!(x, y);
+        }
+
+        let mut s = *b"0x.0000000p-121";
+        for e in 0..40 {
+            for k in 0..(1 << 15) {
+                let expected = f32::from_bits(k) * 2.0f32.powi(e);
+                let x = hf32(std::str::from_utf8(&s).unwrap());
+                assert_eq!(
+                    x.to_bits(),
+                    expected.to_bits(),
+                    "\
+                    e={e}\n\
+                    k={k}\n\
+                    x={x}\n\
+                    expected={expected}\n\
+                    s={}\n\
+                    f32::from_bits(k)={}\n\
+                    2.0f32.powi(e)={}\
+                    ",
+                    std::str::from_utf8(&s).unwrap(),
+                    f32::from_bits(k),
+                    2.0f32.powi(e),
+                );
+                for i in (3..10).rev() {
+                    if s[i] == b'f' {
+                        s[i] = b'0';
+                    } else if s[i] == b'9' {
+                        s[i] = b'a';
+                        break;
+                    } else {
+                        s[i] += 1;
+                        break;
+                    }
+                }
+            }
+            for i in (12..15).rev() {
+                if s[i] == b'0' {
+                    s[i] = b'9';
+                } else {
+                    s[i] -= 1;
+                    break;
+                }
+            }
+            for i in (3..10).rev() {
+                s[i] = b'0';
+            }
+        }
+    }
+
+    // FIXME: this test is causing failures that are likely UB on various platforms
+    #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
+    #[test]
+    #[cfg(f128_enabled)]
+    fn rounding() {
+        let pi = std::f128::consts::PI;
+        let s = format!("{}", Hexf(pi));
+
+        for k in 0..=111 {
+            let (bits, status) = parse_any(&s, 128 - k, 112 - k, Round::Nearest).unwrap();
+            let scale = (1u128 << (112 - k - 1)) as f128;
+            let expected = (pi * scale).round_ties_even() / scale;
+            assert_eq!(bits << k, expected.to_bits(), "k = {k}, s = {s}");
+            assert_eq!(expected != pi, status.inexact());
+        }
+    }
+    #[test]
+    fn rounding_extreme_underflow() {
+        for k in 1..1000 {
+            let s = format!("0x1p{}", -149 - k);
+            let Ok((bits, status)) = parse_any(&s, 32, 23, Round::Nearest) else {
+                unreachable!()
+            };
+            assert_eq!(bits, 0, "{s} should round to zero, got bits={bits}");
+            assert!(
+                status.underflow(),
+                "should indicate underflow when parsing {s}"
+            );
+            assert!(status.inexact(), "should indicate inexact when parsing {s}");
+        }
+    }
+    #[test]
+    fn long_tail() {
+        for k in 1..1000 {
+            let s = format!("0x1.{}p0", "0".repeat(k));
+            let Ok(bits) = parse_hex_exact(&s, 32, 23) else {
+                panic!("parsing {s} failed")
+            };
+            assert_eq!(f32::from_bits(bits as u32), 1.0);
+
+            let s = format!("0x1.{}1p0", "0".repeat(k));
+            let Ok((bits, status)) = parse_any(&s, 32, 23, Round::Nearest) else {
+                unreachable!()
+            };
+            if status.inexact() {
+                assert!(1.0 == f32::from_bits(bits as u32));
+            } else {
+                assert!(1.0 < f32::from_bits(bits as u32));
+            }
+        }
+    }
+    // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to
+    // hide them from the AST.
+    #[cfg(f16_enabled)]
+    macro_rules! f16_tests {
+        () => {
+            #[test]
+            fn test_f16() {
+                let checks = [
+                    ("0x.1234p+16", (0x1234 as f16).to_bits()),
+                    ("0x1.234p+12", (0x1234 as f16).to_bits()),
+                    ("0x12.34p+8", (0x1234 as f16).to_bits()),
+                    ("0x123.4p+4", (0x1234 as f16).to_bits()),
+                    ("0x1234p+0", (0x1234 as f16).to_bits()),
+                    ("0x1234.p+0", (0x1234 as f16).to_bits()),
+                    ("0x1234.0p+0", (0x1234 as f16).to_bits()),
+                    ("0x1.ffcp+15", f16::MAX.to_bits()),
+                    ("0x1.0p+1", 2.0f16.to_bits()),
+                    ("0x1.0p+0", 1.0f16.to_bits()),
+                    ("0x1.ffp+8", 0x5ffc),
+                    ("+0x1.ffp+8", 0x5ffc),
+                    ("0x1p+0", 0x3c00),
+                    ("0x1.998p-4", 0x2e66),
+                    ("0x1.9p+6", 0x5640),
+                    ("0x0.0p0", 0.0f16.to_bits()),
+                    ("-0x0.0p0", (-0.0f16).to_bits()),
+                    ("0x1.0p0", 1.0f16.to_bits()),
+                    ("0x1.998p-4", (0.1f16).to_bits()),
+                    ("-0x1.998p-4", (-0.1f16).to_bits()),
+                    ("0x0.123p-12", 0x0123),
+                    ("0x1p-24", 0x0001),
+                    ("nan", f16::NAN.to_bits()),
+                    ("-nan", (-f16::NAN).to_bits()),
+                    ("inf", f16::INFINITY.to_bits()),
+                    ("-inf", f16::NEG_INFINITY.to_bits()),
+                ];
+                for (s, exp) in checks {
+                    println!("parsing {s}");
+                    assert!(rounding_properties(s).is_ok());
+                    let act = hf16(s).to_bits();
+                    assert_eq!(
+                        act, exp,
+                        "parsing {s}: {act:#06x} != {exp:#06x}\nact: {act:#018b}\nexp: {exp:#018b}"
+                    );
+                }
+            }
+
+            #[test]
+            fn test_macros_f16() {
+                assert_eq!(hf16!("0x1.ffp+8").to_bits(), 0x5ffc_u16);
+            }
+        };
+    }
+
+    #[cfg(f16_enabled)]
+    f16_tests!();
+
+    #[test]
+    fn test_f32() {
+        let checks = [
+            ("0x.1234p+16", (0x1234 as f32).to_bits()),
+            ("0x1.234p+12", (0x1234 as f32).to_bits()),
+            ("0x12.34p+8", (0x1234 as f32).to_bits()),
+            ("0x123.4p+4", (0x1234 as f32).to_bits()),
+            ("0x1234p+0", (0x1234 as f32).to_bits()),
+            ("0x1234.p+0", (0x1234 as f32).to_bits()),
+            ("0x1234.0p+0", (0x1234 as f32).to_bits()),
+            ("0x1.fffffep+127", f32::MAX.to_bits()),
+            ("0x1.0p+1", 2.0f32.to_bits()),
+            ("0x1.0p+0", 1.0f32.to_bits()),
+            ("0x1.ffep+8", 0x43fff000),
+            ("+0x1.ffep+8", 0x43fff000),
+            ("0x1p+0", 0x3f800000),
+            ("0x1.99999ap-4", 0x3dcccccd),
+            ("0x1.9p+6", 0x42c80000),
+            ("0x1.2d5ed2p+20", 0x4996af69),
+            ("-0x1.348eb8p+10", 0xc49a475c),
+            ("-0x1.33dcfep-33", 0xaf19ee7f),
+            ("0x0.0p0", 0.0f32.to_bits()),
+            ("-0x0.0p0", (-0.0f32).to_bits()),
+            ("0x1.0p0", 1.0f32.to_bits()),
+            ("0x1.99999ap-4", (0.1f32).to_bits()),
+            ("-0x1.99999ap-4", (-0.1f32).to_bits()),
+            ("0x1.111114p-127", 0x00444445),
+            ("0x1.23456p-130", 0x00091a2b),
+            ("0x1p-149", 0x00000001),
+            ("nan", f32::NAN.to_bits()),
+            ("-nan", (-f32::NAN).to_bits()),
+            ("inf", f32::INFINITY.to_bits()),
+            ("-inf", f32::NEG_INFINITY.to_bits()),
+        ];
+        for (s, exp) in checks {
+            println!("parsing {s}");
+            let act = hf32(s).to_bits();
+            assert_eq!(
+                act, exp,
+                "parsing {s}: {act:#010x} != {exp:#010x}\nact: {act:#034b}\nexp: {exp:#034b}"
+            );
+        }
+    }
+
+    #[test]
+    fn test_f64() {
+        let checks = [
+            ("0x.1234p+16", (0x1234 as f64).to_bits()),
+            ("0x1.234p+12", (0x1234 as f64).to_bits()),
+            ("0x12.34p+8", (0x1234 as f64).to_bits()),
+            ("0x123.4p+4", (0x1234 as f64).to_bits()),
+            ("0x1234p+0", (0x1234 as f64).to_bits()),
+            ("0x1234.p+0", (0x1234 as f64).to_bits()),
+            ("0x1234.0p+0", (0x1234 as f64).to_bits()),
+            ("0x1.ffep+8", 0x407ffe0000000000),
+            ("0x1p+0", 0x3ff0000000000000),
+            ("0x1.999999999999ap-4", 0x3fb999999999999a),
+            ("0x1.9p+6", 0x4059000000000000),
+            ("0x1.2d5ed1fe1da7bp+20", 0x4132d5ed1fe1da7b),
+            ("-0x1.348eb851eb852p+10", 0xc09348eb851eb852),
+            ("-0x1.33dcfe54a3803p-33", 0xbde33dcfe54a3803),
+            ("0x1.0p0", 1.0f64.to_bits()),
+            ("0x0.0p0", 0.0f64.to_bits()),
+            ("-0x0.0p0", (-0.0f64).to_bits()),
+            ("0x1.999999999999ap-4", 0.1f64.to_bits()),
+            ("0x1.999999999998ap-4", (0.1f64 - f64::EPSILON).to_bits()),
+            ("-0x1.999999999999ap-4", (-0.1f64).to_bits()),
+            ("-0x1.999999999998ap-4", (-0.1f64 + f64::EPSILON).to_bits()),
+            ("0x0.8000000000001p-1022", 0x0008000000000001),
+            ("0x0.123456789abcdp-1022", 0x000123456789abcd),
+            ("0x0.0000000000002p-1022", 0x0000000000000002),
+            ("nan", f64::NAN.to_bits()),
+            ("-nan", (-f64::NAN).to_bits()),
+            ("inf", f64::INFINITY.to_bits()),
+            ("-inf", f64::NEG_INFINITY.to_bits()),
+        ];
+        for (s, exp) in checks {
+            println!("parsing {s}");
+            let act = hf64(s).to_bits();
+            assert_eq!(
+                act, exp,
+                "parsing {s}: {act:#018x} != {exp:#018x}\nact: {act:#066b}\nexp: {exp:#066b}"
+            );
+        }
+    }
+
+    // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to
+    // hide them from the AST.
+    #[cfg(f128_enabled)]
+    macro_rules! f128_tests {
+        () => {
+            #[test]
+            fn test_f128() {
+                let checks = [
+                    ("0x.1234p+16", (0x1234 as f128).to_bits()),
+                    ("0x1.234p+12", (0x1234 as f128).to_bits()),
+                    ("0x12.34p+8", (0x1234 as f128).to_bits()),
+                    ("0x123.4p+4", (0x1234 as f128).to_bits()),
+                    ("0x1234p+0", (0x1234 as f128).to_bits()),
+                    ("0x1234.p+0", (0x1234 as f128).to_bits()),
+                    ("0x1234.0p+0", (0x1234 as f128).to_bits()),
+                    ("0x1.ffffffffffffffffffffffffffffp+16383", f128::MAX.to_bits()),
+                    ("0x1.0p+1", 2.0f128.to_bits()),
+                    ("0x1.0p+0", 1.0f128.to_bits()),
+                    ("0x1.ffep+8", 0x4007ffe0000000000000000000000000),
+                    ("+0x1.ffep+8", 0x4007ffe0000000000000000000000000),
+                    ("0x1p+0", 0x3fff0000000000000000000000000000),
+                    ("0x1.999999999999999999999999999ap-4", 0x3ffb999999999999999999999999999a),
+                    ("0x1.9p+6", 0x40059000000000000000000000000000),
+                    ("0x0.0p0", 0.0f128.to_bits()),
+                    ("-0x0.0p0", (-0.0f128).to_bits()),
+                    ("0x1.0p0", 1.0f128.to_bits()),
+                    ("0x1.999999999999999999999999999ap-4", (0.1f128).to_bits()),
+                    ("-0x1.999999999999999999999999999ap-4", (-0.1f128).to_bits()),
+                    ("0x0.abcdef0123456789abcdef012345p-16382", 0x0000abcdef0123456789abcdef012345),
+                    ("0x1p-16494", 0x00000000000000000000000000000001),
+                    ("nan", f128::NAN.to_bits()),
+                    ("-nan", (-f128::NAN).to_bits()),
+                    ("inf", f128::INFINITY.to_bits()),
+                    ("-inf", f128::NEG_INFINITY.to_bits()),
+                ];
+                for (s, exp) in checks {
+                    println!("parsing {s}");
+                    let act = hf128(s).to_bits();
+                    assert_eq!(
+                        act, exp,
+                        "parsing {s}: {act:#034x} != {exp:#034x}\nact: {act:#0130b}\nexp: {exp:#0130b}"
+                    );
+                }
+            }
+
+            #[test]
+            fn test_macros_f128() {
+                assert_eq!(hf128!("0x1.ffep+8").to_bits(), 0x4007ffe0000000000000000000000000_u128);
+            }
+        }
+    }
+
+    #[cfg(f128_enabled)]
+    f128_tests!();
+
+    #[test]
+    fn test_macros() {
+        #[cfg(f16_enabled)]
+        assert_eq!(hf16!("0x1.ffp+8").to_bits(), 0x5ffc_u16);
+        assert_eq!(hf32!("0x1.ffep+8").to_bits(), 0x43fff000_u32);
+        assert_eq!(hf64!("0x1.ffep+8").to_bits(), 0x407ffe0000000000_u64);
+        #[cfg(f128_enabled)]
+        assert_eq!(
+            hf128!("0x1.ffep+8").to_bits(),
+            0x4007ffe0000000000000000000000000_u128
+        );
+    }
+}
+
+#[cfg(test)]
+// FIXME(ppc): something with `should_panic` tests cause a SIGILL with ppc64le
+#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
+mod tests_panicking {
+    extern crate std;
+    use super::*;
+
+    // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to
+    // hide them from the AST.
+    #[cfg(f16_enabled)]
+    macro_rules! f16_tests {
+        () => {
+            #[test]
+            fn test_f16_almost_extra_precision() {
+                // Exact maximum precision allowed
+                hf16("0x1.ffcp+0");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too precise")]
+            fn test_f16_extra_precision() {
+                // One bit more than the above.
+                hf16("0x1.ffdp+0");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too huge")]
+            fn test_f16_overflow() {
+                // One bit more than the above.
+                hf16("0x1p+16");
+            }
+
+            #[test]
+            fn test_f16_tiniest() {
+                let x = hf16("0x1.p-24");
+                let y = hf16("0x0.001p-12");
+                let z = hf16("0x0.8p-23");
+                assert_eq!(x, y);
+                assert_eq!(x, z);
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f16_too_tiny() {
+                hf16("0x1.p-25");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f16_also_too_tiny() {
+                hf16("0x0.8p-24");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f16_again_too_tiny() {
+                hf16("0x0.001p-13");
+            }
+        };
+    }
+
+    #[cfg(f16_enabled)]
+    f16_tests!();
+
+    #[test]
+    fn test_f32_almost_extra_precision() {
+        // Exact maximum precision allowed
+        hf32("0x1.abcdeep+0");
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_f32_extra_precision2() {
+        // One bit more than the above.
+        hf32("0x1.ffffffp+127");
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too huge")]
+    fn test_f32_overflow() {
+        // One bit more than the above.
+        hf32("0x1p+128");
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too precise")]
+    fn test_f32_extra_precision() {
+        // One bit more than the above.
+        hf32("0x1.abcdefp+0");
+    }
+
+    #[test]
+    fn test_f32_tiniest() {
+        let x = hf32("0x1.p-149");
+        let y = hf32("0x0.0000000000000001p-85");
+        let z = hf32("0x0.8p-148");
+        assert_eq!(x, y);
+        assert_eq!(x, z);
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too tiny")]
+    fn test_f32_too_tiny() {
+        hf32("0x1.p-150");
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too tiny")]
+    fn test_f32_also_too_tiny() {
+        hf32("0x0.8p-149");
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too tiny")]
+    fn test_f32_again_too_tiny() {
+        hf32("0x0.0000000000000001p-86");
+    }
+
+    #[test]
+    fn test_f64_almost_extra_precision() {
+        // Exact maximum precision allowed
+        hf64("0x1.abcdabcdabcdfp+0");
+    }
+
+    #[test]
+    #[should_panic(expected = "the value is too precise")]
+    fn test_f64_extra_precision() {
+        // One bit more than the above.
+        hf64("0x1.abcdabcdabcdf8p+0");
+    }
+
+    // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to
+    // hide them from the AST.
+    #[cfg(f128_enabled)]
+    macro_rules! f128_tests {
+        () => {
+            #[test]
+            fn test_f128_almost_extra_precision() {
+                // Exact maximum precision allowed
+                hf128("0x1.ffffffffffffffffffffffffffffp+16383");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too precise")]
+            fn test_f128_extra_precision() {
+                // Just below the maximum finite.
+                hf128("0x1.fffffffffffffffffffffffffffe8p+16383");
+            }
+            #[test]
+            #[should_panic(expected = "the value is too huge")]
+            fn test_f128_extra_precision_overflow() {
+                // One bit more than the above. Should overflow.
+                hf128("0x1.ffffffffffffffffffffffffffff8p+16383");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too huge")]
+            fn test_f128_overflow() {
+                // One bit more than the above.
+                hf128("0x1p+16384");
+            }
+
+            #[test]
+            fn test_f128_tiniest() {
+                let x = hf128("0x1.p-16494");
+                let y = hf128("0x0.0000000000000001p-16430");
+                let z = hf128("0x0.8p-16493");
+                assert_eq!(x, y);
+                assert_eq!(x, z);
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f128_too_tiny() {
+                hf128("0x1.p-16495");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f128_again_too_tiny() {
+                hf128("0x0.0000000000000001p-16431");
+            }
+
+            #[test]
+            #[should_panic(expected = "the value is too tiny")]
+            fn test_f128_also_too_tiny() {
+                hf128("0x0.8p-16494");
+            }
+        };
+    }
+
+    #[cfg(f128_enabled)]
+    f128_tests!();
+}
+
+#[cfg(test)]
+mod print_tests {
+    extern crate std;
+    use std::string::ToString;
+
+    use super::*;
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn test_f16() {
+        use std::format;
+        // Exhaustively check that `f16` roundtrips.
+        for x in 0..=u16::MAX {
+            let f = f16::from_bits(x);
+            let s = format!("{}", Hexf(f));
+            let from_s = hf16(&s);
+
+            if f.is_nan() && from_s.is_nan() {
+                continue;
+            }
+
+            assert_eq!(
+                f.to_bits(),
+                from_s.to_bits(),
+                "{f:?} formatted as {s} but parsed as {from_s:?}"
+            );
+        }
+    }
+
+    #[test]
+    #[cfg(f16_enabled)]
+    fn test_f16_to_f32() {
+        use std::format;
+        // Exhaustively check that these are equivalent for all `f16`:
+        //  - `f16 -> f32`
+        //  - `f16 -> str -> f32`
+        //  - `f16 -> f32 -> str -> f32`
+        //  - `f16 -> f32 -> str -> f16 -> f32`
+        for x in 0..=u16::MAX {
+            let f16 = f16::from_bits(x);
+            let s16 = format!("{}", Hexf(f16));
+            let f32 = f16 as f32;
+            let s32 = format!("{}", Hexf(f32));
+
+            let a = hf32(&s16);
+            let b = hf32(&s32);
+            let c = hf16(&s32);
+
+            if f32.is_nan() && a.is_nan() && b.is_nan() && c.is_nan() {
+                continue;
+            }
+
+            assert_eq!(
+                f32.to_bits(),
+                a.to_bits(),
+                "{f16:?} : f16 formatted as {s16} which parsed as {a:?} : f16"
+            );
+            assert_eq!(
+                f32.to_bits(),
+                b.to_bits(),
+                "{f32:?} : f32 formatted as {s32} which parsed as {b:?} : f32"
+            );
+            assert_eq!(
+                f32.to_bits(),
+                (c as f32).to_bits(),
+                "{f32:?} : f32 formatted as {s32} which parsed as {c:?} : f16"
+            );
+        }
+    }
+    #[test]
+    fn spot_checks() {
+        assert_eq!(Hexf(f32::MAX).to_string(), "0x1.fffffep+127");
+        assert_eq!(Hexf(f64::MAX).to_string(), "0x1.fffffffffffffp+1023");
+
+        assert_eq!(Hexf(f32::MIN).to_string(), "-0x1.fffffep+127");
+        assert_eq!(Hexf(f64::MIN).to_string(), "-0x1.fffffffffffffp+1023");
+
+        assert_eq!(Hexf(f32::ZERO).to_string(), "0x0p+0");
+        assert_eq!(Hexf(f64::ZERO).to_string(), "0x0p+0");
+
+        assert_eq!(Hexf(f32::NEG_ZERO).to_string(), "-0x0p+0");
+        assert_eq!(Hexf(f64::NEG_ZERO).to_string(), "-0x0p+0");
+
+        assert_eq!(Hexf(f32::NAN).to_string(), "NaN");
+        assert_eq!(Hexf(f64::NAN).to_string(), "NaN");
+
+        assert_eq!(Hexf(f32::INFINITY).to_string(), "inf");
+        assert_eq!(Hexf(f64::INFINITY).to_string(), "inf");
+
+        assert_eq!(Hexf(f32::NEG_INFINITY).to_string(), "-inf");
+        assert_eq!(Hexf(f64::NEG_INFINITY).to_string(), "-inf");
+
+        #[cfg(f16_enabled)]
+        {
+            assert_eq!(Hexf(f16::MAX).to_string(), "0x1.ffcp+15");
+            assert_eq!(Hexf(f16::MIN).to_string(), "-0x1.ffcp+15");
+            assert_eq!(Hexf(f16::ZERO).to_string(), "0x0p+0");
+            assert_eq!(Hexf(f16::NEG_ZERO).to_string(), "-0x0p+0");
+            assert_eq!(Hexf(f16::NAN).to_string(), "NaN");
+            assert_eq!(Hexf(f16::INFINITY).to_string(), "inf");
+            assert_eq!(Hexf(f16::NEG_INFINITY).to_string(), "-inf");
+        }
+
+        #[cfg(f128_enabled)]
+        {
+            assert_eq!(
+                Hexf(f128::MAX).to_string(),
+                "0x1.ffffffffffffffffffffffffffffp+16383"
+            );
+            assert_eq!(
+                Hexf(f128::MIN).to_string(),
+                "-0x1.ffffffffffffffffffffffffffffp+16383"
+            );
+            assert_eq!(Hexf(f128::ZERO).to_string(), "0x0p+0");
+            assert_eq!(Hexf(f128::NEG_ZERO).to_string(), "-0x0p+0");
+            assert_eq!(Hexf(f128::NAN).to_string(), "NaN");
+            assert_eq!(Hexf(f128::INFINITY).to_string(), "inf");
+            assert_eq!(Hexf(f128::NEG_INFINITY).to_string(), "-inf");
+        }
+    }
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/int_traits.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/int_traits.rs
new file mode 100644
index 0000000..3ec1fab
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/int_traits.rs
@@ -0,0 +1,455 @@
+use core::{cmp, fmt, ops};
+
+/// Minimal integer implementations needed on all integer types, including wide integers.
+pub trait MinInt:
+    Copy
+    + fmt::Debug
+    + ops::BitOr<Output = Self>
+    + ops::Not<Output = Self>
+    + ops::Shl<u32, Output = Self>
+{
+    /// Type with the same width but other signedness
+    type OtherSign: MinInt;
+    /// Unsigned version of Self
+    type Unsigned: MinInt;
+
+    /// If `Self` is a signed integer
+    const SIGNED: bool;
+
+    /// The bitwidth of the int type
+    const BITS: u32;
+
+    const ZERO: Self;
+    const ONE: Self;
+    const MIN: Self;
+    const MAX: Self;
+}
+
+/// Access the associated `OtherSign` type from an int (helper to avoid ambiguous associated
+/// types).
+pub type OtherSign<I> = <I as MinInt>::OtherSign;
+
+/// Trait for some basic operations on integers
+#[allow(dead_code)]
+pub trait Int:
+    MinInt
+    + fmt::Display
+    + fmt::Binary
+    + fmt::LowerHex
+    + PartialEq
+    + PartialOrd
+    + ops::AddAssign
+    + ops::SubAssign
+    + ops::MulAssign
+    + ops::DivAssign
+    + ops::RemAssign
+    + ops::BitAndAssign
+    + ops::BitOrAssign
+    + ops::BitXorAssign
+    + ops::ShlAssign<i32>
+    + ops::ShlAssign<u32>
+    + ops::ShrAssign<u32>
+    + ops::ShrAssign<i32>
+    + ops::Add<Output = Self>
+    + ops::Sub<Output = Self>
+    + ops::Mul<Output = Self>
+    + ops::Div<Output = Self>
+    + ops::Rem<Output = Self>
+    + ops::Shl<i32, Output = Self>
+    + ops::Shl<u32, Output = Self>
+    + ops::Shr<i32, Output = Self>
+    + ops::Shr<u32, Output = Self>
+    + ops::BitXor<Output = Self>
+    + ops::BitAnd<Output = Self>
+    + cmp::Ord
+    + From<bool>
+    + CastFrom<i32>
+    + CastFrom<u16>
+    + CastFrom<u32>
+    + CastFrom<u8>
+    + CastFrom<usize>
+    + CastInto<i32>
+    + CastInto<u16>
+    + CastInto<u32>
+    + CastInto<u8>
+    + CastInto<usize>
+{
+    fn signed(self) -> OtherSign<Self::Unsigned>;
+    fn unsigned(self) -> Self::Unsigned;
+    fn from_unsigned(unsigned: Self::Unsigned) -> Self;
+    fn abs(self) -> Self;
+
+    fn from_bool(b: bool) -> Self;
+
+    /// Prevents the need for excessive conversions between signed and unsigned
+    fn logical_shr(self, other: u32) -> Self;
+
+    /// Absolute difference between two integers.
+    fn abs_diff(self, other: Self) -> Self::Unsigned;
+
+    // copied from primitive integers, but put in a trait
+    fn is_zero(self) -> bool;
+    fn checked_add(self, other: Self) -> Option<Self>;
+    fn checked_sub(self, other: Self) -> Option<Self>;
+    fn wrapping_neg(self) -> Self;
+    fn wrapping_add(self, other: Self) -> Self;
+    fn wrapping_mul(self, other: Self) -> Self;
+    fn wrapping_sub(self, other: Self) -> Self;
+    fn wrapping_shl(self, other: u32) -> Self;
+    fn wrapping_shr(self, other: u32) -> Self;
+    fn rotate_left(self, other: u32) -> Self;
+    fn overflowing_add(self, other: Self) -> (Self, bool);
+    fn overflowing_sub(self, other: Self) -> (Self, bool);
+    fn leading_zeros(self) -> u32;
+    fn ilog2(self) -> u32;
+}
+
+macro_rules! int_impl_common {
+    ($ty:ty) => {
+        fn from_bool(b: bool) -> Self {
+            b as $ty
+        }
+
+        fn logical_shr(self, other: u32) -> Self {
+            Self::from_unsigned(self.unsigned().wrapping_shr(other))
+        }
+
+        fn is_zero(self) -> bool {
+            self == Self::ZERO
+        }
+
+        fn checked_add(self, other: Self) -> Option<Self> {
+            self.checked_add(other)
+        }
+
+        fn checked_sub(self, other: Self) -> Option<Self> {
+            self.checked_sub(other)
+        }
+
+        fn wrapping_neg(self) -> Self {
+            <Self>::wrapping_neg(self)
+        }
+
+        fn wrapping_add(self, other: Self) -> Self {
+            <Self>::wrapping_add(self, other)
+        }
+
+        fn wrapping_mul(self, other: Self) -> Self {
+            <Self>::wrapping_mul(self, other)
+        }
+
+        fn wrapping_sub(self, other: Self) -> Self {
+            <Self>::wrapping_sub(self, other)
+        }
+
+        fn wrapping_shl(self, other: u32) -> Self {
+            <Self>::wrapping_shl(self, other)
+        }
+
+        fn wrapping_shr(self, other: u32) -> Self {
+            <Self>::wrapping_shr(self, other)
+        }
+
+        fn rotate_left(self, other: u32) -> Self {
+            <Self>::rotate_left(self, other)
+        }
+
+        fn overflowing_add(self, other: Self) -> (Self, bool) {
+            <Self>::overflowing_add(self, other)
+        }
+
+        fn overflowing_sub(self, other: Self) -> (Self, bool) {
+            <Self>::overflowing_sub(self, other)
+        }
+
+        fn leading_zeros(self) -> u32 {
+            <Self>::leading_zeros(self)
+        }
+
+        fn ilog2(self) -> u32 {
+            // On our older MSRV, this resolves to the trait method. Which won't actually work,
+            // but this is only called behind other gates.
+            #[allow(clippy::incompatible_msrv)]
+            <Self>::ilog2(self)
+        }
+    };
+}
+
+macro_rules! int_impl {
+    ($ity:ty, $uty:ty) => {
+        impl MinInt for $uty {
+            type OtherSign = $ity;
+            type Unsigned = $uty;
+
+            const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
+            const SIGNED: bool = Self::MIN != Self::ZERO;
+
+            const ZERO: Self = 0;
+            const ONE: Self = 1;
+            const MIN: Self = <Self>::MIN;
+            const MAX: Self = <Self>::MAX;
+        }
+
+        impl Int for $uty {
+            fn signed(self) -> $ity {
+                self as $ity
+            }
+
+            fn unsigned(self) -> Self {
+                self
+            }
+
+            fn abs(self) -> Self {
+                unimplemented!()
+            }
+
+            // It makes writing macros easier if this is implemented for both signed and unsigned
+            #[allow(clippy::wrong_self_convention)]
+            fn from_unsigned(me: $uty) -> Self {
+                me
+            }
+
+            fn abs_diff(self, other: Self) -> Self {
+                self.abs_diff(other)
+            }
+
+            int_impl_common!($uty);
+        }
+
+        impl MinInt for $ity {
+            type OtherSign = $uty;
+            type Unsigned = $uty;
+
+            const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();
+            const SIGNED: bool = Self::MIN != Self::ZERO;
+
+            const ZERO: Self = 0;
+            const ONE: Self = 1;
+            const MIN: Self = <Self>::MIN;
+            const MAX: Self = <Self>::MAX;
+        }
+
+        impl Int for $ity {
+            fn signed(self) -> Self {
+                self
+            }
+
+            fn unsigned(self) -> $uty {
+                self as $uty
+            }
+
+            fn abs(self) -> Self {
+                self.abs()
+            }
+
+            fn from_unsigned(me: $uty) -> Self {
+                me as $ity
+            }
+
+            fn abs_diff(self, other: Self) -> $uty {
+                self.abs_diff(other)
+            }
+
+            int_impl_common!($ity);
+        }
+    };
+}
+
+int_impl!(isize, usize);
+int_impl!(i8, u8);
+int_impl!(i16, u16);
+int_impl!(i32, u32);
+int_impl!(i64, u64);
+int_impl!(i128, u128);
+
+/// Trait for integers twice the bit width of another integer. This is implemented for all
+/// primitives except for `u8`, because there is not a smaller primitive.
+pub trait DInt: MinInt {
+    /// Integer that is half the bit width of the integer this trait is implemented for
+    type H: HInt<D = Self>;
+
+    /// Returns the low half of `self`
+    fn lo(self) -> Self::H;
+    /// Returns the high half of `self`
+    fn hi(self) -> Self::H;
+    /// Returns the low and high halves of `self` as a tuple
+    fn lo_hi(self) -> (Self::H, Self::H) {
+        (self.lo(), self.hi())
+    }
+    /// Constructs an integer using lower and higher half parts
+    #[allow(unused)]
+    fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
+        lo.zero_widen() | hi.widen_hi()
+    }
+}
+
+/// Trait for integers half the bit width of another integer. This is implemented for all
+/// primitives except for `u128`, because it there is not a larger primitive.
+pub trait HInt: Int {
+    /// Integer that is double the bit width of the integer this trait is implemented for
+    type D: DInt<H = Self> + MinInt;
+
+    // NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for
+    // unknown reasons this can cause infinite recursion when optimizations are disabled. See
+    // <https://github.com/rust-lang/compiler-builtins/pull/707> for context.
+
+    /// Widens (using default extension) the integer to have double bit width
+    fn widen(self) -> Self::D;
+    /// Widens (zero extension only) the integer to have double bit width. This is needed to get
+    /// around problems with associated type bounds (such as `Int<Othersign: DInt>`) being unstable
+    fn zero_widen(self) -> Self::D;
+    /// Widens the integer to have double bit width and shifts the integer into the higher bits
+    #[allow(unused)]
+    fn widen_hi(self) -> Self::D;
+    /// Widening multiplication with zero widening. This cannot overflow.
+    fn zero_widen_mul(self, rhs: Self) -> Self::D;
+    /// Widening multiplication. This cannot overflow.
+    fn widen_mul(self, rhs: Self) -> Self::D;
+}
+
+macro_rules! impl_d_int {
+    ($($X:ident $D:ident),*) => {
+        $(
+            impl DInt for $D {
+                type H = $X;
+
+                fn lo(self) -> Self::H {
+                    self as $X
+                }
+                fn hi(self) -> Self::H {
+                    (self >> <$X as MinInt>::BITS) as $X
+                }
+            }
+        )*
+    };
+}
+
+macro_rules! impl_h_int {
+    ($($H:ident $uH:ident $X:ident),*) => {
+        $(
+            impl HInt for $H {
+                type D = $X;
+
+                fn widen(self) -> Self::D {
+                    self as $X
+                }
+                fn zero_widen(self) -> Self::D {
+                    (self as $uH) as $X
+                }
+                fn zero_widen_mul(self, rhs: Self) -> Self::D {
+                    self.zero_widen().wrapping_mul(rhs.zero_widen())
+                }
+                fn widen_mul(self, rhs: Self) -> Self::D {
+                    self.widen().wrapping_mul(rhs.widen())
+                }
+                fn widen_hi(self) -> Self::D {
+                    (self as $X) << <Self as MinInt>::BITS
+                }
+            }
+        )*
+    };
+}
+
+impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
+impl_h_int!(
+    u8 u8 u16,
+    u16 u16 u32,
+    u32 u32 u64,
+    u64 u64 u128,
+    i8 u8 i16,
+    i16 u16 i32,
+    i32 u32 i64,
+    i64 u64 i128
+);
+
+/// Trait to express (possibly lossy) casting of integers
+pub trait CastInto<T: Copy>: Copy {
+    /// By default, casts should be exact.
+    fn cast(self) -> T;
+
+    /// Call for casts that are expected to truncate.
+    fn cast_lossy(self) -> T;
+}
+
+pub trait CastFrom<T: Copy>: Copy {
+    /// By default, casts should be exact.
+    fn cast_from(value: T) -> Self;
+
+    /// Call for casts that are expected to truncate.
+    fn cast_from_lossy(value: T) -> Self;
+}
+
+impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {
+    fn cast_from(value: U) -> Self {
+        value.cast()
+    }
+
+    fn cast_from_lossy(value: U) -> Self {
+        value.cast_lossy()
+    }
+}
+
+macro_rules! cast_into {
+    ($ty:ty) => {
+        cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);
+    };
+    ($ty:ty; $($into:ty),*) => {$(
+        impl CastInto<$into> for $ty {
+            fn cast(self) -> $into {
+                // All we can really do to enforce casting rules is check the rules when in
+                // debug mode.
+                #[cfg(not(feature = "compiler-builtins"))]
+                debug_assert!(<$into>::try_from(self).is_ok(), "failed cast from {self}");
+                self as $into
+            }
+
+            fn cast_lossy(self) -> $into {
+                self as $into
+            }
+        }
+    )*};
+}
+
+macro_rules! cast_into_float {
+    ($ty:ty) => {
+        #[cfg(f16_enabled)]
+        cast_into_float!($ty; f16);
+
+        cast_into_float!($ty; f32, f64);
+
+        #[cfg(f128_enabled)]
+        cast_into_float!($ty; f128);
+    };
+    ($ty:ty; $($into:ty),*) => {$(
+        impl CastInto<$into> for $ty {
+            fn cast(self) -> $into {
+                #[cfg(not(feature = "compiler-builtins"))]
+                debug_assert_eq!(self as $into as $ty, self, "inexact float cast");
+                self as $into
+            }
+
+            fn cast_lossy(self) -> $into {
+                self as $into
+            }
+        }
+    )*};
+}
+
+cast_into!(usize);
+cast_into!(isize);
+cast_into!(u8);
+cast_into!(i8);
+cast_into!(u16);
+cast_into!(i16);
+cast_into!(u32);
+cast_into!(i32);
+cast_into!(u64);
+cast_into!(i64);
+cast_into!(u128);
+cast_into!(i128);
+
+cast_into_float!(i8);
+cast_into_float!(i16);
+cast_into_float!(i32);
+cast_into_float!(i64);
+cast_into_float!(i128);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/macros.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/macros.rs
new file mode 100644
index 0000000..0b72db0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/macros.rs
@@ -0,0 +1,157 @@
+/// `libm` cannot have dependencies, so this is vendored directly from the `cfg-if` crate
+/// (with some comments stripped for compactness).
+macro_rules! cfg_if {
+    // match if/else chains with a final `else`
+    ($(
+        if #[cfg($meta:meta)] { $($tokens:tt)* }
+    ) else * else {
+        $($tokens2:tt)*
+    }) => {
+        cfg_if! { @__items () ; $( ( ($meta) ($($tokens)*) ), )* ( () ($($tokens2)*) ), }
+    };
+
+    // match if/else chains lacking a final `else`
+    (
+        if #[cfg($i_met:meta)] { $($i_tokens:tt)* }
+        $( else if #[cfg($e_met:meta)] { $($e_tokens:tt)* } )*
+    ) => {
+        cfg_if! {
+            @__items
+            () ;
+            ( ($i_met) ($($i_tokens)*) ),
+            $( ( ($e_met) ($($e_tokens)*) ), )*
+            ( () () ),
+        }
+    };
+
+    // Internal and recursive macro to emit all the items
+    //
+    // Collects all the negated cfgs in a list at the beginning and after the
+    // semicolon is all the remaining items
+    (@__items ($($not:meta,)*) ; ) => {};
+    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($tokens:tt)*) ), $($rest:tt)*) => {
+        #[cfg(all($($m,)* not(any($($not),*))))] cfg_if! { @__identity $($tokens)* }
+        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
+    };
+
+    // Internal macro to make __apply work out right for different match types,
+    // because of how macros matching/expand stuff.
+    (@__identity $($tokens:tt)*) => { $($tokens)* };
+}
+
+/// Choose between using an arch-specific implementation and the function body. Returns directly
+/// if the arch implementation is used, otherwise continue with the rest of the function.
+///
+/// Specify a `use_arch` meta field if an architecture-specific implementation is provided.
+/// These live in the `math::arch::some_target_arch` module.
+///
+/// Specify a `use_arch_required` meta field if something architecture-specific must be used
+/// regardless of feature configuration (`force-soft-floats`).
+///
+/// The passed meta options do not need to account for the `arch` target feature.
+macro_rules! select_implementation {
+    (
+        name: $fn_name:ident,
+        // Configuration meta for when to use arch-specific implementation that requires hard
+        // float ops
+        $( use_arch: $use_arch:meta, )?
+        // Configuration meta for when to use the arch module regardless of whether softfloats
+        // have been requested.
+        $( use_arch_required: $use_arch_required:meta, )?
+        args: $($arg:ident),+ ,
+    ) => {
+        // FIXME: these use paths that are a pretty fragile (`super`). We should figure out
+        // something better w.r.t. how this is vendored into compiler-builtins.
+
+        // However, we do need a few things from `arch` that are used even with soft floats.
+        select_implementation! {
+            @cfg $($use_arch_required)?;
+            if true {
+                return  super::arch::$fn_name( $($arg),+ );
+            }
+        }
+
+        // By default, never use arch-specific implementations if we have force-soft-floats
+        #[cfg(arch_enabled)]
+        select_implementation! {
+            @cfg $($use_arch)?;
+            // Wrap in `if true` to avoid unused warnings
+            if true {
+                return  super::arch::$fn_name( $($arg),+ );
+            }
+        }
+    };
+
+    // Coalesce helper to construct an expression only if a config is provided
+    (@cfg ; $ex:expr) => { };
+    (@cfg $provided:meta; $ex:expr) => { #[cfg($provided)] $ex };
+}
+
+/// Construct a 16-bit float from hex float representation (C-style), guaranteed to
+/// evaluate at compile time.
+#[cfg(f16_enabled)]
+#[cfg_attr(feature = "unstable-public-internals", macro_export)]
+#[allow(unused_macros)]
+macro_rules! hf16 {
+    ($s:literal) => {{
+        const X: f16 = $crate::support::hf16($s);
+        X
+    }};
+}
+
+/// Construct a 32-bit float from hex float representation (C-style), guaranteed to
+/// evaluate at compile time.
+#[allow(unused_macros)]
+#[cfg_attr(feature = "unstable-public-internals", macro_export)]
+macro_rules! hf32 {
+    ($s:literal) => {{
+        const X: f32 = $crate::support::hf32($s);
+        X
+    }};
+}
+
+/// Construct a 64-bit float from hex float representation (C-style), guaranteed to
+/// evaluate at compile time.
+#[allow(unused_macros)]
+#[cfg_attr(feature = "unstable-public-internals", macro_export)]
+macro_rules! hf64 {
+    ($s:literal) => {{
+        const X: f64 = $crate::support::hf64($s);
+        X
+    }};
+}
+
+/// Construct a 128-bit float from hex float representation (C-style), guaranteed to
+/// evaluate at compile time.
+#[cfg(f128_enabled)]
+#[allow(unused_macros)]
+#[cfg_attr(feature = "unstable-public-internals", macro_export)]
+macro_rules! hf128 {
+    ($s:literal) => {{
+        const X: f128 = $crate::support::hf128($s);
+        X
+    }};
+}
+
+/// Assert `F::biteq` with better messages.
+#[cfg(test)]
+macro_rules! assert_biteq {
+    ($left:expr, $right:expr, $($tt:tt)*) => {{
+        use $crate::support::Int;
+        let l = $left;
+        let r = $right;
+        let bits = Int::leading_zeros(l.to_bits() - l.to_bits()); // hack to get the width from the value
+        assert!(
+            l.biteq(r),
+            "{}\nl: {l:?} ({lb:#0width$x})\nr: {r:?} ({rb:#0width$x})",
+            format_args!($($tt)*),
+            lb = l.to_bits(),
+            rb = r.to_bits(),
+            width = ((bits / 4) + 2) as usize,
+
+        );
+    }};
+    ($left:expr, $right:expr $(,)?) => {
+        assert_biteq!($left, $right, "")
+    };
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/mod.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/mod.rs
new file mode 100644
index 0000000..ee3f2bbd
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/mod.rs
@@ -0,0 +1,29 @@
+#[macro_use]
+pub mod macros;
+mod big;
+mod env;
+mod float_traits;
+pub mod hex_float;
+mod int_traits;
+
+#[allow(unused_imports)]
+pub use big::{i256, u256};
+pub use env::{FpResult, Round, Status};
+#[allow(unused_imports)]
+pub use float_traits::{DFloat, Float, HFloat, IntTy};
+pub(crate) use float_traits::{f32_from_bits, f64_from_bits};
+#[cfg(f16_enabled)]
+#[allow(unused_imports)]
+pub use hex_float::hf16;
+#[cfg(f128_enabled)]
+#[allow(unused_imports)]
+pub use hex_float::hf128;
+#[allow(unused_imports)]
+pub use hex_float::{Hexf, hf32, hf64};
+pub use int_traits::{CastFrom, CastInto, DInt, HInt, Int, MinInt};
+
+/// Hint to the compiler that the current path is cold.
+pub fn cold_path() {
+    #[cfg(intrinsics_enabled)]
+    core::intrinsics::cold_path();
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tan.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tan.rs
index a074ca5..a072bde 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tan.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tan.rs
@@ -53,7 +53,11 @@
         if ix < 0x3e400000 {
             /* |x| < 2**-27 */
             /* raise inexact if x!=0 and underflow if subnormal */
-            force_eval!(if ix < 0x00100000 { x / x1p120 as f64 } else { x + x1p120 as f64 });
+            force_eval!(if ix < 0x00100000 {
+                x / x1p120 as f64
+            } else {
+                x + x1p120 as f64
+            });
             return x;
         }
         return k_tan(x, 0.0, 0);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanf.rs
index 7586aae..8bcf9581 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanf.rs
@@ -42,7 +42,11 @@
         if ix < 0x39800000 {
             /* |x| < 2**-12 */
             /* raise inexact if x!=0 and underflow if subnormal */
-            force_eval!(if ix < 0x00800000 { x / x1p120 } else { x + x1p120 });
+            force_eval!(if ix < 0x00800000 {
+                x / x1p120
+            } else {
+                x + x1p120
+            });
             return x;
         }
         return k_tanf(x64, false);
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgamma.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgamma.rs
index 3f38c0b..3059860 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgamma.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgamma.rs
@@ -45,7 +45,8 @@
         1 => k_cos(x, 0.0),
         2 => k_sin(-x, 0.0, 0),
         3 => -k_cos(x, 0.0),
-        0 | _ => k_sin(x, 0.0, 0),
+        // 0
+        _ => k_sin(x, 0.0, 0),
     }
 }
 
@@ -129,6 +130,7 @@
     return num / den;
 }
 
+/// The [Gamma function](https://en.wikipedia.org/wiki/Gamma_function) (f64).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn tgamma(mut x: f64) -> f64 {
     let u: u64 = x.to_bits();
@@ -143,7 +145,7 @@
     /* special cases */
     if ix >= 0x7ff00000 {
         /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
-        return x + core::f64::INFINITY;
+        return x + f64::INFINITY;
     }
     if ix < ((0x3ff - 54) << 20) {
         /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgammaf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgammaf.rs
index 23e3814f..fe178f7 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgammaf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgammaf.rs
@@ -1,5 +1,6 @@
 use super::tgamma;
 
+/// The [Gamma function](https://en.wikipedia.org/wiki/Gamma_function) (f32).
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn tgammaf(x: f32) -> f32 {
     tgamma(x as f64) as f32
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/trunc.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/trunc.rs
index f7892a2..fa50d55 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/trunc.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/trunc.rs
@@ -1,40 +1,53 @@
-use core::f64;
+/// Rounds the number toward 0 to the closest integral value (f16).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
+#[cfg(f16_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn truncf16(x: f16) -> f16 {
+    super::generic::trunc(x)
+}
 
+/// Rounds the number toward 0 to the closest integral value (f32).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn truncf(x: f32) -> f32 {
+    select_implementation! {
+        name: truncf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
+    }
+
+    super::generic::trunc(x)
+}
+
+/// Rounds the number toward 0 to the closest integral value (f64).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn trunc(x: f64) -> f64 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f64.trunc` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::truncf64(x) }
-        }
+    select_implementation! {
+        name: trunc,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
-    let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120f === 2 ^ 120
 
-    let mut i: u64 = x.to_bits();
-    let mut e: i64 = (i >> 52 & 0x7ff) as i64 - 0x3ff + 12;
-    let m: u64;
+    super::generic::trunc(x)
+}
 
-    if e >= 52 + 12 {
-        return x;
-    }
-    if e < 12 {
-        e = 1;
-    }
-    m = -1i64 as u64 >> e;
-    if (i & m) == 0 {
-        return x;
-    }
-    force_eval!(x + x1p120);
-    i &= !m;
-    f64::from_bits(i)
+/// Rounds the number toward 0 to the closest integral value (f128).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
+#[cfg(f128_enabled)]
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn truncf128(x: f128) -> f128 {
+    super::generic::trunc(x)
 }
 
 #[cfg(test)]
 mod tests {
     #[test]
     fn sanity_check() {
-        assert_eq!(super::trunc(1.1), 1.0);
+        assert_eq!(super::truncf(1.1), 1.0);
     }
 }
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf.rs
index 20d5b73b..14533a2 100644
--- a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf.rs
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf.rs
@@ -1,34 +1,15 @@
-use core::f32;
-
+/// Rounds the number toward 0 to the closest integral value (f32).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
 pub fn truncf(x: f32) -> f32 {
-    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
-    // `f32.trunc` native instruction, so we can leverage this for both code size
-    // and speed.
-    llvm_intrinsically_optimized! {
-        #[cfg(target_arch = "wasm32")] {
-            return unsafe { ::core::intrinsics::truncf32(x) }
-        }
+    select_implementation! {
+        name: truncf,
+        use_arch: all(target_arch = "wasm32", intrinsics_enabled),
+        args: x,
     }
-    let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
 
-    let mut i: u32 = x.to_bits();
-    let mut e: i32 = (i >> 23 & 0xff) as i32 - 0x7f + 9;
-    let m: u32;
-
-    if e >= 23 + 9 {
-        return x;
-    }
-    if e < 9 {
-        e = 1;
-    }
-    m = -1i32 as u32 >> e;
-    if (i & m) == 0 {
-        return x;
-    }
-    force_eval!(x + x1p120);
-    i &= !m;
-    f32::from_bits(i)
+    super::generic::trunc(x)
 }
 
 // PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf128.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf128.rs
new file mode 100644
index 0000000..9dccc0d0
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf128.rs
@@ -0,0 +1,7 @@
+/// Rounds the number toward 0 to the closest integral value (f128).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn truncf128(x: f128) -> f128 {
+    super::generic::trunc(x)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf16.rs b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf16.rs
new file mode 100644
index 0000000..d7c3d22
--- /dev/null
+++ b/third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf16.rs
@@ -0,0 +1,7 @@
+/// Rounds the number toward 0 to the closest integral value (f16).
+///
+/// This effectively removes the decimal part of the number, leaving the integral part.
+#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
+pub fn truncf16(x: f16) -> f16 {
+    super::generic::trunc(x)
+}
diff --git a/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/Cargo.toml
index 0fe329d3..825df40 100644
--- a/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'link-cplusplus' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `link-cplusplus-1.0.10` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "link-cplusplus"
diff --git a/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/src/lib.rs
index 68ce2814..71a9b15a 100644
--- a/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/link-cplusplus-v1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'link-cplusplus' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `link-cplusplus-1.0.10` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/once_cell-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/once_cell-v1/Cargo.toml
index 2f5881a2..bbf30770 100644
--- a/third_party/rust/chromium_crates_io/vendor/once_cell-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/once_cell-v1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'once_cell' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `once_cell-1.21.3` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "once_cell"
diff --git a/third_party/rust/chromium_crates_io/vendor/once_cell-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/once_cell-v1/src/lib.rs
index b16d08ae..89b6b9d 100644
--- a/third_party/rust/chromium_crates_io/vendor/once_cell-v1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/once_cell-v1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'once_cell' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `once_cell-1.21.3` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/shlex-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/shlex-v1/Cargo.toml
index 54b1438..47d30c4 100644
--- a/third_party/rust/chromium_crates_io/vendor/shlex-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/shlex-v1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'shlex' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `shlex-1.3.0` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "shlex"
diff --git a/third_party/rust/chromium_crates_io/vendor/shlex-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/shlex-v1/src/lib.rs
index d425f96..a0989d8 100644
--- a/third_party/rust/chromium_crates_io/vendor/shlex-v1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/shlex-v1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'shlex' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `shlex-1.3.0` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/Cargo.toml
index 03cbf3ef..d099afd4 100644
--- a/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'unicode-bidi' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `unicode-bidi-0.3.18` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "unicode-bidi"
diff --git a/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/src/lib.rs
index 6f30a1a..1c5c78a 100644
--- a/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/unicode-bidi-v0_3/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'unicode-bidi' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `unicode-bidi-0.3.18` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/Cargo.toml
index 1e69fb1..6e48c1e4 100644
--- a/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'utf16_iter' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `utf16_iter-1.0.5` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "utf16_iter"
diff --git a/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/src/lib.rs
index 5251867..88f82151 100644
--- a/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/utf16_iter-v1/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'utf16_iter' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `utf16_iter-1.0.5` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/Cargo.toml
index 203e33d..e1769c0 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'wasm-bindgen-backend' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `wasm-bindgen-backend-0.2.100` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "wasm-bindgen-backend"
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/src/lib.rs
index 2c596b8..6b7983f 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-backend-v0_2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'wasm-bindgen-backend' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `wasm-bindgen-backend-0.2.100` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/Cargo.toml
index d05da41..9e52d59 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'wasm-bindgen-macro-support' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `wasm-bindgen-macro-support-0.2.100` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "wasm-bindgen-macro-support"
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/src/lib.rs
index 742d070cb..c291376 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-support-v0_2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'wasm-bindgen-macro-support' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `wasm-bindgen-macro-support-0.2.100` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/Cargo.toml
index ea4baea..69a7fb2 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'wasm-bindgen-macro' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `wasm-bindgen-macro-0.2.100` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "wasm-bindgen-macro"
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/src/lib.rs
index 76f01355..7d8c8a3 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-macro-v0_2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'wasm-bindgen-macro' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `wasm-bindgen-macro-0.2.100` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/Cargo.toml
index 9a9a8b5..1f7c7de 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'wasm-bindgen-shared' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `wasm-bindgen-shared-0.2.100` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "wasm-bindgen-shared"
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/src/lib.rs
index c4d22b8c..36e604a 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-shared-v0_2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'wasm-bindgen-shared' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `wasm-bindgen-shared-0.2.100` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/Cargo.toml
index de89dd9..eb91ea6 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'wasm-bindgen' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `wasm-bindgen-0.2.100` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "wasm-bindgen"
diff --git a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/src/lib.rs
index 0057617..7cc63cb 100644
--- a/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/wasm-bindgen-v0_2/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'wasm-bindgen' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `wasm-bindgen-0.2.100` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/Cargo.toml
index 590d5c21..0cf8680 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'windows_aarch64_gnullvm' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `windows_aarch64_gnullvm-0.52.6` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "windows_aarch64_gnullvm"
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/src/lib.rs
index 4f1e985..20148006 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/windows_aarch64_gnullvm-v0_52/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'windows_aarch64_gnullvm' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `windows_aarch64_gnullvm-0.52.6` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/Cargo.toml
index f40f42e9..a604325 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'windows_i686_gnu' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `windows_i686_gnu-0.52.6` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "windows_i686_gnu"
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/src/lib.rs
index 33de7e5..cbae8a7 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnu-v0_52/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'windows_i686_gnu' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `windows_i686_gnu-0.52.6` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/Cargo.toml
index d99f21f9b..7e1be09 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'windows_i686_gnullvm' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `windows_i686_gnullvm-0.52.6` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "windows_i686_gnullvm"
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/src/lib.rs
index 724dfca3..d868617 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/windows_i686_gnullvm-v0_52/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'windows_i686_gnullvm' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `windows_i686_gnullvm-0.52.6` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/Cargo.toml
index 658856ef..2db6179 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'windows_x86_64_gnu' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `windows_x86_64_gnu-0.52.6` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "windows_x86_64_gnu"
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/src/lib.rs
index ecc632f..3953b514 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnu-v0_52/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'windows_x86_64_gnu' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `windows_x86_64_gnu-0.52.6` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/Cargo.toml
index d9edb79..d421963fc 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/Cargo.toml
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the 'windows_x86_64_gnullvm' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `windows_x86_64_gnullvm-0.52.6` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "windows_x86_64_gnullvm"
diff --git a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/src/lib.rs
index 04e7b0d..be91129 100644
--- a/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/src/lib.rs
+++ b/third_party/rust/chromium_crates_io/vendor/windows_x86_64_gnullvm-v0_52/src/lib.rs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the 'windows_x86_64_gnullvm' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `windows_x86_64_gnullvm-0.52.6` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/rust/libc/v0_2/BUILD.gn b/third_party/rust/libc/v0_2/BUILD.gn
index acd7b0ff..d461faf0 100644
--- a/third_party/rust/libc/v0_2/BUILD.gn
+++ b/third_party/rust/libc/v0_2/BUILD.gn
@@ -200,7 +200,7 @@
 
   build_native_rust_unit_tests = false
   edition = "2021"
-  cargo_pkg_version = "0.2.171"
+  cargo_pkg_version = "0.2.172"
   cargo_pkg_authors = "The Rust Project Developers"
   cargo_pkg_name = "libc"
   cargo_pkg_description = "Raw FFI bindings to platform libraries like libc."
diff --git a/third_party/rust/libc/v0_2/README.chromium b/third_party/rust/libc/v0_2/README.chromium
index 24ea5ae..07a3567 100644
--- a/third_party/rust/libc/v0_2/README.chromium
+++ b/third_party/rust/libc/v0_2/README.chromium
@@ -1,7 +1,7 @@
 Name: libc
 URL: https://crates.io/crates/libc
-Version: 0.2.171
-Revision: 78b0f8a7397e177ff487f1a70a22a67ae5638f72
+Version: 0.2.172
+Revision: a5eab581f9c9c03f29e3edd4a4d4f850d748f2e9
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/libc-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/libm/v0_2/BUILD.gn b/third_party/rust/libm/v0_2/BUILD.gn
index 098cf75..2675cef8 100644
--- a/third_party/rust/libm/v0_2/BUILD.gn
+++ b/third_party/rust/libm/v0_2/BUILD.gn
@@ -21,6 +21,11 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acosh.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/acoshf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/aarch64.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i586.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/i686.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/mod.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/arch/wasm32.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asin.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/asinh.rs",
@@ -34,9 +39,10 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrt.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cbrtf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceil.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ceilf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysign.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/copysignf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cos.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cosf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/cosh.rs",
@@ -54,21 +60,45 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/expo2.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabs.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fabsf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdim.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fenv.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fdimf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floor.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/floorf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaf.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmax.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmaxf.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fma_wide.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmin_fmax.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fminimum_fmaximum_num.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmod.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/fmodf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexp.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/frexpf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/ceil.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/copysign.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fabs.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fdim.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/floor.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmax.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmaximum_num.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmin.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fminimum_num.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/fmod.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/mod.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/rint.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/round.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/scalbn.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/sqrt.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/generic/trunc.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/hypot.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/hypotf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ilogb.rs",
@@ -89,6 +119,8 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/k_tanf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexp.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/ldexpf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgamma_r.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/lgammaf.rs",
@@ -116,11 +148,15 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/remquo.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/remquof.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rint.rs",
-    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/rintf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/round.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundeven.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/roundf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbn.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/scalbnf16.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sin.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincos.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sincosf.rs",
@@ -129,6 +165,16 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sinhf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrt.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/sqrtf16.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/big/tests.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/env.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/float_traits.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/hex_float.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/int_traits.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/macros.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/support/mod.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tan.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tanh.rs",
@@ -137,12 +183,14 @@
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/tgammaf.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/trunc.rs",
     "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf128.rs",
+    "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/src/math/truncf16.rs",
   ]
   inputs = []
 
   build_native_rust_unit_tests = false
   edition = "2021"
-  cargo_pkg_version = "0.2.11"
+  cargo_pkg_version = "0.2.13"
   cargo_pkg_authors = "Jorge Aparicio <jorge@japaric.io>"
   cargo_pkg_name = "libm"
   cargo_pkg_description = "libm in pure Rust"
@@ -153,7 +201,10 @@
   executable_configs += [ "//build/config/compiler:no_chromium_code" ]
   proc_macro_configs -= [ "//build/config/compiler:chromium_code" ]
   proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ]
-  features = [ "default" ]
+  features = [
+    "arch",
+    "default",
+  ]
   build_root = "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs"
   build_sources =
       [ "//third_party/rust/chromium_crates_io/vendor/libm-v0_2/build.rs" ]
diff --git a/third_party/rust/libm/v0_2/README.chromium b/third_party/rust/libm/v0_2/README.chromium
index 8553c43..01802cf 100644
--- a/third_party/rust/libm/v0_2/README.chromium
+++ b/third_party/rust/libm/v0_2/README.chromium
@@ -1,8 +1,8 @@
 Name: libm
 URL: https://crates.io/crates/libm
-Version: 0.2.11
-Revision: cdbf42389e40e15350745cc29e86cd5d93cb2a76
-License: Apache-2.0
+Version: 0.2.13
+Revision: 0bdef053a00a5a17722733c550606ad15d62cea6
+License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/libm-v0_2/LICENSE.txt
 Shipped: yes
 Security Critical: yes
diff --git a/third_party/skia b/third_party/skia
index e5dcffd..1161451 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit e5dcffd10068cddca18339825f2c00f95e51a385
+Subproject commit 1161451d903b47647c31aa0b463623ff58071b56
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src
index b6a8322..8e9165a 160000
--- a/third_party/spirv-tools/src
+++ b/third_party/spirv-tools/src
@@ -1 +1 @@
-Subproject commit b6a83226d75d15b1733d35ee9e26b8f895ecffcb
+Subproject commit 8e9165a3d162967a424dcf2ff645a98b50381cce
diff --git a/third_party/swiftshader b/third_party/swiftshader
index 0e75e70..7545980 160000
--- a/third_party/swiftshader
+++ b/third_party/swiftshader
@@ -1 +1 @@
-Subproject commit 0e75e7030ccbd9d1d7354bd6df68ae4b59acf4a0
+Subproject commit 7545980c939d086da9021c2e51975d1b3eb4eb71
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index b9aab6c..96793fb0 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit b9aab6c35f37e6532011ddab976c3ca71819c074
+Subproject commit 96793fb0ff6fb5d4328cc6f71d84f5cb2d835daf
diff --git a/third_party/vulkan-headers/src b/third_party/vulkan-headers/src
index 409c16b..e2e53a7 160000
--- a/third_party/vulkan-headers/src
+++ b/third_party/vulkan-headers/src
@@ -1 +1 @@
-Subproject commit 409c16be502e39fe70dd6fe2d9ad4842ef2c9a53
+Subproject commit e2e53a724677f6eba8ff0ce1ccb64ee321785cbd
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 6530df5..cea6ec1 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 6530df51e0db74d50241c3a0f2c2798e99d0d9dd
+Subproject commit cea6ec1cdd37494c1f0fc5619c6c356ac33372fb
diff --git a/third_party/webrtc b/third_party/webrtc
index de7866f..41051bb 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit de7866f6cab90d0dc7279cde6c2560fcae90c2d3
+Subproject commit 41051bb035492367ec74795db9eada3321d1ef98
diff --git a/third_party/zlib/CMakeLists.txt b/third_party/zlib/CMakeLists.txt
index ebf9cd4..b085ab8 100644
--- a/third_party/zlib/CMakeLists.txt
+++ b/third_party/zlib/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 project(zlib C)
 
-set(VERSION "1.3.0.1")
+set(VERSION "1.3.1")
 
 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
 set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
@@ -267,7 +267,9 @@
 endif(MINGW)
 
 add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
 set_target_properties(zlib PROPERTIES SOVERSION 1)
 
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c
index 49496bb..1d4c688 100644
--- a/third_party/zlib/deflate.c
+++ b/third_party/zlib/deflate.c
@@ -1,5 +1,5 @@
 /* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -69,7 +69,7 @@
 #endif
 
 const char deflate_copyright[] =
-   " deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
+   " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -1663,13 +1663,21 @@
  */
 local void check_match(deflate_state *s, IPos start, IPos match, int length) {
     /* check that the match is indeed a match */
-    if (zmemcmp(s->window + match,
-                s->window + start, length) != EQUAL) {
-        fprintf(stderr, " start %u, match %u, length %d\n",
-                start, match, length);
+    Bytef *back = s->window + (int)match, *here = s->window + start;
+    IPos len = length;
+    if (match == (IPos)-1) {
+        /* match starts one byte before the current window -- just compare the
+           subsequent length-1 bytes */
+        back++;
+        here++;
+        len--;
+    }
+    if (zmemcmp(back, here, len) != EQUAL) {
+        fprintf(stderr, " start %u, match %d, length %d\n",
+                start, (int)match, length);
         do {
-            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
-        } while (--length != 0);
+            fprintf(stderr, "(%02x %02x)", *back++, *here++);
+        } while (--len != 0);
         z_error("invalid match");
     }
     if (z_verbose > 1) {
diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h
index 099d359..2d5eaab 100644
--- a/third_party/zlib/deflate.h
+++ b/third_party/zlib/deflate.h
@@ -1,5 +1,5 @@
 /* deflate.h -- internal compression state
- * Copyright (C) 1995-2018 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
diff --git a/third_party/zlib/gzguts.h b/third_party/zlib/gzguts.h
index adc2b34..eba7208 100644
--- a/third_party/zlib/gzguts.h
+++ b/third_party/zlib/gzguts.h
@@ -1,5 +1,5 @@
 /* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004-2019 Mark Adler
+ * Copyright (C) 2004-2024 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
diff --git a/third_party/zlib/gzlib.c b/third_party/zlib/gzlib.c
index 7258cae..7136395 100644
--- a/third_party/zlib/gzlib.c
+++ b/third_party/zlib/gzlib.c
@@ -1,5 +1,5 @@
 /* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004-2019 Mark Adler
+ * Copyright (C) 2004-2024 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
diff --git a/third_party/zlib/inftrees.c b/third_party/zlib/inftrees.c
index 73d5a77..98cfe16 100644
--- a/third_party/zlib/inftrees.c
+++ b/third_party/zlib/inftrees.c
@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2023 Mark Adler
+ * Copyright (C) 1995-2024 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.3.0.1 Copyright 1995-2023 Mark Adler ";
+   " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -57,7 +57,7 @@
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 70, 200};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         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,
diff --git a/third_party/zlib/trees.c b/third_party/zlib/trees.c
index 3813527..62286af 100644
--- a/third_party/zlib/trees.c
+++ b/third_party/zlib/trees.c
@@ -1,5 +1,5 @@
 /* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2021 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
  * detect_data_type() function provided freely by Cosmin Truta, 2006
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
diff --git a/third_party/zlib/zconf.h b/third_party/zlib/zconf.h
index 55fe101..b76ded42 100644
--- a/third_party/zlib/zconf.h
+++ b/third_party/zlib/zconf.h
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -312,14 +312,6 @@
 #  endif
 #endif
 
-#ifndef Z_ARG /* function prototypes for stdarg */
-#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#    define Z_ARG(args)  args
-#  else
-#    define Z_ARG(args)  ()
-#  endif
-#endif
-
 /* The following definitions for FAR are needed only for MSDOS mixed
  * model programming (small or medium model with some far allocations).
  * This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/third_party/zlib/zconf.h.cmakein b/third_party/zlib/zconf.h.cmakein
index 310c4392..0abe3bc 100644
--- a/third_party/zlib/zconf.h.cmakein
+++ b/third_party/zlib/zconf.h.cmakein
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -302,14 +302,6 @@
 #  endif
 #endif
 
-#ifndef Z_ARG /* function prototypes for stdarg */
-#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#    define Z_ARG(args)  args
-#  else
-#    define Z_ARG(args)  ()
-#  endif
-#endif
-
 /* The following definitions for FAR are needed only for MSDOS mixed
  * model programming (small or medium model with some far allocations).
  * This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/third_party/zlib/zconf.h.in b/third_party/zlib/zconf.h.in
index fb76ffe..62adc8d84 100644
--- a/third_party/zlib/zconf.h.in
+++ b/third_party/zlib/zconf.h.in
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -300,14 +300,6 @@
 #  endif
 #endif
 
-#ifndef Z_ARG /* function prototypes for stdarg */
-#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
-#    define Z_ARG(args)  args
-#  else
-#    define Z_ARG(args)  ()
-#  endif
-#endif
-
 /* The following definitions for FAR are needed only for MSDOS mixed
  * model programming (small or medium model with some far allocations).
  * This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/third_party/zlib/zlib.3 b/third_party/zlib/zlib.3
index adc5b7f..c716020e 100644
--- a/third_party/zlib/zlib.3
+++ b/third_party/zlib/zlib.3
@@ -1,4 +1,4 @@
-.TH ZLIB 3 "xx Aug 2023"
+.TH ZLIB 3 "22 Jan 2024"
 .SH NAME
 zlib \- compression/decompression library
 .SH SYNOPSIS
@@ -105,9 +105,9 @@
 Send questions and/or comments to zlib@gzip.org,
 or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
 .SH AUTHORS AND LICENSE
-Version 1.2.3.0.1
+Version 1.3.1
 .LP
-Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
 .LP
 This software is provided 'as-is', without any express or implied
 warranty.  In no event will the authors be held liable for any damages
diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h
index e2c920f..8b2f6c1d 100644
--- a/third_party/zlib/zlib.h
+++ b/third_party/zlib/zlib.h
@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.3.0.1, August xxth, 2023
+  version 1.3.1, January 22nd, 2024
 
-  Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -37,12 +37,12 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.3.0.1-motley"
-#define ZLIB_VERNUM 0x1301
+#define ZLIB_VERSION "1.3.1"
+#define ZLIB_VERNUM 0x1310
 #define ZLIB_VER_MAJOR 1
 #define ZLIB_VER_MINOR 3
-#define ZLIB_VER_REVISION 0
-#define ZLIB_VER_SUBREVISION 1
+#define ZLIB_VER_REVISION 1
+#define ZLIB_VER_SUBREVISION 0
 
 /*
     The 'zlib' compression library provides in-memory compression and
diff --git a/third_party/zlib/zlib.map b/third_party/zlib/zlib.map
index b330b60..31544f2e 100644
--- a/third_party/zlib/zlib.map
+++ b/third_party/zlib/zlib.map
@@ -1,100 +1,100 @@
-ZLIB_1.2.0 {

-  global:

-    compressBound;

-    deflateBound;

-    inflateBack;

-    inflateBackEnd;

-    inflateBackInit_;

-    inflateCopy;

-  local:

-    deflate_copyright;

-    inflate_copyright;

-    inflate_fast;

-    inflate_table;

-    zcalloc;

-    zcfree;

-    z_errmsg;

-    gz_error;

-    gz_intmax;

-    _*;

-};

-

-ZLIB_1.2.0.2 {

-    gzclearerr;

-    gzungetc;

-    zlibCompileFlags;

-} ZLIB_1.2.0;

-

-ZLIB_1.2.0.8 {

-    deflatePrime;

-} ZLIB_1.2.0.2;

-

-ZLIB_1.2.2 {

-    adler32_combine;

-    crc32_combine;

-    deflateSetHeader;

-    inflateGetHeader;

-} ZLIB_1.2.0.8;

-

-ZLIB_1.2.2.3 {

-    deflateTune;

-    gzdirect;

-} ZLIB_1.2.2;

-

-ZLIB_1.2.2.4 {

-    inflatePrime;

-} ZLIB_1.2.2.3;

-

-ZLIB_1.2.3.3 {

-    adler32_combine64;

-    crc32_combine64;

-    gzopen64;

-    gzseek64;

-    gztell64;

-    inflateUndermine;

-} ZLIB_1.2.2.4;

-

-ZLIB_1.2.3.4 {

-    inflateReset2;

-    inflateMark;

-} ZLIB_1.2.3.3;

-

-ZLIB_1.2.3.5 {

-    gzbuffer;

-    gzoffset;

-    gzoffset64;

-    gzclose_r;

-    gzclose_w;

-} ZLIB_1.2.3.4;

-

-ZLIB_1.2.5.1 {

-    deflatePending;

-} ZLIB_1.2.3.5;

-

-ZLIB_1.2.5.2 {

-    deflateResetKeep;

-    gzgetc_;

-    inflateResetKeep;

-} ZLIB_1.2.5.1;

-

-ZLIB_1.2.7.1 {

-    inflateGetDictionary;

-    gzvprintf;

-} ZLIB_1.2.5.2;

-

-ZLIB_1.2.9 {

-    inflateCodesUsed;

-    inflateValidate;

-    uncompress2;

-    gzfread;

-    gzfwrite;

-    deflateGetDictionary;

-    adler32_z;

-    crc32_z;

-} ZLIB_1.2.7.1;

-

-ZLIB_1.2.12 {

-	crc32_combine_gen;

-	crc32_combine_gen64;

-	crc32_combine_op;

-} ZLIB_1.2.9;

+ZLIB_1.2.0 {
+  global:
+    compressBound;
+    deflateBound;
+    inflateBack;
+    inflateBackEnd;
+    inflateBackInit_;
+    inflateCopy;
+  local:
+    deflate_copyright;
+    inflate_copyright;
+    inflate_fast;
+    inflate_table;
+    zcalloc;
+    zcfree;
+    z_errmsg;
+    gz_error;
+    gz_intmax;
+    _*;
+};
+
+ZLIB_1.2.0.2 {
+    gzclearerr;
+    gzungetc;
+    zlibCompileFlags;
+} ZLIB_1.2.0;
+
+ZLIB_1.2.0.8 {
+    deflatePrime;
+} ZLIB_1.2.0.2;
+
+ZLIB_1.2.2 {
+    adler32_combine;
+    crc32_combine;
+    deflateSetHeader;
+    inflateGetHeader;
+} ZLIB_1.2.0.8;
+
+ZLIB_1.2.2.3 {
+    deflateTune;
+    gzdirect;
+} ZLIB_1.2.2;
+
+ZLIB_1.2.2.4 {
+    inflatePrime;
+} ZLIB_1.2.2.3;
+
+ZLIB_1.2.3.3 {
+    adler32_combine64;
+    crc32_combine64;
+    gzopen64;
+    gzseek64;
+    gztell64;
+    inflateUndermine;
+} ZLIB_1.2.2.4;
+
+ZLIB_1.2.3.4 {
+    inflateReset2;
+    inflateMark;
+} ZLIB_1.2.3.3;
+
+ZLIB_1.2.3.5 {
+    gzbuffer;
+    gzoffset;
+    gzoffset64;
+    gzclose_r;
+    gzclose_w;
+} ZLIB_1.2.3.4;
+
+ZLIB_1.2.5.1 {
+    deflatePending;
+} ZLIB_1.2.3.5;
+
+ZLIB_1.2.5.2 {
+    deflateResetKeep;
+    gzgetc_;
+    inflateResetKeep;
+} ZLIB_1.2.5.1;
+
+ZLIB_1.2.7.1 {
+    inflateGetDictionary;
+    gzvprintf;
+} ZLIB_1.2.5.2;
+
+ZLIB_1.2.9 {
+    inflateCodesUsed;
+    inflateValidate;
+    uncompress2;
+    gzfread;
+    gzfwrite;
+    deflateGetDictionary;
+    adler32_z;
+    crc32_z;
+} ZLIB_1.2.7.1;
+
+ZLIB_1.2.12 {
+	crc32_combine_gen;
+	crc32_combine_gen64;
+	crc32_combine_op;
+} ZLIB_1.2.9;
diff --git a/third_party/zlib/zutil.h b/third_party/zlib/zutil.h
index 7155090..045a35a4f 100644
--- a/third_party/zlib/zutil.h
+++ b/third_party/zlib/zutil.h
@@ -1,5 +1,5 @@
 /* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index b1a37f7..8f419c4 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -36,7 +36,7 @@
 # https://chromium.googlesource.com/chromium/src/+/main/docs/updating_clang.md
 # Reverting problematic clang rolls is safe, though.
 # This is the output of `git describe` and is usable as a commit-ish.
-CLANG_REVISION = 'llvmorg-21-init-6681-g5b36835d'
+CLANG_REVISION = 'llvmorg-21-init-9266-g09006611'
 CLANG_SUB_REVISION = 1
 
 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/crates/gnrt/removed_Cargo.toml.hbs b/tools/crates/gnrt/removed_Cargo.toml.hbs
index 89e03ee..63877e2 100644
--- a/tools/crates/gnrt/removed_Cargo.toml.hbs
+++ b/tools/crates/gnrt/removed_Cargo.toml.hbs
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# @generated from third_party/rust/chromium_crates_io/removed_Cargo.toml
-# by tools/crates/gnrt. Do not edit!
-
-# This is an empty crate that has replaced the '{{this.name}}' crate, since
-# it was listed in `resolve.remove_crates` in gnrt_config.toml.
+# @generated from `tools/crates/gnrt/removed_Cargo.toml.hbs`
+# by `tools/crates/run_gnrt.py vendor`. Do not edit!
+#
+# This is an empty placeholder that has replaced the
+# `{{this.name}}-{{this.version}}` crate.
+#
+# See `//tools/crates/gnrt/removed_crate.md` to learn more.
 
 [package]
 name = "{{this.name}}"
diff --git a/tools/crates/gnrt/removed_crate.md b/tools/crates/gnrt/removed_crate.md
new file mode 100644
index 0000000..6e11df2
--- /dev/null
+++ b/tools/crates/gnrt/removed_crate.md
@@ -0,0 +1,19 @@
+# Placeholder crates
+
+In some circumstances `tools/crates/run_gnrt.py vendor` will *not* vendor an
+actual crate.  When Chromium doesn't really depend on a given crate, then a
+placeholder crate will be generated instead.  This typically happens when
+either:
+
+* The crate is a conditional dependency that is:
+     - Only present on certain target platforms (ones not supported by
+       Chromium build system as determined by
+       `tools/crates/gnrt/condition.rs`)
+     - Only present if certain crate features are enabled (ones determined to
+       be disabled in Chromium after crate feature resolution performed by
+       `gnrt`, `guppy`, and `cargo`)
+* or `gnrt_config.toml` asked to remove the crate (e.g. via
+  `remove_crates` entry of `gnrt_config.toml`)
+
+`gnrt` generates a placeholder crate, because otherwise `cargo metadata`,
+`cargo tree`, and other `cargo` commands wouldn't work.
diff --git a/tools/crates/gnrt/removed_lib.rs.hbs b/tools/crates/gnrt/removed_lib.rs.hbs
index 7ddce45..fae9e7c 100644
--- a/tools/crates/gnrt/removed_lib.rs.hbs
+++ b/tools/crates/gnrt/removed_lib.rs.hbs
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @generated from third_party/rust/chromium_crates_io/removed_lib.rs
-// by tools/crates/gnrt. Do not edit!
-
-// This is an empty crate that has replaced the '{{this.name}}' crate, since
-// it was listed in `resolve.remove_crates` in gnrt_config.toml.
+// @generated from `tools/crates/gnrt/removed_lib.rs.hbs`
+// by `tools/crates/run_gnrt.py vendor`. Do not edit!
+//
+// This is an empty placeholder that has replaced the
+// `{{this.name}}-{{this.version}}` crate.
+//
+// See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index ccad6f8..bba8a67c 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -48629,6 +48629,8 @@
       label="For password management bubble during signin feature."/>
   <suffix name="PasswordsSavePrimingPromo"
       label="For password save priming promo."/>
+  <suffix name="PasswordsSaveRecoveryPromo"
+      label="For password save recovery promo."/>
   <suffix name="PasswordSuggestions" label="For PasswordSuggestions feature."/>
   <suffix name="PasswordsWebAppProfileSwitch"
       label="For PasswordsWebAppProfileSwitch feature."/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c66a8437..60117e690 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -8861,6 +8861,8 @@
   <int value="-2087444854" label="ThreadWrapperUsesMetronome:disabled"/>
   <int value="-2086690409"
       label="EnableExtensionsPermissionsForSupervisedUsersOnDesktop:enabled"/>
+  <int value="-2086547119"
+      label="ReportNotificationContentDetectionData:disabled"/>
   <int value="-2086380381" label="FedCmIdpSigninStatusEnabled:disabled"/>
   <int value="-2085842174" label="SupportF11AndF12KeyShortcuts:enabled"/>
   <int value="-2085212970" label="FastPairHID:enabled"/>
@@ -10722,6 +10724,8 @@
   <int value="-1388956102" label="OmniboxTouchDownTriggerForPrefetch:disabled"/>
   <int value="-1388817073" label="OmniboxReverseAnswers:disabled"/>
   <int value="-1388546778" label="WebAppManifestImmediateUpdating:disabled"/>
+  <int value="-1388233453"
+      label="UseFrameIntervalDeciderAdaptiveFrameRate:enabled"/>
   <int value="-1388044691" label="ContentLanguagesInLanguagePicker:enabled"/>
   <int value="-1387498034"
       label="SafeBrowsingPasswordCheckIntegrationForSavedPasswordsAndroid:enabled"/>
@@ -11702,6 +11706,8 @@
   <int value="-1015006759" label="ImportantSitesInCBD:disabled"/>
   <int value="-1014936248" label="SyncUSSBookmarks:enabled"/>
   <int value="-1014649471" label="committed-interstitials"/>
+  <int value="-1014147857"
+      label="ReportNotificationContentDetectionData:enabled"/>
   <int value="-1013986101" label="FirstScrollLatencyMeasurement:disabled"/>
   <int value="-1012816526"
       label="FileSystemAccessGetCloudIdentifiers:disabled"/>
@@ -11722,6 +11728,8 @@
   <int value="-1007267652"
       label="NtpPhotosModuleCustomizedOptInArtWork:disabled"/>
   <int value="-1007219628" label="IncreasedCmdBufferParseSlice:enabled"/>
+  <int value="-1006553558"
+      label="UseFrameIntervalDeciderAdaptiveFrameRate:disabled"/>
   <int value="-1006508846" label="AutofillEnableCardBenefitsForBmo:disabled"/>
   <int value="-1005937042" label="ArcVmBalloonPolicy:enabled"/>
   <int value="-1005164075" label="ContextualSearchTranslations:enabled"/>
diff --git a/tools/metrics/histograms/histograms_xml_files.gni b/tools/metrics/histograms/histograms_xml_files.gni
index 3c2d2bee..1eef44c 100644
--- a/tools/metrics/histograms/histograms_xml_files.gni
+++ b/tools/metrics/histograms/histograms_xml_files.gni
@@ -199,6 +199,7 @@
   "//tools/metrics/histograms/metadata/plugin_vm/histograms.xml",
   "//tools/metrics/histograms/metadata/plus_addresses/enums.xml",
   "//tools/metrics/histograms/metadata/plus_addresses/histograms.xml",
+  "//tools/metrics/histograms/metadata/power/enums.xml",
   "//tools/metrics/histograms/metadata/power/histograms.xml",
   "//tools/metrics/histograms/metadata/prefetch/histograms.xml",
   "//tools/metrics/histograms/metadata/preloading/histograms.xml",
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index a06f9a5..fbb927d 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -124,6 +124,8 @@
   <variant name="CreditCard"
       summary="User chose to fill a form or field with a credit card profile."/>
   <variant name="Iban" summary="User chose to fill a field with an iban."/>
+  <variant name="IdentityCredential"
+      summary="User chose to fill a field with an identity credential."/>
   <variant name="LoyaltyCard"
       summary="User chose to fill a field with a loyalty card."/>
   <variant name="MerchantPromoCode"
diff --git a/tools/metrics/histograms/metadata/enterprise/enums.xml b/tools/metrics/histograms/metadata/enterprise/enums.xml
index dce951cf..264e740 100644
--- a/tools/metrics/histograms/metadata/enterprise/enums.xml
+++ b/tools/metrics/histograms/metadata/enterprise/enums.xml
@@ -2226,6 +2226,7 @@
   <int value="1355" label="DefaultSmartCardConnectSetting"/>
   <int value="1356" label="DeviceUserInitiatedFirmwareUpdate"/>
   <int value="1357" label="BuiltInAIAPIsEnabled"/>
+  <int value="1358" label="TabGroupSharingSettings"/>
 </enum>
 
 <enum name="EnterprisePoliciesSources">
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index b728db9..b867d32 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -415,6 +415,8 @@
                during signin flows"/>
   <variant name="IPH_PasswordsSavePrimingPromo"
       summary="prompting users to consider saving passwords in the browser"/>
+  <variant name="IPH_PasswordsSaveRecoveryPromo"
+      summary="prompting users to reconsider saving passwords in the browser"/>
   <variant name="IPH_PasswordSuggestions"
       summary="the Autofill password suggestions on iOS"/>
   <variant name="IPH_PasswordsWebAppProfileSwitch"
diff --git a/tools/metrics/histograms/metadata/gpu/enums.xml b/tools/metrics/histograms/metadata/gpu/enums.xml
index 55ebb8f..2aee09d9 100644
--- a/tools/metrics/histograms/metadata/gpu/enums.xml
+++ b/tools/metrics/histograms/metadata/gpu/enums.xml
@@ -434,6 +434,8 @@
   <int value="3" label="kVideoConference"/>
   <int value="4" label="kOnlyAnimatingImage"/>
   <int value="5" label="kOnlyScrollBarFadeOut"/>
+  <int value="6" label="kUserInputBoost"/>
+  <int value="7" label="kSlowScrollThrottle"/>
 </enum>
 
 <enum name="GLImplementation">
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index d3f5ba1..fa802427 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -2003,6 +2003,16 @@
   </summary>
 </histogram>
 
+<histogram name="History.Embeddings.Embedder.LaunchDuration" units="ms"
+    expires_after="2025-10-05">
+  <owner>wittman@chromium.org</owner>
+  <owner>src/components/history_embeddings/OWNERS</owner>
+  <summary>
+    The time it took to launch the PassageEmbeddingsService. Logged each time
+    the service is successfully launched.
+  </summary>
+</histogram>
+
 <histogram name="History.Embeddings.Embedder.ModelInfoStatus"
     enum="EmbeddingsModelInfoStatus" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
@@ -2441,6 +2451,38 @@
   </summary>
 </histogram>
 
+<histogram name="History.Embeddings.TaskDuration" units="ms"
+    expires_after="2025-10-05">
+  <owner>wittman@chromium.org</owner>
+  <owner>src/components/history_embeddings/OWNERS</owner>
+  <summary>
+    The time it took to compute embeddings for one service round trip. Logged
+    each time the embeddings are successfully computed.
+  </summary>
+</histogram>
+
+<histogram name="History.Embeddings.TaskDuration.Passive" units="ms"
+    expires_after="2025-10-05">
+  <owner>wittman@chromium.org</owner>
+  <owner>src/components/history_embeddings/OWNERS</owner>
+  <summary>
+    The time it took to compute embeddings with kPassive priority, for one
+    service round trip. Logged each time the embeddings are successfully
+    computed.
+  </summary>
+</histogram>
+
+<histogram name="History.Embeddings.TaskDuration.UserInitiated" units="ms"
+    expires_after="2025-10-05">
+  <owner>wittman@chromium.org</owner>
+  <owner>src/components/history_embeddings/OWNERS</owner>
+  <summary>
+    The time it took to compute embeddings with kUserInitiated priority, for one
+    service round trip. Logged each time the embeddings are successfully
+    computed.
+  </summary>
+</histogram>
+
 <histogram name="History.Embeddings.UserActions{UiSurface}"
     enum="EmbeddingsUserActions" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/linux/histograms.xml b/tools/metrics/histograms/metadata/linux/histograms.xml
index 1f28fc8..c8ea6076 100644
--- a/tools/metrics/histograms/metadata/linux/histograms.xml
+++ b/tools/metrics/histograms/metadata/linux/histograms.xml
@@ -163,6 +163,13 @@
   </summary>
 </histogram>
 
+<histogram name="Linux.X11.XInput2" enum="BooleanEnabled"
+    expires_after="2025-10-21">
+  <owner>aycyang@chromium.org</owner>
+  <owner>thomasanderson@chromium.org</owner>
+  <summary>Whether X Input Extension version 2.x is available.</summary>
+</histogram>
+
 </histograms>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 61c52a0..a994fc20a 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -3243,6 +3243,23 @@
   </token>
 </histogram>
 
+<histogram name="Net.IpProtection.CanFalloverToNextProxy.Error.{Chain}"
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2025-11-28">
+  <owner>rsailer@chromium.org</owner>
+  <owner>src/components/ip_protection/OWNERS</owner>
+  <summary>
+    Records the error code passed to CanFalloverToNextProxy() for IP Protection
+    proxy chains. This function is called when a proxy fails, and the error code
+    is used to determine whether to try the next proxy in the chain or not.
+  </summary>
+  <token key="Chain">
+    <variant name="Chain0"/>
+    <variant name="Chain1"/>
+    <variant name="Chain2"/>
+    <variant name="Chain3"/>
+  </token>
+</histogram>
+
 <histogram name="Net.NeedsHWCAP2Workaround" enum="BooleanBroken"
     expires_after="2024-06-30">
   <owner>davidben@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index 00b0f0d..f6ba6c2 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -366,7 +366,7 @@
 </histogram>
 
 <histogram name="NewTabPage.CustomizeChromeBackgroundAction"
-    enum="NTPCustomizeChromeBackgroundAction" expires_after="2025-05-31">
+    enum="NTPCustomizeChromeBackgroundAction" expires_after="2026-01-31">
   <owner>pauladedeji@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -439,7 +439,7 @@
 </histogram>
 
 <histogram name="NewTabPage.CustomizeLocalImageBackgroundAction"
-    enum="NTPCustomizeLocalImageBackgroundAction" expires_after="2025-05-31">
+    enum="NTPCustomizeLocalImageBackgroundAction" expires_after="2026-01-31">
   <owner>pauladedeji@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/platform/enums.xml b/tools/metrics/histograms/metadata/platform/enums.xml
index f49daa3..041906dc 100644
--- a/tools/metrics/histograms/metadata/platform/enums.xml
+++ b/tools/metrics/histograms/metadata/platform/enums.xml
@@ -2586,6 +2586,7 @@
   <int value="230386903" label="CROS Cr50 0.0.24 Eve Flags 0x7f00(prod)"/>
   <int value="245471087" label="CROS Cr50 0.4.25"/>
   <int value="267286010" label="CROS Cr50 0.6.40"/>
+  <int value="272592294" label="CROS Ti50 0.24.170"/>
   <int value="276176597" label="CROS Cr50 0.1.0 Flags 0x10(pre-pvt)"/>
   <int value="293403010" label="CROS Ti50 0.24.2"/>
   <int value="297017579" label="CROS Cr50 0.6.60 aka 0.6.80"/>
@@ -2720,6 +2721,7 @@
   <int value="1349306733" label="CROS Cr50 0.6.222"/>
   <int value="1352415402" label="CROS Ti50 0.24.160"/>
   <int value="1353576267" label="IFX 9635 fw 3.18 build 0009"/>
+  <int value="1355918206" label="CROS Ti50 0.24.171"/>
   <int value="1360145401" label="CROS Ti50 NT 0.36.4"/>
   <int value="1366252830" label="CROS Ti50 0.0.15"/>
   <int value="1374014142" label="CROS Ti50 NT 0.36.7"/>
@@ -2817,6 +2819,7 @@
   <int value="2104725364" label="CROS Cr50 0.3.20"/>
   <int value="2109398286" label="CROS Cr50 0.4.7"/>
   <int value="2109915777" label="CROS Cr50 0.6.261"/>
+  <int value="2121663881" label="CROS Ti50 0.24.172"/>
   <int value="2127616984" label="CROS Cr50 0.6.1"/>
   <int value="2128561741" label="CROS Cr50 0.5.93"/>
   <int value="2128775895" label="CROS Ti50 0.24.61"/>
diff --git a/tools/metrics/histograms/metadata/power/enums.xml b/tools/metrics/histograms/metadata/power/enums.xml
new file mode 100644
index 0000000..9174581
--- /dev/null
+++ b/tools/metrics/histograms/metadata/power/enums.xml
@@ -0,0 +1,41 @@
+<!--
+Copyright 2025 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+
+This file describes the enumerations referenced by entries in histograms.xml for
+this directory. Some enums may instead be listed in the central enums.xml file
+at src/tools/metrics/histograms/enums.xml when multiple files use them.
+
+For best practices on writing enumerations descriptions, see
+https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#Enum-Histograms
+
+Please follow the instructions in the OWNERS file in this directory to find a
+reviewer. If no OWNERS file exists, please consider signing up at
+go/reviewing-metrics (Googlers only), as all subdirectories are expected to
+have an OWNERS file. As a last resort you can send the CL to
+chromium-metrics-reviews@google.com.
+-->
+
+<histogram-configuration>
+
+<!-- Enum types -->
+
+<enums>
+
+<enum name="SystemHealthManagerError">
+<!-- LINT.IfChange(SystemHealthManagerError) -->
+
+  <int value="0" label="No power monitors available"/>
+  <int value="1" label="getPowerMonitorReadings call interrupted"/>
+  <int value="2" label="getPowerMonitorReadings call timed out"/>
+<!-- Lint.ThenChange(/base/android/java/src/org/chromium/base/PowerMonitor.java:SystemHealthManagerError) -->
+
+</enum>
+
+</enums>
+
+</histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 8779cee..0d1cecd 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -63,6 +63,40 @@
       summary="intervals with battery saver mode enabled."/>
 </variants>
 
+<variants name="Exclusive">
+<!--
+  Variants indicating if battery drain can be attributed to Chrome exclusively.
+-->
+
+  <variant name="" summary=""/>
+  <variant name=".Exclusive"
+      summary="However, only battery drain that can be attributed exclusively
+               to the time Chrome/WebView was visible is reported: The first
+               drain after becoming foregrounded is not reported. As a
+               result, this metric typically doesn't include drain related to
+               app startup. Note that other apps can still contribute to the
+               power consumed/tracked, e.g. due to using resources while they
+               are backgrounded or in a multi-window context."/>
+</variants>
+
+<variants name="InputScenario">
+<!--
+  Variants indicating an input scenario.
+-->
+
+<!-- LINT.IfChange(InputScenarioSuffix) -->
+
+  <variant name="_NoInput" summary="the user is not providing input"/>
+  <variant name="_Scroll" summary="the user scrolled"/>
+  <variant name="_Tap" summary="the user tapped but not scrolled"/>
+  <variant name="_Typing"
+      summary="The user typed be neither tapped nor scrolled"/>
+  <variant name="_UnknownInputScenario"
+      summary="input state could not be detected"/>
+<!-- LINT.ThenChange(/content/browser/android/battery_metrics.cc:InputScenarioSuffix) -->
+
+</variants>
+
 <variants name="IntervalType">
 <!--
     Variants describing if the histogram contains all samples, only the first
@@ -78,6 +112,28 @@
       summary="every sample recorded after the first one"/>
 </variants>
 
+<variants name="LoadingScenario">
+<!--
+  Variants indicating a page loading scenario.
+-->
+
+<!-- LINT.IfChange(LoadingScenarioSuffix) -->
+
+  <variant name=".BackgroundPageLoading"
+      summary="a background (but not focused or visible) page was loading for
+               some part of the 30s interval"/>
+  <variant name=".FocusedPageLoading"
+      summary="a focused page was loading for some part of the 30s interval"/>
+  <variant name=".NoPageLoading" summary="no page is loading"/>
+  <variant name=".UnknownLoadingScenario"
+      summary="page loading state could not be detected"/>
+  <variant name=".VisiblePageLoading"
+      summary="a visible (but not focused) page was loading for some part of
+               the 30s interval"/>
+<!-- LINT.ThenChange(/content/browser/android/battery_metrics.cc:LoadingScenarioSuffix) -->
+
+</variants>
+
 <variants name="ProcessName">
   <variant name="BrowserProcess" summary=""/>
   <variant name="GPUProcess" summary=""/>
@@ -1189,21 +1245,7 @@
     This histogram is of special interest to the chrome-analysis-team@. Do not
     change its semantics or retire it without talking to them first.
   </summary>
-  <token key="Exclusive">
-    <variant name="" summary=""/>
-    <variant name=".Exclusive"
-        summary="However, only battery drain that can be attributed
-                 exclusively to the time Chrome/WebView was visible is
-                 reported: The first drain after becoming foregrounded is not
-                 reported. As a result, this metric typically doesn't include
-                 drain related to app startup. Similarly, no values are
-                 reported for the time after the last capacity drop in a
-                 session, since these would likely under-account the actual
-                 battery drain in that time. Note that other apps can still
-                 contribute to the power consumed/tracked, e.g. due to using
-                 resources while they are backgrounded or in a multi-window
-                 context."/>
-  </token>
+  <token key="Exclusive" variants="Exclusive"/>
   <token key="DarkeningType">
     <variant name="" summary=""/>
     <variant name=".DarkMode"
@@ -1249,18 +1291,7 @@
     different times on the same device, also due to environmental factors like
     device temperature or charge level).
   </summary>
-  <token key="Exclusive">
-    <variant name="" summary=""/>
-    <variant name=".Exclusive"
-        summary="However, only battery drain that can be attributed
-                 exclusively to the time Chrome/WebView was visible is
-                 reported: The first drain after becoming foregrounded is not
-                 reported. As a result, this metric typically doesn't include
-                 drain related to app startup. Note that other apps can still
-                 contribute to the power consumed/tracked, e.g. due to using
-                 resources while they are backgrounded or in a multi-window
-                 context."/>
-  </token>
+  <token key="Exclusive" variants="Exclusive"/>
 </histogram>
 
 <histogram
@@ -1273,48 +1304,9 @@
     usage scenario classification: {LoadingScenario} and {InputScenario}.
     {Exclusive}
   </summary>
-  <token key="Exclusive">
-    <variant name="" summary=""/>
-    <variant name=".Exclusive"
-        summary="However, only battery drain that can be attributed
-                 exclusively to the time Chrome/WebView was visible is
-                 reported: The first drain after becoming foregrounded is not
-                 reported. As a result, this metric typically doesn't include
-                 drain related to app startup. Note that other apps can still
-                 contribute to the power consumed/tracked, e.g. due to using
-                 resources while they are backgrounded or in a multi-window
-                 context."/>
-  </token>
-<!-- LINT.IfChange(LoadingScenarioSuffix) -->
-
-  <token key="LoadingScenario">
-    <variant name=".BackgroundPageLoading"
-        summary="a background (but not focused or visible) page was loading
-                 for some part of the 30s interval"/>
-    <variant name=".FocusedPageLoading"
-        summary="a focused page was loading for some part of the 30s interval"/>
-    <variant name=".NoPageLoading" summary="no page is loading"/>
-    <variant name=".UnknownLoadingScenario"
-        summary="page loading state could not be detected"/>
-    <variant name=".VisiblePageLoading"
-        summary="a visible (but not focused) page was loading for some part
-                 of the 30s interval"/>
-  </token>
-<!-- LINT.ThenChange(/content/browser/android/battery_metrics.cc:LoadingScenarioSuffix) -->
-
-<!-- LINT.IfChange(InputScenarioSuffix) -->
-
-  <token key="InputScenario">
-    <variant name="_NoInput" summary="the user is not providing input"/>
-    <variant name="_Scroll" summary="the user scrolled"/>
-    <variant name="_Tap" summary="the user tapped but not scrolled"/>
-    <variant name="_Typing"
-        summary="The user typed be neither tapped nor scrolled"/>
-    <variant name="_UnknownInputScenario"
-        summary="input state could not be detected"/>
-  </token>
-<!-- LINT.ThenChange(/content/browser/android/battery_metrics.cc:InputScenarioSuffix) -->
-
+  <token key="Exclusive" variants="Exclusive"/>
+  <token key="LoadingScenario" variants="LoadingScenario"/>
+  <token key="InputScenario" variants="InputScenario"/>
 </histogram>
 
 <histogram name="Power.ForegroundBatteryDrain{Exclusive}" units="0.1 mAh"
@@ -1343,18 +1335,28 @@
     For a histogram of daily per-user values, see the computed histogram
     Power.DailyForegroundBatteryDrain.
   </summary>
-  <token key="Exclusive">
-    <variant name="" summary=""/>
-    <variant name=".Exclusive"
-        summary="However, only battery drain that can be attributed
-                 exclusively to the time Chrome/WebView was visible is
-                 reported: The first drain after becoming foregrounded is not
-                 reported. As a result, this metric typically doesn't include
-                 drain related to app startup. Note that other apps can still
-                 contribute to the power consumed/tracked, e.g. due to using
-                 resources while they are backgrounded or in a multi-window
-                 context."/>
-  </token>
+  <token key="Exclusive" variants="Exclusive"/>
+</histogram>
+
+<histogram
+    name="Power.ForegroundEnergyConsumedPerScenario.30Seconds{Exclusive}{LoadingScenario}{InputScenario}"
+    units="uWh" expires_after="2026-04-15">
+  <owner>kraskevich@google.com</owner>
+  <owner>woa-performance@google.com</owner>
+  <summary>
+    Similar to Power.ForegroundBatteryDrain.30Seconds, with additional Chrome
+    usage scenario classification: {LoadingScenario} and {InputScenario}.
+    {Exclusive}
+
+    This metric uses a more accurate (but less widely supported) underlying API
+    https://developer.android.com/reference/android/os/health/SystemHealthManager.
+
+    The reported value is energy consumed during the 30s interval in
+    microwatt-hours.
+  </summary>
+  <token key="Exclusive" variants="Exclusive"/>
+  <token key="LoadingScenario" variants="LoadingScenario"/>
+  <token key="InputScenario" variants="InputScenario"/>
 </histogram>
 
 <histogram name="Power.HasPreciseBatteryDischargeGranularity" enum="Boolean"
@@ -1810,6 +1812,18 @@
   </summary>
 </histogram>
 
+<histogram name="Power.SystemHealthManagerError"
+    enum="SystemHealthManagerError" expires_after="2026-04-15">
+  <owner>kraskevich@google.com</owner>
+  <owner>woa-performance@google.com</owner>
+  <summary>
+    Records errors for SystemHealthManager API calls.
+
+    The SystemHealthManager API is used for computing
+    Power.ForegroundEnergyConsumedPerScenario.30Seconds.
+  </summary>
+</histogram>
+
 <histogram name="Power.TimeInSuspendAtBoot" units="minutes"
     expires_after="2025-08-24">
   <owner>tbroch@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sync/enums.xml b/tools/metrics/histograms/metadata/sync/enums.xml
index c3830a0eb..8d19492 100644
--- a/tools/metrics/histograms/metadata/sync/enums.xml
+++ b/tools/metrics/histograms/metadata/sync/enums.xml
@@ -399,6 +399,8 @@
   <int value="81" label="AutofillBnplEnabled"/>
   <int value="82" label="AutofillHasSeenBnpl"/>
   <int value="83" label="AutomaticPasskeyUpgrades"/>
+  <int value="84" label="(test) SyncablePriorityPrefForTesting"/>
+  <int value="85" label="(test) SyncableAlwaysSyncingPriorityPrefForTesting"/>
 <!-- LINT.ThenChange(/components/sync_preferences/common_syncable_prefs_database.cc:CommonSyncablePref)-->
 
 <!-- LINT.IfChange(ChromeSyncablePref) -->
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index 0d8bd8c..13e93cd7 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -658,6 +658,7 @@
     'speedometer2-minorms',
     'speedometer3-minorms',
 ])
+_MAC_M3_PRO_BENCHMARK_CONFIGS = PerfSuite([])
 
 _WIN_10_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([
     'v8.runtime_stats.top_25',
@@ -844,7 +845,12 @@
                           20,
                           'mac',
                           crossbench=_CROSSBENCH_BENCHMARKS_ALL)
-
+MAC_M3_PRO = PerfPlatform('mac-m3-pro-perf',
+                          'Mac M3 PRO ARM',
+                          _MAC_M3_PRO_BENCHMARK_CONFIGS,
+                          4,
+                          'mac',
+                          crossbench=_CROSSBENCH_BENCHMARKS_ALL)
 # Win
 WIN_10_LOW_END = PerfPlatform(
     'win-10_laptop_low_end-perf',
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index b185ba9e..4605d4d 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -138,6 +138,7 @@
     'mac-m1_mini_2020-perf',
     'mac-m1_mini_2020-perf-pgo',
     'mac-m2-pro-perf',
+    'mac-m3-pro-perf',
     'win-10-processor-perf',
     'win-10_amd_laptop-perf',
     'win-10_laptop_low_end-processor-perf',
@@ -991,6 +992,30 @@
             'Mac14,7_arm64-64-Apple_M2_apple m2_8192_APPLE SSD AP0256Z',
         },
     },
+    'mac-m3-pro-perf': {
+        'tests': [
+            {
+                'isolate': 'performance_test_suite',
+                'extra_args': [
+                    '--assert-gpu-compositing',
+                ],
+            },
+        ],
+        'platform':
+        'mac',
+        'dimension': {
+            'cpu':
+            'arm',
+            'mac_model':
+            'Mac15,3',
+            'os':
+            'Mac',
+            'pool':
+            'chrome.tests.perf',
+            'synthetic_product_name':
+            'Mac15,3_arm64-64-Apple_M3_apple m3_8192_APPLE SSD AP0512Z',
+        },
+    },
     'win-10_amd_laptop-perf': {
         'tests': [
             {
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index acd91cc7..37f3e0d8 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/v50.1/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "cb116261436227ccbb63f5179aab563c8fb6cba7",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/8a38f2ad11b6b2bf0a4d60b39c79d00d35fdbc01/trace_processor_shell.exe"
+            "hash": "8a1ee5642da9d94ef5bd5d754ed999d046c3c93a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b9acf7ff3553f8cf7545dc5e2bfb1b1e1a4a7081/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "99f971ca131f6d11c73f4b918099d434bdd8093c",
@@ -21,8 +21,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v50.1/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "c5095d45c469e7f629d445dfff678d2a1d5811c8",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6acaf607621ce5a117dc1a9773f27aa0d4c77b5b/trace_processor_shell"
+            "hash": "10f385bffae6657b01d20dca71335daf1769dccf",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/b9acf7ff3553f8cf7545dc5e2bfb1b1e1a4a7081/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json b/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json
new file mode 100644
index 0000000..ebb5b31f
--- /dev/null
+++ b/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json
@@ -0,0 +1,65 @@
+{
+    "0": {
+        "crossbench": {
+            "speedometer_3.1": {
+                "display_name": "speedometer3.1.crossbench",
+                "arguments": []
+            },
+            "jetstream_2.2": {
+                "display_name": "jetstream2.crossbench",
+                "arguments": []
+            }
+        },
+        "benchmarks": {}
+    },
+    "1": {
+        "crossbench": {
+            "speedometer_3.1": {
+                "display_name": "speedometer3.1.crossbench",
+                "arguments": []
+            }
+        },
+        "benchmarks": {}
+    },
+    "2": {
+        "crossbench": {
+            "speedometer_3.1": {
+                "display_name": "speedometer3.1.crossbench",
+                "arguments": []
+            },
+            "motionmark_1.3": {
+                "display_name": "motionmark1.3.crossbench",
+                "arguments": []
+            }
+        },
+        "benchmarks": {}
+    },
+    "3": {
+        "crossbench": {
+            "speedometer_3.1": {
+                "display_name": "speedometer3.1.crossbench",
+                "arguments": []
+            },
+            "speedometer_2.1": {
+                "display_name": "speedometer2.1.crossbench",
+                "arguments": []
+            },
+            "speedometer_3.0": {
+                "display_name": "speedometer3.crossbench",
+                "arguments": []
+            }
+        },
+        "benchmarks": {}
+    },
+    "extra_infos": {
+        "num_stories": 8,
+        "predicted_min_shard_time": 60,
+        "predicted_min_shard_index": 1,
+        "predicted_max_shard_time": 420,
+        "predicted_max_shard_index": 2,
+        "shard #0": 240,
+        "shard #1": 60,
+        "shard #2": 420,
+        "shard #3": 180
+    }
+}
diff --git a/tools/perf/core/shard_maps/timing_data/mac-m3-pro-perf_timing.json b/tools/perf/core/shard_maps/timing_data/mac-m3-pro-perf_timing.json
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/tools/perf/core/shard_maps/timing_data/mac-m3-pro-perf_timing.json
@@ -0,0 +1 @@
+[]
diff --git a/tools/perf/cross_device_test_config.py b/tools/perf/cross_device_test_config.py
index 7c74b34..28d59943 100644
--- a/tools/perf/cross_device_test_config.py
+++ b/tools/perf/cross_device_test_config.py
@@ -306,4 +306,7 @@
         'speedometer3.crossbench': 4,
         'speedometer3.1.crossbench': 4,
     },
+     'mac-m3-pro-perf': {
+        'speedometer3.1.crossbench': 4,
+    },
 }
diff --git a/tools/rust/update_rust.py b/tools/rust/update_rust.py
index c9a4f2f..183e234 100755
--- a/tools/rust/update_rust.py
+++ b/tools/rust/update_rust.py
@@ -31,7 +31,7 @@
 
 # These fields are written by //tools/clang/scripts/upload_revision.py, and
 # should not be changed manually.
-RUST_REVISION = '3f690c2257b7080cd3a8cce64e082fc972148990'
+RUST_REVISION = 'c8f94230282a8e8c1148f3e657f0199aad909228'
 RUST_SUB_REVISION = 1
 
 # The revision of Crubit to use from https://github.com/google/crubit
@@ -46,7 +46,7 @@
 # Hash of src/stage0.json, which itself contains the stage0 toolchain hashes.
 # We trust the Rust build system checks, but to ensure it is not tampered with
 # itself check the hash.
-STAGE0_JSON_SHA256 = 'ad3095f23fe55ef1d86bc8ee8b5d31eb4e98eb3d8a6d163c295625ffa18ca35a'
+STAGE0_JSON_SHA256 = '1113296e1412c791d09f3033355001061e7ca36e06e796ff0f1f798791a6d93b'
 
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
 CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..'))
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml
index a9a82c2b..2343698 100644
--- a/ui/android/java/res/values/color_palette.xml
+++ b/ui/android/java/res/values/color_palette.xml
@@ -106,6 +106,8 @@
     <color name="gm3_baseline_surface_container_highest_dark">#333537</color>
     <color name="gm3_baseline_surface_bright_light">@color/gm3_baseline_surface_light</color>
     <color name="gm3_baseline_surface_bright_dark">#37393B</color>
+    <color name="gm3_baseline_surface_dim_light">#D3DBE5</color>
+    <color name="gm3_baseline_surface_dim_dark">@color/gm3_baseline_surface_dark</color>
 
     <!-- System colors that point to the baseline palette for below Android S.-->
     <color name="system_neutral1_10">@color/baseline_neutral_99</color>
diff --git a/ui/android/java/res/values/dimens.xml b/ui/android/java/res/values/dimens.xml
index 9425f50..4e82fff 100644
--- a/ui/android/java/res/values/dimens.xml
+++ b/ui/android/java/res/values/dimens.xml
@@ -88,9 +88,6 @@
     <!-- Elevation levels -->
     <dimen name="default_elevation_0">0dp</dimen>
 
-    <!-- Arbitrary shadow length for elevation levels -->
-    <dimen name="default_shadow_length_elev_2">6dp</dimen>
-
     <dimen name="default_list_row_padding">16dp</dimen>
 
     <!-- List menu & item dimensions -->
diff --git a/ui/android/java/src/org/chromium/ui/KeyboardUtils.java b/ui/android/java/src/org/chromium/ui/KeyboardUtils.java
index 13c7ff06..1c5bf5a 100644
--- a/ui/android/java/src/org/chromium/ui/KeyboardUtils.java
+++ b/ui/android/java/src/org/chromium/ui/KeyboardUtils.java
@@ -9,6 +9,7 @@
 import android.os.Handler;
 import android.os.StrictMode;
 import android.provider.Settings;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
@@ -31,6 +32,11 @@
     /** Waiting time between attempts to show the keyboard. */
     private static final long KEYBOARD_RETRY_DELAY_MS = 100;
 
+    public static final int CTRL = 1 << 31;
+    public static final int ALT = 1 << 30;
+    public static final int SHIFT = 1 << 29;
+    public static final int NO_MODIFIER = 0;
+
     /**
      * Tries to show the soft keyboard by using the {@link Context#INPUT_METHOD_SERVICE}.
      *
@@ -145,4 +151,17 @@
                         context.getContentResolver(), "show_ime_with_hard_keyboard", 0)
                 != 0;
     }
+
+    /**
+     * Reports the metaState of a KeyEvent, which gives information about the modifier keys that are
+     * part of the event (e.g. Ctrl).
+     *
+     * @param event A {@link KeyEvent}.
+     * @return Bitmask of the modifier keys included in the event.
+     */
+    public static int getMetaState(KeyEvent event) {
+        return (event.isCtrlPressed() ? CTRL : 0)
+                | (event.isAltPressed() ? ALT : 0)
+                | (event.isShiftPressed() ? SHIFT : 0);
+    }
 }
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuButton.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuButton.java
index 84a23062..5c8e4c80 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuButton.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuButton.java
@@ -31,7 +31,7 @@
      * @param context The {@link Context} used to build the visuals from.
      * @param attrs The specific {@link AttributeSet} used to build the button.
      */
-    public ListMenuButton(Context context, AttributeSet attrs) {
+    public ListMenuButton(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mListMenuHost = new ListMenuHost(this, attrs);
     }
diff --git a/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java b/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java
index 21103bd..9583ee0 100644
--- a/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java
+++ b/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java
@@ -11,6 +11,7 @@
 import androidx.appcompat.widget.AppCompatImageButton;
 
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 
 // TODO(crbug.com/40883889): See if we still need this class.
 /**
@@ -23,11 +24,11 @@
         super(context);
     }
 
-    public ChromeImageButton(Context context, AttributeSet attrs) {
+    public ChromeImageButton(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public ChromeImageButton(Context context, AttributeSet attrs, int defStyle) {
+    public ChromeImageButton(Context context, @Nullable AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
     }
 
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 8abb389f..dfca458 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -12,7 +12,6 @@
 import("//build/config/ozone.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
-import("//build/util/branding.gni")
 import("//skia/features.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
@@ -28,6 +27,7 @@
   import("//build/config/apple/mobile_config.gni")
 } else if (is_mac) {
   import("//build/config/mac/rules.gni")
+  import("//build/util/branding.gni")
 }
 
 build_ime = !is_ios
diff --git a/ui/events/devices/x11/touch_factory_x11.cc b/ui/events/devices/x11/touch_factory_x11.cc
index 88cabd9..eb67313 100644
--- a/ui/events/devices/x11/touch_factory_x11.cc
+++ b/ui/events/devices/x11/touch_factory_x11.cc
@@ -225,12 +225,9 @@
   // these events.
   SetXinputMask(mask_data, x11::Input::HierarchyEvent::opcode);
   SetXinputMask(mask_data, x11::Input::DeviceChangedEvent::opcode);
-#if BUILDFLAG(IS_CHROMEOS)
-  if (base::SysInfo::IsRunningOnChromeOS()) {
-    SetXinputMask(mask_data, x11::Input::DeviceEvent::KeyPress);
-    SetXinputMask(mask_data, x11::Input::DeviceEvent::KeyRelease);
-  }
-#endif
+
+  SetXinputMask(mask_data, x11::Input::DeviceEvent::KeyPress);
+  SetXinputMask(mask_data, x11::Input::DeviceEvent::KeyRelease);
 
   connection->xinput().XISelectEvents({window, {mask}});
   connection->Flush();
diff --git a/ui/events/x/x11_event_translation.cc b/ui/events/x/x11_event_translation.cc
index 1234b9f4..9ec592e8 100644
--- a/ui/events/x/x11_event_translation.cc
+++ b/ui/events/x/x11_event_translation.cc
@@ -4,6 +4,7 @@
 
 #include "ui/events/x/x11_event_translation.h"
 
+#include <numeric>
 #include <vector>
 
 #include "base/check.h"
@@ -26,6 +27,21 @@
 
 namespace {
 
+// This function is a shim for approximately emulating the state field of
+// legacy XKB key events, using information from XI2 key events, for
+// consumption by GTK.
+uint32_t XkbStateFromXI2Event(const x11::Input::DeviceEvent& xievent) {
+  uint32_t mods = xievent.mods.effective & 0xf;
+  uint8_t buttons = std::reduce(xievent.button_mask.begin(),
+                                xievent.button_mask.end(), 0, std::bit_or<>());
+  // For some reason, the XInput2 button mask needs to be right-shifted by one
+  // to match the XKB button mask.
+  buttons = (buttons >> 1) & 0x1f;
+  // The group (bits 13-14 of the XKB state) is deliberately omitted because
+  // it's not used by GdkModifierType.
+  return (static_cast<uint32_t>(buttons) << 8) | mods;
+}
+
 int XkbGroupForCoreState(int state) {
   return (state >> 13) & 0x3;
 }
@@ -61,30 +77,44 @@
   using Values = std::vector<uint8_t>;
   Event::Properties properties;
   if (type == EventType::kKeyPressed || type == EventType::kKeyReleased) {
-    auto* key = x11_event.As<x11::KeyEvent>();
+    if (auto* key = x11_event.As<x11::KeyEvent>()) {
+      // Keyboard group
+      auto state = static_cast<uint32_t>(key->state);
+      properties.emplace(kPropertyKeyboardState,
+                         Values{
+                             static_cast<uint8_t>(state),
+                             static_cast<uint8_t>(state >> 8),
+                             static_cast<uint8_t>(state >> 16),
+                             static_cast<uint8_t>(state >> 24),
+                         });
 
-    // Keyboard group
-    auto state = static_cast<uint32_t>(key->state);
-    properties.emplace(kPropertyKeyboardState,
-                       Values{
-                           static_cast<uint8_t>(state),
-                           static_cast<uint8_t>(state >> 8),
-                           static_cast<uint8_t>(state >> 16),
-                           static_cast<uint8_t>(state >> 24),
-                       });
+      uint8_t group = XkbGroupForCoreState(state);
+      properties.emplace(kPropertyKeyboardGroup, Values{group});
 
-    uint8_t group = XkbGroupForCoreState(state);
-    properties.emplace(kPropertyKeyboardGroup, Values{group});
+      // Hardware keycode
+      uint8_t hw_keycode = static_cast<uint8_t>(key->detail);
+      properties.emplace(kPropertyKeyboardHwKeyCode, Values{hw_keycode});
 
-    // Hardware keycode
-    uint8_t hw_keycode = static_cast<uint8_t>(key->detail);
-    properties.emplace(kPropertyKeyboardHwKeyCode, Values{hw_keycode});
-
-    // IBus-/fctix-GTK specific flags
-    uint8_t ime_flags = (state >> kPropertyKeyboardImeFlagOffset) &
-                        kPropertyKeyboardImeFlagMask;
-    if (ime_flags) {
-      SetKeyboardImeFlagProperty(&properties, ime_flags);
+      // IBus-/fctix-GTK specific flags
+      uint8_t ime_flags = (state >> kPropertyKeyboardImeFlagOffset) &
+                          kPropertyKeyboardImeFlagMask;
+      if (ime_flags) {
+        SetKeyboardImeFlagProperty(&properties, ime_flags);
+      }
+    } else if (auto* xievent = x11_event.As<x11::Input::DeviceEvent>()) {
+      // Handle case where XI2 is enabled for KeyPress and KeyRelease events.
+      auto state = XkbStateFromXI2Event(*xievent);
+      properties.emplace(kPropertyKeyboardState,
+                         Values{
+                             static_cast<uint8_t>(state),
+                             static_cast<uint8_t>(state >> 8),
+                             static_cast<uint8_t>(state >> 16),
+                             static_cast<uint8_t>(state >> 24),
+                         });
+      properties.emplace(kPropertyKeyboardGroup,
+                         Values{xievent->group.effective});
+      properties.emplace(kPropertyKeyboardHwKeyCode,
+                         Values{static_cast<uint8_t>(xievent->detail)});
     }
   } else if (type == EventType::kMouseExited) {
     // NotifyVirtual events are created for intermediate windows that the
diff --git a/ui/gl/features.gni b/ui/gl/features.gni
index f4f3f98..84678cb 100644
--- a/ui/gl/features.gni
+++ b/ui/gl/features.gni
@@ -4,7 +4,6 @@
 
 import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//chrome/version.gni")
 
 declare_args() {
   # Should ANGLE be linked statically?
diff --git a/ui/gl/startup_trace.h b/ui/gl/startup_trace.h
index 3b5b5544..d3bae4e7 100644
--- a/ui/gl/startup_trace.h
+++ b/ui/gl/startup_trace.h
@@ -77,20 +77,6 @@
 
 }  // namespace gl
 
-// Generate a unique variable name with a given prefix.
-#define GPU_STARTUP_TRACE_INTERNAL_CONCAT2(a, b) a##b
-#define GPU_STARTUP_TRACE_INTERNAL_CONCAT(a, b) \
-  GPU_STARTUP_TRACE_INTERNAL_CONCAT2(a, b)
-#define GPU_STARTUP_TRACE_UID(prefix) \
-  GPU_STARTUP_TRACE_INTERNAL_CONCAT(prefix, __LINE__)
-
-#define GPU_STARTUP_TRACE_EVENT(name)                                       \
-  gl::StartupTrace::ScopedStage GPU_STARTUP_TRACE_UID(scoped_gpu_trace){0}; \
-  if (gl::StartupTrace::IsEnabled()) {                                      \
-    GPU_STARTUP_TRACE_UID(scoped_gpu_trace) =                               \
-        gl::StartupTrace::GetInstance()->AddStage(name);                    \
-  } else {                                                                  \
-    TRACE_EVENT0("gpu,startup", name);                                      \
-  }
+#define GPU_STARTUP_TRACE_EVENT(name) TRACE_EVENT("gpu,startup", name);
 
 #endif  // UI_GL_STARTUP_TRACE_H_
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index dcca94fc..14a38b1 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
@@ -274,6 +273,10 @@
 
     base::UmaHistogramEnumeration("Linux.WindowManager", GetWindowManagerUMA());
 
+    base::UmaHistogramBoolean(
+        "Linux.X11.XInput2",
+        x11::Connection::Get()->xinput_version().first == 2);
+
     return true;
   }
 
diff --git a/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc b/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc
index 98afc78..205dffac 100644
--- a/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc
+++ b/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc
@@ -64,6 +64,43 @@
   EXPECT_EQ(ui::DomKey::ENTER, copy.GetDomKey());
 }
 
+// Ensure KeyEvent::Properties is properly set when XI2 key events are used.
+TEST(XEventTranslationTest, KeyEventXI2EventPropertiesSet) {
+  ui::ScopedKeyboardLayout keyboard_layout(ui::KEYBOARD_LAYOUT_ENGLISH_US);
+  ScopedXI2Event scoped_xev;
+  // deviceid of XI2 key event must match that of virtual core keyboard in
+  // x11::TouchFactory to be processed.
+  scoped_xev.InitGenericKeyEvent(/*deviceid=*/3, /*sourceid=*/0,
+                                 EventType::kKeyPressed, KeyboardCode::VKEY_A,
+                                 EF_NONE);
+
+  x11::Event* xev = scoped_xev;
+  auto* connection = x11::Connection::Get();
+  // Set keyboard group.
+  auto* xievent = xev->As<x11::Input::DeviceEvent>();
+  xievent->group.base = 2;
+  xievent->group.effective = 2;
+
+  auto keyev = ui::BuildKeyEventFromXEvent(*xev);
+  ASSERT_TRUE(keyev);
+
+  auto* properties = keyev->properties();
+  ASSERT_TRUE(properties);
+  EXPECT_FALSE(properties->empty());
+
+  // Ensure hardware keycode and keyboard group are properly set.
+  auto hw_keycode_it = properties->find(ui::kPropertyKeyboardHwKeyCode);
+  EXPECT_NE(hw_keycode_it, properties->end());
+  EXPECT_EQ(1u, hw_keycode_it->second.size());
+  EXPECT_EQ(static_cast<uint8_t>(connection->KeysymToKeycode(XK_a)),
+            hw_keycode_it->second[0]);
+
+  auto kbd_group_it = properties->find(ui::kPropertyKeyboardGroup);
+  EXPECT_NE(kbd_group_it, properties->end());
+  EXPECT_EQ(1u, kbd_group_it->second.size());
+  EXPECT_EQ(2u, kbd_group_it->second[0]);
+}
+
 // Ensure KeyEvent::Properties is properly set regardless X11 build config is
 // in place. This prevents regressions such as crbug.com/1047999.
 TEST(XEventTranslationTest, KeyEventXEventPropertiesSet) {
@@ -81,10 +118,10 @@
   xev->As<x11::KeyEvent>()->state = static_cast<x11::KeyButMask>(state);
 
   auto keyev = ui::BuildKeyEventFromXEvent(*xev);
-  EXPECT_TRUE(keyev);
+  ASSERT_TRUE(keyev);
 
   auto* properties = keyev->properties();
-  EXPECT_TRUE(properties);
+  ASSERT_TRUE(properties);
   EXPECT_EQ(4u, properties->size());
 
   // Ensure hardware keycode, keyboard group and IME flag properties are
diff --git a/ui/views/test/views_test_base.h b/ui/views/test/views_test_base.h
index c93256d..36649418 100644
--- a/ui/views/test/views_test_base.h
+++ b/ui/views/test/views_test_base.h
@@ -173,6 +173,10 @@
           views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
 
  private:
+#if BUILDFLAG(IS_WIN)
+  ui::ScopedOleInitializer ole_initializer_;
+#endif
+
   std::unique_ptr<base::test::TaskEnvironment> task_environment_;
   std::optional<ui::AXPlatformForTest> ax_platform_;
 
@@ -189,10 +193,6 @@
   bool interactive_setup_called_ = false;
   bool setup_called_ = false;
   bool teardown_called_ = false;
-
-#if BUILDFLAG(IS_WIN)
-  ui::ScopedOleInitializer ole_initializer_;
-#endif
 };
 
 // A helper that makes it easier to declare basic views tests that want to test
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index cd6a3b6..5af3d8a 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -80,6 +80,7 @@
 
 #if BUILDFLAG(IS_WIN)
 #include "ui/base/win/shell.h"
+#include "ui/gfx/win/hwnd_util.h"
 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager_win.h"
 #endif
 
@@ -965,8 +966,29 @@
 }
 
 bool DesktopNativeWidgetAura::IsVisibleOnScreen() const {
-  // TODO(crbug.com/410938804): implement this.
-  return IsVisible();
+  if (!IsVisible() || IsMinimized()) {
+    return false;
+  }
+
+  if (!desktop_window_tree_host_) {
+    return false;
+  }
+
+  // Determine if the window is hidden in some other way, such as on a different
+  // desktop.
+  // TODO(crbug.com/410938804): implement workspace handling on other platforms.
+#if BUILDFLAG(IS_WIN)
+  // If a window is cloaked, it is not visible on screen because e.g., it is
+  // on an invisible virtual desktop.
+  // https://devblogs.microsoft.com/oldnewthing/20200302-00/?p=103507
+  aura::WindowTreeHost* host = desktop_window_tree_host_->AsWindowTreeHost();
+  if (gfx::IsWindowCloaked(host->GetAcceleratedWidget())) {
+    return false;
+  }
+#endif
+
+  // All checks pass, the window is visible on screen.
+  return true;
 }
 
 void DesktopNativeWidgetAura::Activate() {
diff --git a/v8 b/v8
index 299a02b..1610539 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 299a02b2c82bfd6bffe69b1675d154190290bbcd
+Subproject commit 1610539c8018d743b4aeb2a24a12aa5a0190159f