diff --git a/DEPS b/DEPS
index 9e3038f2..1dddf331 100644
--- a/DEPS
+++ b/DEPS
@@ -318,15 +318,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'a2728a7ad2a3471505475eedb485d46beb4b2e09',
+  'skia_revision': '6f4fd97d2f7ef837b678787c2760854ebb838ee1',
   # 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': '93af4438d2bed525e6cb577274c208796d736b44',
+  'v8_revision': '389dcb03ad1e7ee7f050248439e9ef296f859d3b',
   # 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': 'b9e9c58bbd779cfeb98b16c57fb76001379b4975',
+  'angle_revision': 'bc7fc3997be824e3029da785ba5bc2e3df25e546',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -409,7 +409,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': 'a49a95dd95a964a380334ddfba99b395d645f51a',
+  'devtools_frontend_revision': 'f5943cd8a7ae161fbec5be57e76aa8fc37a69e76',
   # 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.
@@ -449,7 +449,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': '7bb40bf80a1e94e24c29121214063d7baafdad8e',
+  'dawn_revision': '321c577d7732e0deae843267d84213477f03d1c2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -493,7 +493,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.
-  'cros_components_revision': 'b6cc7558fa4230d674f8808304f2d174e034bd9f',
+  'cros_components_revision': 'abc723520515cae61c172469d11b5c8b1cea1e2d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -849,7 +849,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '5d6852ae1087957cdf63633e42a5ee9e0164cbfd',
+    'a750aaa5d035918cb1e2c927521827a15c82c9c8',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1055,7 +1055,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '7UcP-gfaZsQlLtYH2gehhuV2jA8hQ6kOdWC_4ya_N0IC',
+          'version': 'x3LXBT0Dy8ROMd3aWRcLKHgL0a0c6siwpcA-jDz39V4C',
       },
     ],
     'condition': 'checkout_android',
@@ -1305,7 +1305,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '6d52aa08d983d20ead0713e01e1fa77131302332',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '698aeffe4942c5018875c07800e939a3cac87c27',
     'condition': 'checkout_src_internal',
   },
 
@@ -1817,7 +1817,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': '_AUNqTBtlUIMSIQEV31lcrlDaaUdwQdUUdp4BtPoOUMC',
+              'version': 'JUSda0InJf03iz7TOn_GUWgr-G_er-KNeju2rGW2NgQC',
           },
       ],
       'condition': 'checkout_android',
@@ -1962,7 +1962,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '03819a515332bd0ac6daf11ab13839bdd75eae7f',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f43ca8da0bd572622360f284730c1742af5feabe',
+    Var('webrtc_git') + '/src.git' + '@' + '675ef918a89db571aac879c3df28805e0077f436',
 
   # 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.
@@ -2129,7 +2129,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'HyKszgkgbdrFzP_4W2BjrX40Bd8fl3kAzUzzEkNGGu4C',
+        'version': 'TIRfzHKehsx2lzzUJ8ppda4U9xQ6rKaq0USMUmozQyUC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4251,7 +4251,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '5365862f786acddba08a3b38bee6b278569f086b',
+        '7d687f5d436610c2d0959561d1a720d72754637c',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index c40419e..1f1a8c81 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -845,11 +845,6 @@
              "EnableKioskLoginScreen",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Enables skipping of network screen.
-BASE_FEATURE(kEnableOobeNetworkScreenSkip,
-             "EnableOobeNetworkScreenSkip",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Enables showing notification after the password change for SAML users.
 BASE_FEATURE(kEnableSamlNotificationOnPasswordChangeSuccess,
              "EnableSamlNotificationOnPasswordChangeSuccess",
@@ -1568,7 +1563,7 @@
 // Enables IME button in the floating accessibility menu for the Kiosk session.
 BASE_FEATURE(kKioskEnableImeButton,
              "KioskEnableImeButton",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables to use lacros-chrome as the only web browser on ChromeOS.
 // This may not be allowed depending on user types and/or policies.
@@ -3673,10 +3668,6 @@
   return base::FeatureList::IsEnabled(kOobeSkipAssistant);
 }
 
-bool IsOobeNetworkScreenSkipEnabled() {
-  return base::FeatureList::IsEnabled(kEnableOobeNetworkScreenSkip);
-}
-
 bool IsOobeChoobeEnabled() {
   return base::FeatureList::IsEnabled(kOobeChoobe);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 1e2c4546..a9fb34f 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -253,8 +253,6 @@
 BASE_DECLARE_FEATURE(kEnableKioskEnrollmentInOobe);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableKioskLoginScreen);
 COMPONENT_EXPORT(ASH_CONSTANTS)
-BASE_DECLARE_FEATURE(kEnableOobeNetworkScreenSkip);
-COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kEnableSamlNotificationOnPasswordChangeSuccess);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableAllSystemWebApps);
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnablePerDeskZOrder);
@@ -1026,7 +1024,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsKioskLoginScreenEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsDeprecateOldKeyboardShortcutsAcceleratorEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeNetworkScreenSkipEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeQuickStartEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeRemoveShutdownButtonEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeTouchpadScrollEnabled();
diff --git a/ash/system/accessibility/floating_accessibility_controller_unittest.cc b/ash/system/accessibility/floating_accessibility_controller_unittest.cc
index 9a459d2..83eac74 100644
--- a/ash/system/accessibility/floating_accessibility_controller_unittest.cc
+++ b/ash/system/accessibility/floating_accessibility_controller_unittest.cc
@@ -212,22 +212,20 @@
 };
 
 TEST_F(FloatingAccessibilityControllerTest, ImeButtonNotShowWhenDisabled) {
+  features_.InitAndDisableFeature(features::kKioskEnableImeButton);
+
   SetUpVisibleMenu();
 
   EXPECT_FALSE(IsButtonVisible(FloatingAccessibilityView::ButtonId::kIme));
 }
 
 TEST_F(FloatingAccessibilityControllerTest, ImeButtonShownWhenEnabled) {
-  features_.InitAndEnableFeature(features::kKioskEnableImeButton);
-
   SetUpVisibleMenu();
 
   EXPECT_TRUE(IsButtonVisible(FloatingAccessibilityView::ButtonId::kIme));
 }
 
 TEST_F(FloatingAccessibilityControllerTest, ImeButtonHiddenWhenSingleLanguage) {
-  features_.InitAndEnableFeature(features::kKioskEnableImeButton);
-
   SetSingleAvailableIme();
   SetUpVisibleMenu();
 
@@ -235,8 +233,6 @@
 }
 
 TEST_F(FloatingAccessibilityControllerTest, KioskImeTrayVisibility) {
-  features_.InitAndEnableFeature(features::kKioskEnableImeButton);
-
   SetUpVisibleMenu();
 
   // Tray bubble is visible when  a user taps on the IME icon.
@@ -249,16 +245,12 @@
 }
 
 TEST_F(FloatingAccessibilityControllerTest, KioskImeTrayBottomButtons) {
-  features_.InitAndEnableFeature(features::kKioskEnableImeButton);
-
   SetUpVisibleMenu();
   EXPECT_FALSE(GetImeTray()->AnyBottomButtonShownForTest());
 }
 
 TEST_F(FloatingAccessibilityControllerTest,
        ImeTrayNotOverlapWithFloatingBubble) {
-  features_.InitAndEnableFeature(features::kKioskEnableImeButton);
-
   SetUpVisibleMenu();
 
   // Tray bubble is visible when  a user taps on the IME icon.
@@ -631,7 +623,9 @@
   EXPECT_EQ(GetMenuViewBounds(), original_bounds);
 }
 
-TEST_F(FloatingAccessibilityControllerTest, AccelatorFocusMenu) {
+TEST_F(FloatingAccessibilityControllerTest, AcceleratorFocusMenuImeDisabled) {
+  // The IME menu is not shown for a single language.
+  SetSingleAvailableIme();
   SetUpVisibleMenu();
 
   ASSERT_TRUE(widget());
diff --git a/base/allocator/dispatcher/dispatcher_unittest.cc b/base/allocator/dispatcher/dispatcher_unittest.cc
index 60f5227..700a12a7 100644
--- a/base/allocator/dispatcher/dispatcher_unittest.cc
+++ b/base/allocator/dispatcher/dispatcher_unittest.cc
@@ -99,7 +99,7 @@
 // because it makes PartitionAlloc take a different path that doesn't provide
 // notifications to observer hooks.
 struct PartitionAllocator {
-  void* Alloc(size_t size) { return alloc_.AllocWithFlags(0, size, nullptr); }
+  void* Alloc(size_t size) { return alloc_.AllocInline(size, nullptr); }
   void Free(void* data) { alloc_.Free(data); }
   ~PartitionAllocator() {
     // Use |DisallowLeaks| to confirm that there is no memory allocated and
diff --git a/base/allocator/partition_allocator/PartitionAlloc.md b/base/allocator/partition_allocator/PartitionAlloc.md
index f8390f2..146eec5c 100644
--- a/base/allocator/partition_allocator/PartitionAlloc.md
+++ b/base/allocator/partition_allocator/PartitionAlloc.md
@@ -81,7 +81,7 @@
 64-bit systems, and 8B on 32-bit).
 
 PartitionAlloc also supports higher levels of alignment, that can be requested
-via `PartitionAlloc::AlignedAllocWithFlags()` or platform-specific APIs (such as
+via `PartitionAlloc::AlignedAlloc()` or platform-specific APIs (such as
 `posix_memalign()`). The requested
 alignment has to be a power of two. PartitionAlloc reserves the right to round
 up the requested size to the nearest power of two, greater than or equal to the
diff --git a/base/allocator/partition_allocator/hardening_unittest.cc b/base/allocator/partition_allocator/hardening_unittest.cc
index 7e33a617..b8afeb5 100644
--- a/base/allocator/partition_allocator/hardening_unittest.cc
+++ b/base/allocator/partition_allocator/hardening_unittest.cc
@@ -106,7 +106,7 @@
   root.UncapEmptySlotSpanMemoryForTesting();
 
   uintptr_t* zero_vector = reinterpret_cast<uintptr_t*>(
-      root.AllocWithFlags(AllocFlags::kZeroFill, 100 * sizeof(uintptr_t), ""));
+      root.Alloc<AllocFlags::kZeroFill>(100 * sizeof(uintptr_t), ""));
   ASSERT_TRUE(zero_vector);
   // Pointer to the middle of an existing allocation.
   uintptr_t* to_corrupt = zero_vector + 20;
diff --git a/base/allocator/partition_allocator/partition_alloc_constants.h b/base/allocator/partition_allocator/partition_alloc_constants.h
index 24e2dcb..c52246a 100644
--- a/base/allocator/partition_allocator/partition_alloc_constants.h
+++ b/base/allocator/partition_allocator/partition_alloc_constants.h
@@ -25,8 +25,8 @@
 
 namespace partition_alloc {
 
-// Bit flag constants used as `flag` argument of PartitionRoot::AllocWithFlags,
-// AlignedAllocWithFlags, etc.
+// Bit flag constants used as `flag` argument of PartitionRoot::Alloc<flags>,
+// AlignedAlloc, etc.
 struct AllocFlags {
   static constexpr unsigned int kReturnNull = 1 << 0;
   static constexpr unsigned int kZeroFill = 1 << 1;
@@ -420,7 +420,7 @@
   return (1UL << 31) - kSuperPageSize;
 }
 
-// Max alignment supported by AlignedAllocWithFlags().
+// Max alignment supported by AlignedAlloc().
 // kSuperPageSize alignment can't be easily supported, because each super page
 // starts with guard pages & metadata.
 constexpr size_t kMaxSupportedAlignment = kSuperPageSize / 2;
diff --git a/base/allocator/partition_allocator/partition_alloc_perftest.cc b/base/allocator/partition_allocator/partition_alloc_perftest.cc
index b40c22c..3659c70 100644
--- a/base/allocator/partition_allocator/partition_alloc_perftest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_perftest.cc
@@ -96,7 +96,7 @@
   ~PartitionAllocator() override { alloc_.DestructForTesting(); }
 
   void* Alloc(size_t size) override {
-    return alloc_.AllocWithFlagsNoHooks(0, size, PartitionPageSize());
+    return alloc_.AllocNoHooks(size, PartitionPageSize());
   }
   void Free(void* data) override {
     // Even though it's easy to invoke the fast path with alloc_.FreeNoHooks(),
@@ -122,8 +122,7 @@
   ~PartitionAllocatorWithThreadCache() override = default;
 
   void* Alloc(size_t size) override {
-    return allocator_.root()->AllocWithFlagsNoHooks(0, size,
-                                                    PartitionPageSize());
+    return allocator_.root()->AllocNoHooks(size, PartitionPageSize());
   }
   void Free(void* data) override {
     // Even though it's easy to invoke the fast path with alloc_.Free(),
@@ -159,7 +158,7 @@
   }
 
   void* Alloc(size_t size) override {
-    return alloc_.AllocWithFlags(0, size, nullptr);
+    return alloc_.AllocInline(size, nullptr);
   }
 
   void Free(void* data) override {
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index 4c4af1d..cee5972 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -159,15 +159,14 @@
 };
 constexpr size_t kTestSizesCount = std::size(kTestSizes);
 
-void AllocateRandomly(partition_alloc::PartitionRoot* root,
-                      size_t count,
-                      unsigned int flags) {
+template <unsigned int flags>
+void AllocateRandomly(partition_alloc::PartitionRoot* root, size_t count) {
   std::vector<void*> allocations(count, nullptr);
   for (size_t i = 0; i < count; ++i) {
     const size_t size =
         kTestSizes[partition_alloc::internal::base::RandGenerator(
             kTestSizesCount)];
-    allocations[i] = root->AllocWithFlags(flags, size, nullptr);
+    allocations[i] = root->Alloc<flags>(size, nullptr);
     EXPECT_NE(nullptr, allocations[i]) << " size: " << size << " i: " << i;
   }
 
@@ -388,7 +387,7 @@
           PartitionOptions {
 #if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
     BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
-            // AlignedAllocWithFlags() can't be called when BRP is in the
+            // AlignedAlloc() can't be called when BRP is in the
             // "before allocation" mode, because this mode adds extras before
             // the allocation. Extras after the allocation are ok.
             .aligned_alloc = PartitionOptions::kAllowed,
@@ -541,8 +540,8 @@
   }
 
   enum ReturnNullTestMode {
-    kPartitionAllocWithFlags,
-    kPartitionReallocWithFlags,
+    kPartitionAlloc,
+    kPartitionRealloc,
     kPartitionRootTryRealloc,
   };
 
@@ -567,21 +566,21 @@
 
     for (i = 0; i < num_allocations; ++i) {
       switch (mode) {
-        case kPartitionAllocWithFlags: {
-          ptrs[i] = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull,
-                                                     alloc_size, type_name);
+        case kPartitionAlloc: {
+          ptrs[i] = allocator.root()->Alloc<AllocFlags::kReturnNull>(alloc_size,
+                                                                     type_name);
           break;
         }
-        case kPartitionReallocWithFlags: {
-          ptrs[i] = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull, 1,
-                                                     type_name);
-          ptrs[i] = allocator.root()->ReallocWithFlags(
-              AllocFlags::kReturnNull, ptrs[i], alloc_size, type_name);
+        case kPartitionRealloc: {
+          ptrs[i] =
+              allocator.root()->Alloc<AllocFlags::kReturnNull>(1, type_name);
+          ptrs[i] = allocator.root()->Realloc<AllocFlags::kReturnNull>(
+              ptrs[i], alloc_size, type_name);
           break;
         }
         case kPartitionRootTryRealloc: {
-          ptrs[i] = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull, 1,
-                                                     type_name);
+          ptrs[i] =
+              allocator.root()->Alloc<AllocFlags::kReturnNull>(1, type_name);
           ptrs[i] =
               allocator.root()->TryRealloc(ptrs[i], alloc_size, type_name);
         }
@@ -591,8 +590,8 @@
         EXPECT_TRUE(ptrs[0]);
       }
       if (!ptrs[i]) {
-        ptrs[i] = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull,
-                                                   alloc_size, type_name);
+        ptrs[i] = allocator.root()->Alloc<AllocFlags::kReturnNull>(alloc_size,
+                                                                   type_name);
         EXPECT_FALSE(ptrs[i]);
         break;
       }
@@ -606,8 +605,8 @@
     // check that freeing memory also works correctly after a failed allocation.
     for (--i; i >= 0; --i) {
       allocator.root()->Free(ptrs[i]);
-      ptrs[i] = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull,
-                                                 alloc_size, type_name);
+      ptrs[i] = allocator.root()->Alloc<AllocFlags::kReturnNull>(alloc_size,
+                                                                 type_name);
       EXPECT_TRUE(ptrs[i]);
       allocator.root()->Free(ptrs[i]);
     }
@@ -1284,9 +1283,8 @@
     allocator.root()->Free(nullptr);
 
     // Do we correctly get a null for a failed allocation?
-    EXPECT_EQ(nullptr,
-              allocator.root()->AllocWithFlags(
-                  AllocFlags::kReturnNull, 3u * 1024 * 1024 * 1024, type_name));
+    EXPECT_EQ(nullptr, allocator.root()->Alloc<AllocFlags::kReturnNull>(
+                           3u * 1024 * 1024 * 1024, type_name));
   }
 }
 
@@ -1813,8 +1811,7 @@
     // 64-bit systems), even if the alignment padding is taken out.
     size_t size = 10 * kSuperPageSize + SystemPageSize() - 42;
     ASSERT_GT(size, kMaxBucketed);
-    void* ptr =
-        allocator.root()->AllocWithFlagsInternal(0, size, alignment, type_name);
+    void* ptr = allocator.root()->AllocInternal<0>(size, alignment, type_name);
     uintptr_t slot_start = allocator.root()->ObjectToSlotStart(ptr);
     size_t actual_capacity =
         allocator.root()->AllocationCapacityFromSlotStart(slot_start);
@@ -1861,8 +1858,8 @@
   // boundary.
   size_t size = 2 * kSuperPageSize - kMaxSupportedAlignment + SystemPageSize();
   ASSERT_GT(size, kMaxBucketed);
-  void* ptr = allocator.root()->AllocWithFlagsInternal(
-      0, size, kMaxSupportedAlignment, type_name);
+  void* ptr = allocator.root()->AllocInternal<0>(size, kMaxSupportedAlignment,
+                                                 type_name);
   // Reallocating with the same size will actually relocate, because without a
   // need for alignment we can downsize the reservation significantly.
   void* ptr2 = allocator.root()->Realloc(ptr, size, type_name);
@@ -1874,8 +1871,8 @@
   // shrinking.
   size = 10 * kSuperPageSize - kMaxSupportedAlignment + SystemPageSize();
   ASSERT_GT(size, kMaxBucketed);
-  ptr = allocator.root()->AllocWithFlagsInternal(
-      0, size, kMaxSupportedAlignment, type_name);
+  ptr = allocator.root()->AllocInternal<0>(size, kMaxSupportedAlignment,
+                                           type_name);
   ptr2 = allocator.root()->Realloc(ptr, size, type_name);
   EXPECT_EQ(ptr, ptr2);
   allocator.root()->Free(ptr2);
@@ -2443,7 +2440,7 @@
   // A direct-mapped allocation size.
   size_t direct_map_size = 32 * 1024 * 1024;
   ASSERT_GT(direct_map_size, kMaxBucketed);
-  EXPECT_DEATH(DoReturnNullTest(direct_map_size, kPartitionAllocWithFlags),
+  EXPECT_DEATH(DoReturnNullTest(direct_map_size, kPartitionAlloc),
                "Passed DoReturnNullTest");
 }
 
@@ -2451,7 +2448,7 @@
 TEST_P(PartitionAllocDeathTest, MAYBE_RepeatedReallocReturnNullDirect) {
   size_t direct_map_size = 32 * 1024 * 1024;
   ASSERT_GT(direct_map_size, kMaxBucketed);
-  EXPECT_DEATH(DoReturnNullTest(direct_map_size, kPartitionReallocWithFlags),
+  EXPECT_DEATH(DoReturnNullTest(direct_map_size, kPartitionRealloc),
                "Passed DoReturnNullTest");
 }
 
@@ -2473,7 +2470,7 @@
   size_t single_slot_size = 512 * 1024;
   ASSERT_GT(single_slot_size, MaxRegularSlotSpanSize());
   ASSERT_LE(single_slot_size, kMaxBucketed);
-  EXPECT_DEATH(DoReturnNullTest(single_slot_size, kPartitionAllocWithFlags),
+  EXPECT_DEATH(DoReturnNullTest(single_slot_size, kPartitionAlloc),
                "Passed DoReturnNullTest");
 }
 
@@ -2482,7 +2479,7 @@
   size_t single_slot_size = 512 * 1024;
   ASSERT_GT(single_slot_size, MaxRegularSlotSpanSize());
   ASSERT_LE(single_slot_size, kMaxBucketed);
-  EXPECT_DEATH(DoReturnNullTest(single_slot_size, kPartitionReallocWithFlags),
+  EXPECT_DEATH(DoReturnNullTest(single_slot_size, kPartitionRealloc),
                "Passed DoReturnNullTest");
 }
 
@@ -3626,7 +3623,7 @@
       std::numeric_limits<size_t>::max();
   for (size_t size : kTestSizes) {
     char* p = static_cast<char*>(
-        allocator.root()->AllocWithFlags(AllocFlags::kZeroFill, size, nullptr));
+        allocator.root()->Alloc<AllocFlags::kZeroFill>(size, nullptr));
     size_t non_zero_position = kAllZerosSentinel;
     for (size_t i = 0; i < size; ++i) {
       if (0 != p[i]) {
@@ -3641,7 +3638,7 @@
 
   for (int i = 0; i < 10; ++i) {
     SCOPED_TRACE(i);
-    AllocateRandomly(allocator.root(), 250, AllocFlags::kZeroFill);
+    AllocateRandomly<AllocFlags::kZeroFill>(allocator.root(), 250);
   }
 }
 
@@ -3653,11 +3650,11 @@
   size_t kDesiredSize = 983100;
   ASSERT_GT(kInitialSize, kMaxBucketed);
   ASSERT_GT(kDesiredSize, kMaxBucketed);
-  void* ptr = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull,
-                                               kInitialSize, nullptr);
+  void* ptr =
+      allocator.root()->Alloc<AllocFlags::kReturnNull>(kInitialSize, nullptr);
   ASSERT_NE(nullptr, ptr);
-  ptr = allocator.root()->ReallocWithFlags(AllocFlags::kReturnNull, ptr,
-                                           kDesiredSize, nullptr);
+  ptr = allocator.root()->Realloc<AllocFlags::kReturnNull>(ptr, kDesiredSize,
+                                                           nullptr);
   ASSERT_NE(nullptr, ptr);
   memset(ptr, 0xbd, kDesiredSize);
   allocator.root()->Free(ptr);
@@ -3699,8 +3696,8 @@
         return false;
       });
 
-  void* ptr = allocator.root()->AllocWithFlags(
-      AllocFlags::kReturnNull, kOverriddenSize, kOverriddenType);
+  void* ptr = allocator.root()->Alloc<AllocFlags::kReturnNull>(kOverriddenSize,
+                                                               kOverriddenType);
   ASSERT_EQ(ptr, overridden_allocation);
 
   allocator.root()->Free(ptr);
@@ -3709,8 +3706,7 @@
   // overridden_allocation has not actually been freed so we can now immediately
   // realloc it.
   free_called = false;
-  ptr = allocator.root()->ReallocWithFlags(AllocFlags::kReturnNull, ptr, 1,
-                                           nullptr);
+  ptr = allocator.root()->Realloc<AllocFlags::kReturnNull>(ptr, 1, nullptr);
   ASSERT_NE(ptr, nullptr);
   EXPECT_NE(ptr, overridden_allocation);
   EXPECT_TRUE(free_called);
@@ -3798,7 +3794,7 @@
   std::vector<void*> allocated_ptrs;
 
   for (int index = 0; index < 3; index++) {
-    void* ptr = root->AlignedAllocWithFlags(0, alignment, size);
+    void* ptr = root->AlignedAlloc(alignment, size);
     ASSERT_TRUE(ptr);
     allocated_ptrs.push_back(ptr);
     EXPECT_EQ(0ull, UntagPtr(ptr) % alignment)
@@ -4105,8 +4101,8 @@
       // For direct map, we commit only as many pages as needed.
       size_t aligned_size = partition_alloc::internal::base::bits::AlignUp(
           huge_size, SystemPageSize());
-      ptr = root.AllocWithFlagsInternal(
-          0, huge_size - ExtraAllocSize(allocator), alignment, type_name);
+      ptr = root.AllocInternal<0>(huge_size - ExtraAllocSize(allocator),
+                                  alignment, type_name);
       expected_committed_size += aligned_size;
       expected_max_committed_size =
           std::max(expected_max_committed_size, expected_committed_size);
@@ -4893,8 +4889,8 @@
 TEST_P(PartitionAllocTest, CrossPartitionRootRealloc) {
   // Size is large enough to satisfy it from a single-slot slot span
   size_t test_size = MaxRegularSlotSpanSize() - ExtraAllocSize(allocator);
-  void* ptr = allocator.root()->AllocWithFlags(AllocFlags::kReturnNull,
-                                               test_size, nullptr);
+  void* ptr =
+      allocator.root()->Alloc<AllocFlags::kReturnNull>(test_size, nullptr);
   EXPECT_TRUE(ptr);
 
   // Create new root and call PurgeMemory to simulate ConfigurePartitions().
@@ -4907,8 +4903,8 @@
       PartitionTestOptions{.set_bucket_distribution = true});
 
   // Realloc from |allocator.root()| into |new_root|.
-  void* ptr2 = new_root->ReallocWithFlags(AllocFlags::kReturnNull, ptr,
-                                          test_size + 1024, nullptr);
+  void* ptr2 = new_root->Realloc<AllocFlags::kReturnNull>(ptr, test_size + 1024,
+                                                          nullptr);
   EXPECT_TRUE(ptr2);
   PA_EXPECT_PTR_NE(ptr, ptr2);
 }
@@ -4917,24 +4913,25 @@
   size_t allocation_size = 64;
   // The very first allocation is never a fast path one, since it needs a new
   // super page and a new partition page.
-  EXPECT_FALSE(allocator.root()->AllocWithFlags(
-      AllocFlags::kFastPathOrReturnNull, allocation_size, ""));
-  void* ptr = allocator.root()->AllocWithFlags(0, allocation_size, "");
+  EXPECT_FALSE(allocator.root()->Alloc<AllocFlags::kFastPathOrReturnNull>(
+      allocation_size, ""));
+  void* ptr = allocator.root()->Alloc(allocation_size, "");
   ASSERT_TRUE(ptr);
 
   // Next one is, since the partition page has been activated.
-  void* ptr2 = allocator.root()->AllocWithFlags(
-      AllocFlags::kFastPathOrReturnNull, allocation_size, "");
+  void* ptr2 = allocator.root()->Alloc<AllocFlags::kFastPathOrReturnNull>(
+      allocation_size, "");
   EXPECT_TRUE(ptr2);
 
   // First allocation of a different bucket is slow.
-  EXPECT_FALSE(allocator.root()->AllocWithFlags(
-      AllocFlags::kFastPathOrReturnNull, 2 * allocation_size, ""));
+  EXPECT_FALSE(allocator.root()->Alloc<AllocFlags::kFastPathOrReturnNull>(
+      2 * allocation_size, ""));
 
   size_t allocated_size = 2 * allocation_size;
   std::vector<void*> ptrs;
-  while (void* new_ptr = allocator.root()->AllocWithFlags(
-             AllocFlags::kFastPathOrReturnNull, allocation_size, "")) {
+  while (void* new_ptr =
+             allocator.root()->Alloc<AllocFlags::kFastPathOrReturnNull>(
+                 allocation_size, "")) {
     ptrs.push_back(new_ptr);
     allocated_size += allocation_size;
   }
diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc
index 0b0d8bd..e00088b 100644
--- a/base/allocator/partition_allocator/partition_root.cc
+++ b/base/allocator/partition_allocator/partition_root.cc
@@ -1343,101 +1343,6 @@
   return object;
 }
 
-void* PartitionRoot::ReallocWithFlags(unsigned int flags,
-                                      void* ptr,
-                                      size_t new_size,
-                                      const char* type_name) {
-#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-  CHECK_MAX_SIZE_OR_RETURN_NULLPTR(new_size, flags);
-  void* result = realloc(ptr, new_size);
-  PA_CHECK(result || flags & AllocFlags::kReturnNull);
-  return result;
-#else
-  bool no_hooks = flags & AllocFlags::kNoHooks;
-  if (PA_UNLIKELY(!ptr)) {
-    return no_hooks
-               ? AllocWithFlagsNoHooks(flags, new_size,
-                                       internal::PartitionPageSize())
-               : AllocWithFlagsInternal(
-                     flags, new_size, internal::PartitionPageSize(), type_name);
-  }
-
-  if (PA_UNLIKELY(!new_size)) {
-    FreeInUnknownRoot(ptr);
-    return nullptr;
-  }
-
-  if (new_size > internal::MaxDirectMapped()) {
-    if (flags & AllocFlags::kReturnNull) {
-      return nullptr;
-    }
-    internal::PartitionExcessiveAllocationSize(new_size);
-  }
-
-  const bool hooks_enabled = PartitionAllocHooks::AreHooksEnabled();
-  bool overridden = false;
-  size_t old_usable_size;
-  if (!no_hooks && hooks_enabled) {
-    overridden = PartitionAllocHooks::ReallocOverrideHookIfEnabled(
-        &old_usable_size, ptr);
-  }
-  if (PA_LIKELY(!overridden)) {
-    // |ptr| may have been allocated in another root.
-    SlotSpan* slot_span = SlotSpan::FromObject(ptr);
-    auto* old_root = PartitionRoot::FromSlotSpan(slot_span);
-    bool success = false;
-    bool tried_in_place_for_direct_map = false;
-    {
-      ::partition_alloc::internal::ScopedGuard guard{
-          internal::PartitionRootLock(old_root)};
-      // TODO(crbug.com/1257655): See if we can afford to make this a CHECK.
-      DCheckIsValidSlotSpan(slot_span);
-      old_usable_size = old_root->GetSlotUsableSize(slot_span);
-
-      if (PA_UNLIKELY(slot_span->bucket->is_direct_mapped())) {
-        tried_in_place_for_direct_map = true;
-        // We may be able to perform the realloc in place by changing the
-        // accessibility of memory pages and, if reducing the size, decommitting
-        // them.
-        success = old_root->TryReallocInPlaceForDirectMap(slot_span, new_size);
-      }
-    }
-    if (success) {
-      if (PA_UNLIKELY(!no_hooks && hooks_enabled)) {
-        PartitionAllocHooks::ReallocObserverHookIfEnabled(
-            CreateFreeNotificationData(ptr),
-            CreateAllocationNotificationData(ptr, new_size, type_name));
-      }
-      return ptr;
-    }
-
-    if (PA_LIKELY(!tried_in_place_for_direct_map)) {
-      if (old_root->TryReallocInPlaceForNormalBuckets(ptr, slot_span,
-                                                      new_size)) {
-        return ptr;
-      }
-    }
-  }
-
-  // This realloc cannot be resized in-place. Sadness.
-  void* ret =
-      no_hooks ? AllocWithFlagsNoHooks(flags, new_size,
-                                       internal::PartitionPageSize())
-               : AllocWithFlagsInternal(
-                     flags, new_size, internal::PartitionPageSize(), type_name);
-  if (!ret) {
-    if (flags & AllocFlags::kReturnNull) {
-      return nullptr;
-    }
-    internal::PartitionExcessiveAllocationSize(new_size);
-  }
-
-  memcpy(ret, ptr, std::min(old_usable_size, new_size));
-  FreeInUnknownRoot(ptr);  // Implicitly protects the old ptr on MTE systems.
-  return ret;
-#endif
-}
-
 void PartitionRoot::PurgeMemory(int flags) {
   {
     ::partition_alloc::internal::ScopedGuard guard{
@@ -1773,6 +1678,19 @@
   sort_active_slot_spans_ = new_value;
 }
 
+// Explicitly define common template instantiations to reduce compile time.
+#define EXPORT_TEMPLATE \
+  template PA_EXPORT_TEMPLATE_DEFINE(PA_COMPONENT_EXPORT(PARTITION_ALLOC))
+EXPORT_TEMPLATE void* PartitionRoot::Alloc<0>(size_t, const char*);
+EXPORT_TEMPLATE void* PartitionRoot::Alloc<AllocFlags::kReturnNull>(
+    size_t,
+    const char*);
+EXPORT_TEMPLATE void* PartitionRoot::Realloc<0>(void*, size_t, const char*);
+EXPORT_TEMPLATE void*
+PartitionRoot::Realloc<AllocFlags::kReturnNull>(void*, size_t, const char*);
+EXPORT_TEMPLATE void* PartitionRoot::AlignedAlloc<0>(size_t, size_t);
+#undef EXPORT_TEMPLATE
+
 static_assert(offsetof(PartitionRoot, sentinel_bucket) ==
                   offsetof(PartitionRoot, buckets) +
                       internal::kNumBuckets * sizeof(PartitionRoot::Bucket),
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
index 892521e4..7d57cd1 100644
--- a/base/allocator/partition_allocator/partition_root.h
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -34,6 +34,7 @@
 #include <atomic>
 #include <cstddef>
 #include <cstdint>
+#include <limits>
 
 #include "base/allocator/partition_allocator/address_pool_manager_types.h"
 #include "base/allocator/partition_allocator/allocation_guard.h"
@@ -47,6 +48,7 @@
 #include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
 #include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
 #include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
+#include "base/allocator/partition_allocator/partition_alloc_base/export_template.h"
 #include "base/allocator/partition_allocator/partition_alloc_base/notreached.h"
 #include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h"
 #include "base/allocator/partition_allocator/partition_alloc_base/time/time.h"
@@ -446,66 +448,104 @@
   //
   // NOTE: This is incompatible with anything that adds extras before the
   // returned pointer, such as ref-count.
-  PA_ALWAYS_INLINE void* AlignedAllocWithFlags(unsigned int flags,
-                                               size_t alignment,
-                                               size_t requested_size);
+  template <unsigned int flags = 0>
+  PA_NOINLINE void* AlignedAlloc(size_t alignment, size_t requested_size) {
+    return AlignedAllocInline<flags>(alignment, requested_size);
+  }
+  template <unsigned int flags = 0>
+  PA_ALWAYS_INLINE void* AlignedAllocInline(size_t alignment,
+                                            size_t requested_size);
 
   // PartitionAlloc supports multiple partitions, and hence multiple callers to
   // these functions. Setting PA_ALWAYS_INLINE bloats code, and can be
   // detrimental to performance, for instance if multiple callers are hot (by
   // increasing cache footprint). Set PA_NOINLINE on the "basic" top-level
   // functions to mitigate that for "vanilla" callers.
+  template <unsigned int flags = 0>
   PA_NOINLINE PA_MALLOC_FN void* Alloc(size_t requested_size,
                                        const char* type_name)
       PA_MALLOC_ALIGNED {
-    return AllocWithFlags(0, requested_size, type_name);
+    return AllocInline<flags>(requested_size, type_name);
   }
-  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocWithFlags(unsigned int flags,
-                                                     size_t requested_size,
-                                                     const char* type_name)
-      PA_MALLOC_ALIGNED;
-  // Same as |AllocWithFlags()|, but allows specifying |slot_span_alignment|. It
+  template <unsigned int flags = 0>
+  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocInline(size_t requested_size,
+                                                  const char* type_name)
+      PA_MALLOC_ALIGNED {
+    static_assert((flags & AllocFlags::kNoHooks) == 0);  // Internal only.
+    return AllocInternal<flags>(requested_size, internal::PartitionPageSize(),
+                                type_name);
+  }
+  // Same as |Alloc()|, but allows specifying |slot_span_alignment|. It
   // has to be a multiple of partition page size, greater than 0 and no greater
   // than kMaxSupportedAlignment. If it equals exactly 1 partition page, no
   // special action is taken as PartitionAlloc naturally guarantees this
   // alignment, otherwise a sub-optimal allocation strategy is used to
   // guarantee the higher-order alignment.
-  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocWithFlagsInternal(
-      unsigned int flags,
-      size_t requested_size,
-      size_t slot_span_alignment,
-      const char* type_name) PA_MALLOC_ALIGNED;
-  // Same as |AllocWithFlags()|, but bypasses the allocator hooks.
+  template <unsigned int flags>
+  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocInternal(size_t requested_size,
+                                                    size_t slot_span_alignment,
+                                                    const char* type_name)
+      PA_MALLOC_ALIGNED;
+  // Same as |Alloc()|, but bypasses the allocator hooks.
   //
-  // This is separate from AllocWithFlags() because other callers of
-  // AllocWithFlags() should not have the extra branch checking whether the
+  // This is separate from Alloc() because other callers of
+  // Alloc() should not have the extra branch checking whether the
   // hooks should be ignored or not. This is the same reason why |FreeNoHooks()|
   // exists. However, |AlignedAlloc()| and |Realloc()| have few callers, so
   // taking the extra branch in the non-malloc() case doesn't hurt. In addition,
   // for the malloc() case, the compiler correctly removes the branch, since
   // this is marked |PA_ALWAYS_INLINE|.
-  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocWithFlagsNoHooks(
-      unsigned int flags,
-      size_t requested_size,
-      size_t slot_span_alignment) PA_MALLOC_ALIGNED;
+  template <unsigned int flags = 0>
+  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocNoHooks(size_t requested_size,
+                                                   size_t slot_span_alignment)
+      PA_MALLOC_ALIGNED;
+  // Deprecated compatibility method.
+  // TODO(mikt): remove this once all third party usage is gone.
+  PA_ALWAYS_INLINE PA_MALLOC_FN void* AllocWithFlags(unsigned int flags,
+                                                     size_t requested_size,
+                                                     const char* type_name)
+      PA_MALLOC_ALIGNED {
+    // These conditional branching should be optimized away.
+    if (flags == (AllocFlags::kReturnNull)) {
+      return AllocInline<AllocFlags::kReturnNull>(requested_size, type_name);
+    } else if (flags == (AllocFlags::kZeroFill)) {
+      return AllocInline<AllocFlags::kZeroFill>(requested_size, type_name);
+    } else if (flags == (AllocFlags::kReturnNull | AllocFlags::kZeroFill)) {
+      return AllocInline<AllocFlags::kReturnNull | AllocFlags::kZeroFill>(
+          requested_size, type_name);
+    } else {
+      PA_CHECK(0);
+      PA_NOTREACHED();
+    }
+  }
 
+  template <unsigned int flags = 0>
   PA_NOINLINE void* Realloc(void* ptr,
                             size_t new_size,
                             const char* type_name) PA_MALLOC_ALIGNED {
-    return ReallocWithFlags(0, ptr, new_size, type_name);
+    return ReallocInline<flags>(ptr, new_size, type_name);
   }
-
+  template <unsigned int flags = 0>
+  PA_ALWAYS_INLINE void* ReallocInline(void* ptr,
+                                       size_t new_size,
+                                       const char* type_name) PA_MALLOC_ALIGNED;
   // Overload that may return nullptr if reallocation isn't possible. In this
   // case, |ptr| remains valid.
   PA_NOINLINE void* TryRealloc(void* ptr,
                                size_t new_size,
                                const char* type_name) PA_MALLOC_ALIGNED {
-    return ReallocWithFlags(AllocFlags::kReturnNull, ptr, new_size, type_name);
+    return ReallocInline<AllocFlags::kReturnNull>(ptr, new_size, type_name);
   }
+  // Deprecated compatibility method.
+  // TODO(mikt): remove this once all third party usage is gone.
   PA_NOINLINE void* ReallocWithFlags(unsigned int flags,
                                      void* ptr,
                                      size_t new_size,
-                                     const char* type_name) PA_MALLOC_ALIGNED;
+                                     const char* type_name) PA_MALLOC_ALIGNED {
+    PA_CHECK(flags == AllocFlags::kReturnNull);
+    return ReallocInline<AllocFlags::kReturnNull>(ptr, new_size, type_name);
+  }
+
   template <unsigned int flags = 0>
   PA_NOINLINE void Free(void* object);
   PA_ALWAYS_INLINE void FreeNoHooks(void* object);
@@ -730,7 +770,7 @@
     // There are known cases where allowing size 0 would lead to problems:
     // 1. If extras are present only before allocation (e.g. BRP ref-count), the
     //    extras will fill the entire kAlignment-sized slot, leading to
-    //    returning a pointer to the next slot. ReallocWithFlags() calls
+    //    returning a pointer to the next slot. Realloc() calls
     //    SlotSpanMetadata::FromObject() prior to subtracting extras, thus
     //    potentially getting a wrong slot span.
     // 2. If we put BRP ref-count in the previous slot, that slot may be free.
@@ -884,19 +924,19 @@
 
   // Allocates a memory slot, without initializing extras.
   //
-  // - |flags| are as in AllocWithFlags().
-  // - |raw_size| accommodates for extras on top of AllocWithFlags()'s
+  // - |flags| are as in Alloc().
+  // - |raw_size| accommodates for extras on top of Alloc()'s
   //   |requested_size|.
   // - |usable_size| and |is_already_zeroed| are output only. |usable_size| is
-  //   guaranteed to be larger or equal to AllocWithFlags()'s |requested_size|.
+  //   guaranteed to be larger or equal to Alloc()'s |requested_size|.
+  template <unsigned int flags>
   PA_ALWAYS_INLINE uintptr_t RawAlloc(Bucket* bucket,
-                                      unsigned int flags,
                                       size_t raw_size,
                                       size_t slot_span_alignment,
                                       size_t* usable_size,
                                       bool* is_already_zeroed);
+  template <unsigned int flags>
   PA_ALWAYS_INLINE uintptr_t AllocFromBucket(Bucket* bucket,
-                                             unsigned int flags,
                                              size_t raw_size,
                                              size_t slot_span_alignment,
                                              size_t* usable_size,
@@ -1123,9 +1163,9 @@
 
 }  // namespace internal
 
+template <unsigned int flags>
 PA_ALWAYS_INLINE uintptr_t
 PartitionRoot::AllocFromBucket(Bucket* bucket,
-                               unsigned int flags,
                                size_t raw_size,
                                size_t slot_span_alignment,
                                size_t* usable_size,
@@ -1439,7 +1479,7 @@
   // Note: ref-count and cookie can be 0-sized.
   //
   // For more context, see the other "Layout inside the slot" comment inside
-  // AllocWithFlagsNoHooks().
+  // AllocNoHooks().
 
   if (settings.use_cookie) {
     // Verify the cookie after the allocated region.
@@ -1877,32 +1917,24 @@
   }
 }
 
-PA_ALWAYS_INLINE void* PartitionRoot::AllocWithFlags(unsigned int flags,
-                                                     size_t requested_size,
-                                                     const char* type_name) {
-  return AllocWithFlagsInternal(flags, requested_size,
-                                internal::PartitionPageSize(), type_name);
-}
-
-PA_ALWAYS_INLINE void* PartitionRoot::AllocWithFlagsInternal(
-    unsigned int flags,
-    size_t requested_size,
-    size_t slot_span_alignment,
-    const char* type_name) {
+template <unsigned int flags>
+PA_ALWAYS_INLINE void* PartitionRoot::AllocInternal(size_t requested_size,
+                                                    size_t slot_span_alignment,
+                                                    const char* type_name) {
+  static_assert(flags < AllocFlags::kLastFlag << 1);
   PA_DCHECK(
       (slot_span_alignment >= internal::PartitionPageSize()) &&
       partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
 
-  PA_DCHECK(flags < AllocFlags::kLastFlag << 1);
   PA_DCHECK((flags & AllocFlags::kNoHooks) == 0);  // Internal only.
-  PA_DCHECK((flags & AllocFlags::kMemoryShouldBeTaggedForMte) ==
-            0);  // Internal only.
+  static_assert((flags & AllocFlags::kMemoryShouldBeTaggedForMte) ==
+                0);  // Internal only.
   PA_DCHECK(initialized);
 
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-  if (!(flags & AllocFlags::kNoMemoryToolOverride)) {
+  if constexpr (!(flags & AllocFlags::kNoMemoryToolOverride)) {
     CHECK_MAX_SIZE_OR_RETURN_NULLPTR(requested_size, flags);
-    const bool zero_fill = flags & AllocFlags::kZeroFill;
+    constexpr bool zero_fill = flags & AllocFlags::kZeroFill;
     void* result =
         zero_fill ? calloc(1, requested_size) : malloc(requested_size);
     PA_CHECK(result || flags & AllocFlags::kReturnNull);
@@ -1931,7 +1963,7 @@
     }
   }
 
-  object = AllocWithFlagsNoHooks(flags, requested_size, slot_span_alignment);
+  object = AllocNoHooks<flags>(requested_size, slot_span_alignment);
 
   if (PA_UNLIKELY(hooks_enabled)) {
     PartitionAllocHooks::AllocationObserverHookIfEnabled(
@@ -1941,10 +1973,10 @@
   return object;
 }
 
-PA_ALWAYS_INLINE void* PartitionRoot::AllocWithFlagsNoHooks(
-    unsigned int flags,
-    size_t requested_size,
-    size_t slot_span_alignment) {
+template <unsigned int flags>
+PA_ALWAYS_INLINE void* PartitionRoot::AllocNoHooks(size_t requested_size,
+                                                   size_t slot_span_alignment) {
+  static_assert(flags < AllocFlags::kLastFlag << 1);
   PA_DCHECK(
       (slot_span_alignment >= internal::PartitionPageSize()) &&
       partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
@@ -2019,13 +2051,13 @@
 #endif
     } else {
       slot_start =
-          RawAlloc(buckets + bucket_index, flags, raw_size, slot_span_alignment,
-                   &usable_size, &is_already_zeroed);
+          RawAlloc<flags>(buckets + bucket_index, raw_size, slot_span_alignment,
+                          &usable_size, &is_already_zeroed);
     }
   } else {
     slot_start =
-        RawAlloc(buckets + bucket_index, flags, raw_size, slot_span_alignment,
-                 &usable_size, &is_already_zeroed);
+        RawAlloc<flags>(buckets + bucket_index, raw_size, slot_span_alignment,
+                        &usable_size, &is_already_zeroed);
   }
 
   if (PA_UNLIKELY(!slot_start)) {
@@ -2091,9 +2123,9 @@
 
   // Fill the region kUninitializedByte (on debug builds, if not requested to 0)
   // or 0 (if requested and not 0 already).
-  bool zero_fill = flags & AllocFlags::kZeroFill;
+  constexpr bool zero_fill = flags & AllocFlags::kZeroFill;
   // PA_LIKELY: operator new() calls malloc(), not calloc().
-  if (PA_LIKELY(!zero_fill)) {
+  if constexpr (!zero_fill) {
     // memset() can be really expensive.
 #if BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON)
     internal::DebugMemset(object, internal::kUninitializedByte, usable_size);
@@ -2140,20 +2172,20 @@
   return object;
 }
 
+template <unsigned int flags>
 PA_ALWAYS_INLINE uintptr_t PartitionRoot::RawAlloc(Bucket* bucket,
-                                                   unsigned int flags,
                                                    size_t raw_size,
                                                    size_t slot_span_alignment,
                                                    size_t* usable_size,
                                                    bool* is_already_zeroed) {
   ::partition_alloc::internal::ScopedGuard guard{
       internal::PartitionRootLock(this)};
-  return AllocFromBucket(bucket, flags, raw_size, slot_span_alignment,
-                         usable_size, is_already_zeroed);
+  return AllocFromBucket<flags>(bucket, raw_size, slot_span_alignment,
+                                usable_size, is_already_zeroed);
 }
 
-PA_ALWAYS_INLINE void* PartitionRoot::AlignedAllocWithFlags(
-    unsigned int flags,
+template <unsigned int flags>
+PA_ALWAYS_INLINE void* PartitionRoot::AlignedAllocInline(
     size_t alignment,
     size_t requested_size) {
   // Aligned allocation support relies on the natural alignment guarantees of
@@ -2205,12 +2237,12 @@
                   raw_size - 1));
     }
     PA_DCHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(raw_size));
-    // Adjust back, because AllocWithFlagsNoHooks/Alloc will adjust it again.
+    // Adjust back, because AllocNoHooks/Alloc will adjust it again.
     adjusted_size = AdjustSizeForExtrasSubtract(raw_size);
 
     // Overflow check. adjusted_size must be larger or equal to requested_size.
     if (PA_UNLIKELY(adjusted_size < requested_size)) {
-      if (flags & AllocFlags::kReturnNull) {
+      if constexpr (flags & AllocFlags::kReturnNull) {
         return nullptr;
       }
       // OutOfMemoryDeathTest.AlignedAlloc requires
@@ -2226,11 +2258,10 @@
   // don't pass anything less, because it'll mess up callee's calculations.
   size_t slot_span_alignment =
       std::max(alignment, internal::PartitionPageSize());
-  bool no_hooks = flags & AllocFlags::kNoHooks;
-  void* object =
-      no_hooks
-          ? AllocWithFlagsNoHooks(0, adjusted_size, slot_span_alignment)
-          : AllocWithFlagsInternal(0, adjusted_size, slot_span_alignment, "");
+  constexpr bool no_hooks = flags & AllocFlags::kNoHooks;
+  void* object = no_hooks
+                     ? AllocNoHooks(adjusted_size, slot_span_alignment)
+                     : AllocInternal<0>(adjusted_size, slot_span_alignment, "");
 
   // |alignment| is a power of two, but the compiler doesn't necessarily know
   // that. A regular % operation is very slow, make sure to use the equivalent,
@@ -2241,6 +2272,99 @@
   return object;
 }
 
+template <unsigned int flags>
+void* PartitionRoot::ReallocInline(void* ptr,
+                                   size_t new_size,
+                                   const char* type_name) {
+#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+  CHECK_MAX_SIZE_OR_RETURN_NULLPTR(new_size, flags);
+  void* result = realloc(ptr, new_size);
+  PA_CHECK(result || flags & AllocFlags::kReturnNull);
+  return result;
+#else
+  constexpr bool no_hooks = flags & AllocFlags::kNoHooks;
+  if (PA_UNLIKELY(!ptr)) {
+    return no_hooks
+               ? AllocNoHooks<flags>(new_size, internal::PartitionPageSize())
+               : AllocInternal<flags>(new_size, internal::PartitionPageSize(),
+                                      type_name);
+  }
+
+  if (PA_UNLIKELY(!new_size)) {
+    FreeInUnknownRoot(ptr);
+    return nullptr;
+  }
+
+  if (new_size > internal::MaxDirectMapped()) {
+    if constexpr (flags & AllocFlags::kReturnNull) {
+      return nullptr;
+    }
+    internal::PartitionExcessiveAllocationSize(new_size);
+  }
+
+  const bool hooks_enabled = PartitionAllocHooks::AreHooksEnabled();
+  bool overridden = false;
+  size_t old_usable_size;
+  if (PA_UNLIKELY(!no_hooks && hooks_enabled)) {
+    overridden = PartitionAllocHooks::ReallocOverrideHookIfEnabled(
+        &old_usable_size, ptr);
+  }
+  if (PA_LIKELY(!overridden)) {
+    // |ptr| may have been allocated in another root.
+    SlotSpan* slot_span = SlotSpan::FromObject(ptr);
+    auto* old_root = PartitionRoot::FromSlotSpan(slot_span);
+    bool success = false;
+    bool tried_in_place_for_direct_map = false;
+    {
+      ::partition_alloc::internal::ScopedGuard guard{
+          internal::PartitionRootLock(old_root)};
+      // TODO(crbug.com/1257655): See if we can afford to make this a CHECK.
+      DCheckIsValidSlotSpan(slot_span);
+      old_usable_size = old_root->GetSlotUsableSize(slot_span);
+
+      if (PA_UNLIKELY(slot_span->bucket->is_direct_mapped())) {
+        tried_in_place_for_direct_map = true;
+        // We may be able to perform the realloc in place by changing the
+        // accessibility of memory pages and, if reducing the size, decommitting
+        // them.
+        success = old_root->TryReallocInPlaceForDirectMap(slot_span, new_size);
+      }
+    }
+    if (success) {
+      if (PA_UNLIKELY(!no_hooks && hooks_enabled)) {
+        PartitionAllocHooks::ReallocObserverHookIfEnabled(
+            CreateFreeNotificationData(ptr),
+            CreateAllocationNotificationData(ptr, new_size, type_name));
+      }
+      return ptr;
+    }
+
+    if (PA_LIKELY(!tried_in_place_for_direct_map)) {
+      if (old_root->TryReallocInPlaceForNormalBuckets(ptr, slot_span,
+                                                      new_size)) {
+        return ptr;
+      }
+    }
+  }
+
+  // This realloc cannot be resized in-place. Sadness.
+  void* ret = no_hooks
+                  ? AllocNoHooks<flags>(new_size, internal::PartitionPageSize())
+                  : AllocInternal<flags>(
+                        new_size, internal::PartitionPageSize(), type_name);
+  if (!ret) {
+    if constexpr (flags & AllocFlags::kReturnNull) {
+      return nullptr;
+    }
+    internal::PartitionExcessiveAllocationSize(new_size);
+  }
+
+  memcpy(ret, ptr, std::min(old_usable_size, new_size));
+  FreeInUnknownRoot(ptr);  // Implicitly protects the old ptr on MTE systems.
+  return ret;
+#endif
+}
+
 // Return the capacity of the underlying slot (adjusted for extras) that'd be
 // used to satisfy a request of |size|. This doesn't mean this capacity would be
 // readily available. It merely means that if an allocation happened with that
@@ -2284,6 +2408,20 @@
   return PA_LIKELY(settings.with_thread_cache) ? ThreadCache::Get() : nullptr;
 }
 
+// Explicitly declare common template instantiations to reduce compile time.
+#define EXPORT_TEMPLATE                       \
+  extern template PA_EXPORT_TEMPLATE_DECLARE( \
+      PA_COMPONENT_EXPORT(PARTITION_ALLOC))
+EXPORT_TEMPLATE void* PartitionRoot::Alloc<0>(size_t, const char*);
+EXPORT_TEMPLATE void* PartitionRoot::Alloc<AllocFlags::kReturnNull>(
+    size_t,
+    const char*);
+EXPORT_TEMPLATE void* PartitionRoot::Realloc<0>(void*, size_t, const char*);
+EXPORT_TEMPLATE void*
+PartitionRoot::Realloc<AllocFlags::kReturnNull>(void*, size_t, const char*);
+EXPORT_TEMPLATE void* PartitionRoot::AlignedAlloc<0>(size_t, size_t);
+#undef EXPORT_TEMPLATE
+
 #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
 // Usage in `raw_ptr.cc` is notable enough to merit a non-internal alias.
 using ::partition_alloc::internal::PartitionAllocGetSlotStartInBRPPool;
diff --git a/base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
index 98e5dfb6..c6035522 100644
--- a/base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -222,12 +222,13 @@
     PA_CHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(alignment));
     // TODO(bartekn): See if the compiler optimizes branches down the stack on
     // Mac, where PartitionPageSize() isn't constexpr.
-    return Allocator()->AllocWithFlagsNoHooks(
-        0, size, partition_alloc::PartitionPageSize());
+    return Allocator()->AllocNoHooks(size,
+                                     partition_alloc::PartitionPageSize());
   }
 
-  return AlignedAllocator()->AlignedAllocWithFlags(
-      partition_alloc::AllocFlags::kNoHooks, alignment, size);
+  return AlignedAllocator()
+      ->AlignedAllocInline<partition_alloc::AllocFlags::kNoHooks>(alignment,
+                                                                  size);
 }
 
 }  // namespace
@@ -236,17 +237,15 @@
 
 void* PartitionMalloc(const AllocatorDispatch*, size_t size, void* context) {
   partition_alloc::ScopedDisallowAllocations guard{};
-  return Allocator()->AllocWithFlagsNoHooks(
-      0, size, partition_alloc::PartitionPageSize());
+  return Allocator()->AllocNoHooks(size, partition_alloc::PartitionPageSize());
 }
 
 void* PartitionMallocUnchecked(const AllocatorDispatch*,
                                size_t size,
                                void* context) {
   partition_alloc::ScopedDisallowAllocations guard{};
-  return Allocator()->AllocWithFlagsNoHooks(
-      partition_alloc::AllocFlags::kReturnNull, size,
-      partition_alloc::PartitionPageSize());
+  return Allocator()->AllocNoHooks<partition_alloc::AllocFlags::kReturnNull>(
+      size, partition_alloc::PartitionPageSize());
 }
 
 void* PartitionCalloc(const AllocatorDispatch*,
@@ -256,9 +255,8 @@
   partition_alloc::ScopedDisallowAllocations guard{};
   const size_t total =
       partition_alloc::internal::base::CheckMul(n, size).ValueOrDie();
-  return Allocator()->AllocWithFlagsNoHooks(
-      partition_alloc::AllocFlags::kZeroFill, total,
-      partition_alloc::PartitionPageSize());
+  return Allocator()->AllocNoHooks<partition_alloc::AllocFlags::kZeroFill>(
+      total, partition_alloc::PartitionPageSize());
 }
 
 void* PartitionMemalign(const AllocatorDispatch*,
@@ -282,8 +280,7 @@
 // TODO(tasak): Expand the given memory block to the given size if possible.
 // This realloc always free the original memory block and allocates a new memory
 // block.
-// TODO(tasak): Implement PartitionRoot<thread_safe>::AlignedReallocWithFlags
-// and use it.
+// TODO(tasak): Implement PartitionRoot::AlignedRealloc and use it.
 void* PartitionAlignedRealloc(const AllocatorDispatch* dispatch,
                               void* address,
                               size_t size,
@@ -331,8 +328,8 @@
   }
 #endif  // BUILDFLAG(IS_APPLE)
 
-  return Allocator()->ReallocWithFlags(partition_alloc::AllocFlags::kNoHooks,
-                                       address, size, "");
+  return Allocator()->Realloc<partition_alloc::AllocFlags::kNoHooks>(address,
+                                                                     size, "");
 }
 
 #if BUILDFLAG(PA_IS_CAST_ANDROID)
diff --git a/base/allocator/partition_allocator/shim/nonscannable_allocator.cc b/base/allocator/partition_allocator/shim/nonscannable_allocator.cc
index fb71d18..b9dfce8 100644
--- a/base/allocator/partition_allocator/shim/nonscannable_allocator.cc
+++ b/base/allocator/partition_allocator/shim/nonscannable_allocator.cc
@@ -39,13 +39,13 @@
   // TODO(bikineev): Change to LIKELY once PCScan is enabled by default.
   if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
     PA_DCHECK(allocator_.get());
-    return allocator_->root()->AllocWithFlagsNoHooks(
-        0, size, partition_alloc::PartitionPageSize());
+    return allocator_->root()->AllocNoHooks(
+        size, partition_alloc::PartitionPageSize());
   }
 #endif  // BUILDFLAG(USE_STARSCAN)
   // Otherwise, dispatch to default partition.
   return allocator_shim::internal::PartitionAllocMalloc::Allocator()
-      ->AllocWithFlagsNoHooks(0, size, partition_alloc::PartitionPageSize());
+      ->AllocNoHooks(size, partition_alloc::PartitionPageSize());
 }
 
 template <bool quarantinable>
diff --git a/base/allocator/partition_allocator/starscan/metadata_allocator.h b/base/allocator/partition_allocator/starscan/metadata_allocator.h
index 2270838..5cee174c 100644
--- a/base/allocator/partition_allocator/starscan/metadata_allocator.h
+++ b/base/allocator/partition_allocator/starscan/metadata_allocator.h
@@ -45,9 +45,8 @@
   }
 
   value_type* allocate(size_t size) {
-    return static_cast<value_type*>(
-        PCScanMetadataAllocator().AllocWithFlagsNoHooks(
-            0, size * sizeof(value_type), PartitionPageSize()));
+    return static_cast<value_type*>(PCScanMetadataAllocator().AllocNoHooks(
+        size * sizeof(value_type), PartitionPageSize()));
   }
 
   void deallocate(value_type* ptr, size_t size) {
@@ -58,8 +57,7 @@
 // Inherit from it to make a class allocated on the metadata partition.
 struct AllocatedOnPCScanMetadataPartition {
   static void* operator new(size_t size) {
-    return PCScanMetadataAllocator().AllocWithFlagsNoHooks(0, size,
-                                                           PartitionPageSize());
+    return PCScanMetadataAllocator().AllocNoHooks(size, PartitionPageSize());
   }
   static void operator delete(void* ptr) {
     PCScanMetadataAllocator().FreeNoHooks(ptr);
@@ -68,9 +66,8 @@
 
 template <typename T, typename... Args>
 T* MakePCScanMetadata(Args&&... args) {
-  auto* memory =
-      static_cast<T*>(PCScanMetadataAllocator().AllocWithFlagsNoHooks(
-          0, sizeof(T), PartitionPageSize()));
+  auto* memory = static_cast<T*>(
+      PCScanMetadataAllocator().AllocNoHooks(sizeof(T), PartitionPageSize()));
   return new (memory) T(std::forward<Args>(args)...);
 }
 
diff --git a/base/allocator/partition_allocator/starscan/pcscan_unittest.cc b/base/allocator/partition_allocator/starscan/pcscan_unittest.cc
index ed5e36fa..7db02a6 100644
--- a/base/allocator/partition_allocator/starscan/pcscan_unittest.cc
+++ b/base/allocator/partition_allocator/starscan/pcscan_unittest.cc
@@ -142,7 +142,7 @@
   uintptr_t first = 0;
   uintptr_t last = 0;
   for (size_t i = 0; i < num_slots; ++i) {
-    void* ptr = root.AllocWithFlagsNoHooks(0, object_size, PartitionPageSize());
+    void* ptr = root.AllocNoHooks(object_size, PartitionPageSize());
     EXPECT_TRUE(ptr);
     if (i == 0) {
       first = root.ObjectToSlotStart(ptr);
@@ -194,8 +194,7 @@
   static List* Create(PartitionRoot& root, ListBase* next = nullptr) {
     List* list;
     if (Alignment) {
-      list = static_cast<List*>(
-          root.AlignedAllocWithFlags(0, Alignment, sizeof(List)));
+      list = static_cast<List*>(root.AlignedAlloc(Alignment, sizeof(List)));
     } else {
       list = static_cast<List*>(root.Alloc(sizeof(List), nullptr));
     }
@@ -389,7 +388,7 @@
   // This allocation must go through the slow path and call SetNewActivePage(),
   // which will flush the full page from the active page list.
   void* value_buffer =
-      root().AllocWithFlagsNoHooks(0, sizeof(ValueList), PartitionPageSize());
+      root().AllocNoHooks(sizeof(ValueList), PartitionPageSize());
 
   // Assert that the first and the last objects are in different slot spans but
   // in the same bucket.
@@ -694,7 +693,7 @@
   };
 
   auto* const pointers = static_cast<Pointers*>(
-      root().AllocWithFlagsNoHooks(0, sizeof(Pointers), PartitionPageSize()));
+      root().AllocNoHooks(sizeof(Pointers), PartitionPageSize()));
 
   // Converting to slot start strips MTE tag.
   const uintptr_t super_page =
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc
index f3f0ae6..2ceb669e 100644
--- a/base/allocator/partition_allocator/thread_cache.cc
+++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -460,9 +460,9 @@
 
   auto* bucket = root->buckets + PartitionRoot::SizeToBucketIndex(
                                      raw_size, root->GetBucketDistribution());
-  uintptr_t buffer = root->RawAlloc(bucket, AllocFlags::kZeroFill, raw_size,
-                                    internal::PartitionPageSize(), &usable_size,
-                                    &already_zeroed);
+  uintptr_t buffer = root->RawAlloc<AllocFlags::kZeroFill>(
+      bucket, raw_size, internal::PartitionPageSize(), &usable_size,
+      &already_zeroed);
   ThreadCache* tcache =
       new (internal::SlotStartAddr2Ptr(buffer)) ThreadCache(root);
 
@@ -615,11 +615,12 @@
     // |raw_size| is set to the slot size, as we don't know it. However, it is
     // only used for direct-mapped allocations and single-slot ones anyway,
     // which are not handled here.
-    uintptr_t slot_start = root_->AllocFromBucket(
-        &root_->buckets[bucket_index],
-        AllocFlags::kFastPathOrReturnNull | AllocFlags::kReturnNull,
-        root_->buckets[bucket_index].slot_size /* raw_size */,
-        internal::PartitionPageSize(), &usable_size, &is_already_zeroed);
+    uintptr_t slot_start =
+        root_->AllocFromBucket<AllocFlags::kFastPathOrReturnNull |
+                               AllocFlags::kReturnNull>(
+            &root_->buckets[bucket_index],
+            root_->buckets[bucket_index].slot_size /* raw_size */,
+            internal::PartitionPageSize(), &usable_size, &is_already_zeroed);
 
     // Either the previous allocation would require a slow path allocation, or
     // the central allocator is out of memory. If the bucket was filled with
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc
index e09acfa..b6aee774 100644
--- a/base/allocator/partition_allocator/thread_cache_unittest.cc
+++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -1411,7 +1411,7 @@
                                  {128, 2 * internal::PartitionPageSize()},
                                  {(4 << 20) + 1, 1 << 19}};
   for (auto [requested_size, alignment] : size_alignments) {
-    void* ptr = root()->AlignedAllocWithFlags(0, alignment, requested_size);
+    void* ptr = root()->AlignedAlloc(alignment, requested_size);
     ASSERT_TRUE(ptr);
     alloc_count++;
     total_size += root()->GetUsableSize(ptr);
diff --git a/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc b/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc
index 7c519e2..76dd31a 100644
--- a/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc
+++ b/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc
@@ -137,8 +137,8 @@
 // In the final use, we'll likely allow at least read access to the default
 // pkey.
 ISOLATED_FUNCTION uint64_t IsolatedAllocFree(void* arg) {
-  char* buf = (char*)isolated_globals.allocator->root()->AllocWithFlagsNoHooks(
-      0, 1024, partition_alloc::PartitionPageSize());
+  char* buf = (char*)isolated_globals.allocator->root()->AllocNoHooks(
+      1024, partition_alloc::PartitionPageSize());
   if (!buf) {
     return 0xffffffffffffffffllu;
   }
diff --git a/build/android/AndroidManifest.xml b/build/android/AndroidManifest.xml
index 821108f8..1d65b17 100644
--- a/build/android/AndroidManifest.xml
+++ b/build/android/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright (c) 2012 The Chromium Authors. All rights reserved.  Use of this
-  source code is governed by a BSD-style license that can be found in the
-  LICENSE file.
+  Copyright 2012 The Chromium Authors
+  Use of this source code is governed by a BSD-style license that can be
+  found in the LICENSE file.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/build/android/gradle/android.jinja b/build/android/gradle/android.jinja
index 3b66b97..1a9c0952 100644
--- a/build/android/gradle/android.jinja
+++ b/build/android/gradle/android.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2016 The Chromium Authors. All rights reserved. #}
+{# Copyright 2016 The Chromium Authors #}
 {# Use of this source code is governed by a BSD-style license that can be #}
 {# found in the LICENSE file. #}
 {% macro expand_sourceset(variables, prefix) %}
diff --git a/build/android/gradle/cmake.jinja b/build/android/gradle/cmake.jinja
index b7273880..f0d1bd7 100644
--- a/build/android/gradle/cmake.jinja
+++ b/build/android/gradle/cmake.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2018 The Chromium Authors. All rights reserved. #}
+{# 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. #}
 # Generated by //build/android/generate_gradle.py
diff --git a/build/android/gradle/dependencies.jinja b/build/android/gradle/dependencies.jinja
index 87bc312..e0da3ed 100644
--- a/build/android/gradle/dependencies.jinja
+++ b/build/android/gradle/dependencies.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2016 The Chromium Authors. All rights reserved. #}
+{# Copyright 2016 The Chromium Authors #}
 {# Use of this source code is governed by a BSD-style license that can be #}
 {# found in the LICENSE file. #}
 {% macro expand_deps(variables, prefix) %}
diff --git a/build/android/gradle/java.jinja b/build/android/gradle/java.jinja
index 61886e91..1cd7611d0 100644
--- a/build/android/gradle/java.jinja
+++ b/build/android/gradle/java.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2016 The Chromium Authors. All rights reserved. #}
+{# Copyright 2016 The Chromium Authors #}
 {# Use of this source code is governed by a BSD-style license that can be #}
 {# found in the LICENSE file. #}
 // Generated by //build/android/generate_gradle.py
diff --git a/build/android/gradle/manifest.jinja b/build/android/gradle/manifest.jinja
index dea7071e..4c39120 100644
--- a/build/android/gradle/manifest.jinja
+++ b/build/android/gradle/manifest.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2017 The Chromium Authors. All rights reserved. #}
+{# Copyright 2017 The Chromium Authors #}
 {# Use of this source code is governed by a BSD-style license that can be #}
 {# found in the LICENSE file. #}
 <?xml version="1.0" encoding="utf-8"?>
diff --git a/build/android/gradle/root.jinja b/build/android/gradle/root.jinja
index 8009ebe..a48b5fbaf 100644
--- a/build/android/gradle/root.jinja
+++ b/build/android/gradle/root.jinja
@@ -1,4 +1,4 @@
-{# Copyright 2016 The Chromium Authors. All rights reserved. #}
+{# Copyright 2016 The Chromium Authors #}
 {# Use of this source code is governed by a BSD-style license that can be #}
 {# found in the LICENSE file. #}
 // Generated by //build/android/generate_gradle.py
diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enum.py
index 9098cfc8..5225b89 100755
--- a/build/android/gyp/java_cpp_enum.py
+++ b/build/android/gyp/java_cpp_enum.py
@@ -349,7 +349,7 @@
 
 def GenerateOutput(source_path, enum_definition):
   template = Template("""
-// Copyright ${YEAR} The Chromium Authors. All rights reserved.
+// Copyright ${YEAR} The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/android/gyp/java_cpp_enum_tests.py b/build/android/gyp/java_cpp_enum_tests.py
index c14f2a0..6103b58 100755
--- a/build/android/gyp/java_cpp_enum_tests.py
+++ b/build/android/gyp/java_cpp_enum_tests.py
@@ -31,7 +31,7 @@
                                                  'really long.')])
     output = GenerateOutput('path/to/file', definition)
     expected = """
-// Copyright %d The Chromium Authors. All rights reserved.
+// Copyright %d The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/AlwaysInline.java b/build/android/java/src/org/chromium/build/annotations/AlwaysInline.java
index e79bfe77..1a4d1ff 100644
--- a/build/android/java/src/org/chromium/build/annotations/AlwaysInline.java
+++ b/build/android/java/src/org/chromium/build/annotations/AlwaysInline.java
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/CheckDiscard.java b/build/android/java/src/org/chromium/build/annotations/CheckDiscard.java
index 897067e..8b30c5d 100644
--- a/build/android/java/src/org/chromium/build/annotations/CheckDiscard.java
+++ b/build/android/java/src/org/chromium/build/annotations/CheckDiscard.java
@@ -1,4 +1,4 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java b/build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java
index 94c9fa3..e32a5fa 100644
--- a/build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java
+++ b/build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/DoNotInline.java b/build/android/java/src/org/chromium/build/annotations/DoNotInline.java
index 4dd19333..5d1bf02 100644
--- a/build/android/java/src/org/chromium/build/annotations/DoNotInline.java
+++ b/build/android/java/src/org/chromium/build/annotations/DoNotInline.java
@@ -1,4 +1,4 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java b/build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java
index ca8b2df..d2939f4f 100644
--- a/build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java
+++ b/build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/MainDex.java b/build/android/java/src/org/chromium/build/annotations/MainDex.java
index 9bb49f8..dc9695f 100644
--- a/build/android/java/src/org/chromium/build/annotations/MainDex.java
+++ b/build/android/java/src/org/chromium/build/annotations/MainDex.java
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
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 6b486f7b..120864c 100644
--- a/build/android/java/src/org/chromium/build/annotations/MockedInTests.java
+++ b/build/android/java/src/org/chromium/build/annotations/MockedInTests.java
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/build/android/java/src/org/chromium/build/annotations/UsedByReflection.java b/build/android/java/src/org/chromium/build/annotations/UsedByReflection.java
index f28f383..478627c 100644
--- a/build/android/java/src/org/chromium/build/annotations/UsedByReflection.java
+++ b/build/android/java/src/org/chromium/build/annotations/UsedByReflection.java
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 0a4ea11..daeaaf6b 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -26,6 +26,7 @@
   import("//build/config/chromecast_build.gni")
   import("//build/config/clang/clang.gni")
   import("//build/config/dcheck_always_on.gni")
+  import("//build/toolchain/siso.gni")
   import("//build_overrides/build.gni")
   import("abi.gni")
 
@@ -87,6 +88,12 @@
   assert(android_static_analysis == "on" || android_static_analysis == "off" ||
          android_static_analysis == "build_server")
 
+  # Build server modifies stamp files independently of builds.
+  # Siso is not well-suited for this use case.
+  assert(
+      !(android_static_analysis == "build_server" && use_siso),
+      "Siso doesn't support android_static_analysis=\"build_server\". Please set android_static_analysis=\"on\"")
+
   # This configuration has not bot coverage and has broken multiple times.
   # Warn against it.
   assert(!(enable_chrome_android_internal && skip_secondary_abi_for_cq))
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 373adf4..d22bdf0 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -471,7 +471,7 @@
   #
   # FooSwitches.java.tmpl
   #
-  # // Copyright {YEAR} The Chromium Authors. All rights reserved.
+  # // Copyright {YEAR} The Chromium Authors
   # // Use of this source code is governed by a BSD-style license that can be
   # // found in the LICENSE file.
   #
@@ -544,7 +544,7 @@
   #
   # FooFeatures.java.tmpl
   #
-  # // Copyright $YEAR The Chromium Authors. All rights reserved.
+  # // Copyright $YEAR The Chromium Authors
   # // Use of this source code is governed by a BSD-style license that can be
   # // found in the LICENSE file.
   #
diff --git a/build/config/ios/generate_umbrella_header.py b/build/config/ios/generate_umbrella_header.py
index 943c49c4..587ff17 100644
--- a/build/config/ios/generate_umbrella_header.py
+++ b/build/config/ios/generate_umbrella_header.py
@@ -12,7 +12,7 @@
 
 
 HEADER_TEMPLATE = string.Template('''\
-// Copyright $year The Chromium Authors. All rights reserved.
+// Copyright $year The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
diff --git a/build/config/loongarch64.gni b/build/config/loongarch64.gni
index 32aedbc..9a95ec91 100644
--- a/build/config/loongarch64.gni
+++ b/build/config/loongarch64.gni
@@ -1,4 +1,4 @@
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 
diff --git a/build/config/riscv.gni b/build/config/riscv.gni
index 5f93266..5a78490 100644
--- a/build/config/riscv.gni
+++ b/build/config/riscv.gni
@@ -1,4 +1,4 @@
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 
diff --git a/build/config/siso/android.star b/build/config/siso/android.star
index c2c108d..08bd3c0 100644
--- a/build/config/siso/android.star
+++ b/build/config/siso/android.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for Android builds."""
diff --git a/build/config/siso/blink_all.star b/build/config/siso/blink_all.star
index 46b50341..0ed0331b 100644
--- a/build/config/siso/blink_all.star
+++ b/build/config/siso/blink_all.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for blink scripts."""
diff --git a/build/config/siso/clang_all.star b/build/config/siso/clang_all.star
index 48cb9a1..673f6eb 100644
--- a/build/config/siso/clang_all.star
+++ b/build/config/siso/clang_all.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for clang."""
diff --git a/build/config/siso/clang_code_coverage_wrapper.star b/build/config/siso/clang_code_coverage_wrapper.star
index 3994c65b..d40b1704 100644
--- a/build/config/siso/clang_code_coverage_wrapper.star
+++ b/build/config/siso/clang_code_coverage_wrapper.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso config version of clang_code_coverage_wrapper.py"""
diff --git a/build/config/siso/clang_linux.star b/build/config/siso/clang_linux.star
index 6985fcb..dfb3e913 100644
--- a/build/config/siso/clang_linux.star
+++ b/build/config/siso/clang_linux.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for clang/linux."""
diff --git a/build/config/siso/clang_mac.star b/build/config/siso/clang_mac.star
index a25f08c..86ee558f 100644
--- a/build/config/siso/clang_mac.star
+++ b/build/config/siso/clang_mac.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for clang/mac."""
diff --git a/build/config/siso/clang_windows.star b/build/config/siso/clang_windows.star
index d11b3e63..25091a8b 100644
--- a/build/config/siso/clang_windows.star
+++ b/build/config/siso/clang_windows.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for clang-cl/windows."""
diff --git a/build/config/siso/config.star b/build/config/siso/config.star
index f1bd52c..e927638 100644
--- a/build/config/siso/config.star
+++ b/build/config/siso/config.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Config module for checking siso -config flags."""
diff --git a/build/config/siso/linux.star b/build/config/siso/linux.star
index 66bcb5f..095ecf6 100644
--- a/build/config/siso/linux.star
+++ b/build/config/siso/linux.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for linux."""
@@ -29,7 +29,6 @@
 __handlers.update(nacl.handlers)
 __handlers.update(nasm.handlers)
 __handlers.update(proto.handlers)
-__handlers.update(reproxy.handlers)
 
 def __disable_remote_b289968566(ctx, step_config):
     rule = {
@@ -64,22 +63,13 @@
 
 def __step_config(ctx, step_config):
     config.check(ctx)
-    step_config["platforms"] = {
+    step_config["platforms"].update({
         "default": {
             "OSFamily": "Linux",
             "container-image": "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:912808c295e578ccde53b0685bcd0d56c15d7a03e819dcce70694bfe3fdab35e",
             "label:action_default": "1",
         },
-        "large": {
-            "OSFamily": "Linux",
-            "container-image": "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:912808c295e578ccde53b0685bcd0d56c15d7a03e819dcce70694bfe3fdab35e",
-            # As of Jul 2023, the action_large pool uses n2-highmem-8 with 200GB of pd-ssd.
-            # The pool is intended for the following actions.
-            #  - slow actions that can benefit from multi-cores and/or faster disk I/O. e.g. link, mojo, generate bindings etc.
-            #  - actions that fail for OOM.
-            "label:action_large": "1",
-        },
-    }
+    })
 
     step_config = __disable_remote_b289968566(ctx, step_config)
 
@@ -92,9 +82,6 @@
     step_config = mojo.step_config(ctx, step_config)
     step_config = clang.step_config(ctx, step_config)
 
-    if reproxy.enabled(ctx):
-        step_config = reproxy.step_config(ctx, step_config)
-
     return step_config
 
 chromium = module(
diff --git a/build/config/siso/mac.star b/build/config/siso/mac.star
index d03440e..d1b8b01 100644
--- a/build/config/siso/mac.star
+++ b/build/config/siso/mac.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for macOS."""
@@ -7,21 +7,15 @@
 load("@builtin//struct.star", "module")
 load("./clang_mac.star", "clang")
 load("./config.star", "config")
-load("./reproxy.star", "reproxy")
 
 __filegroups = {}
 __filegroups.update(clang.filegroups)
 __handlers = {}
 __handlers.update(clang.handlers)
-__handlers.update(reproxy.handlers)
 
 def __step_config(ctx, step_config):
     config.check(ctx)
-    step_config["platforms"] = {}
-
     step_config = clang.step_config(ctx, step_config)
-    if reproxy.enabled(ctx):
-        step_config = reproxy.step_config(ctx, step_config)
     return step_config
 
 chromium = module(
diff --git a/build/config/siso/main.star b/build/config/siso/main.star
index 3928f3c..da5342676 100644
--- a/build/config/siso/main.star
+++ b/build/config/siso/main.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration main entry."""
@@ -10,6 +10,7 @@
 load("./blink_all.star", "blink_all")
 load("./linux.star", chromium_linux = "chromium")
 load("./mac.star", chromium_mac = "chromium")
+load("./reproxy.star", "reproxy")
 load("./simple.star", "simple")
 load("./windows.star", chromium_windows = "chromium")
 
@@ -25,13 +26,27 @@
         "windows": chromium_windows,
     }[runtime.os]
     step_config = {
-        "platforms": {},
+        "platforms": {
+            # Large workers are usually used for Python actions like generate bindings, mojo generators etc
+            # They can run on Linux workers.
+            "large": {
+                "OSFamily": "Linux",
+                "container-image": "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:912808c295e578ccde53b0685bcd0d56c15d7a03e819dcce70694bfe3fdab35e",
+                # As of Jul 2023, the action_large pool uses n2-highmem-8 with 200GB of pd-ssd.
+                # The pool is intended for the following actions.
+                #  - slow actions that can benefit from multi-cores and/or faster disk I/O. e.g. link, mojo, generate bindings etc.
+                #  - actions that fail for OOM.
+                "label:action_large": "1",
+            },
+        },
         "input_deps": {},
         "rules": [],
     }
     step_config = host.step_config(ctx, step_config)
     step_config = simple.step_config(ctx, step_config)
     step_config = blink_all.step_config(ctx, step_config)
+    if reproxy.enabled(ctx):
+        step_config = reproxy.step_config(ctx, step_config)
 
     #  Python actions may use an absolute path at the first argument.
     #  e.g. C:/src/depot_tools/bootstrap-2@3_8_10_chromium_26_bin/python3/bin/python3.exe
@@ -54,6 +69,7 @@
     handlers.update(blink_all.handlers)
     handlers.update(host.handlers)
     handlers.update(simple.handlers)
+    handlers.update(reproxy.handlers)
 
     return module(
         "config",
diff --git a/build/config/siso/mojo.star b/build/config/siso/mojo.star
index de8150f..db7f273d 100644
--- a/build/config/siso/mojo.star
+++ b/build/config/siso/mojo.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for mojo."""
@@ -159,6 +159,20 @@
             "output_local": True,
             "platform_ref": platform_ref,
         },
+        {
+            "name": "mojo/validate_typemap_config",
+            "command_prefix": "python3 ../../mojo/public/tools/bindings/validate_typemap_config.py",
+            "remote": True,
+            "output_local": True,
+            "platform_ref": platform_ref,
+        },
+        {
+            "name": "mojo/generate_type_mappings",
+            "command_prefix": "python3 ../../mojo/public/tools/bindings/generate_type_mappings.py",
+            "remote": True,
+            "output_local": True,
+            "platform_ref": platform_ref,
+        },
     ])
     return step_config
 
diff --git a/build/config/siso/nacl_linux.star b/build/config/siso/nacl_linux.star
index 12a56eb..5a61aa2 100644
--- a/build/config/siso/nacl_linux.star
+++ b/build/config/siso/nacl_linux.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for nacl/linux."""
diff --git a/build/config/siso/nasm_linux.star b/build/config/siso/nasm_linux.star
index 55f2778..5c9b8ece 100644
--- a/build/config/siso/nasm_linux.star
+++ b/build/config/siso/nasm_linux.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for nasm/linux."""
diff --git a/build/config/siso/reproxy.star b/build/config/siso/reproxy.star
index fe960028..d9a5401f 100644
--- a/build/config/siso/reproxy.star
+++ b/build/config/siso/reproxy.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for rewriting remote calls into reproxy config."""
diff --git a/build/config/siso/simple.star b/build/config/siso/simple.star
index 71b18d0..d09dad68 100644
--- a/build/config/siso/simple.star
+++ b/build/config/siso/simple.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for simple steps."""
diff --git a/build/config/siso/windows.star b/build/config/siso/windows.star
index a6b1296f..31141f4 100644
--- a/build/config/siso/windows.star
+++ b/build/config/siso/windows.star
@@ -1,5 +1,5 @@
 # -*- bazel-starlark -*-
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 """Siso configuration for Windows."""
@@ -7,21 +7,15 @@
 load("@builtin//struct.star", "module")
 load("./clang_windows.star", "clang")
 load("./config.star", "config")
-load("./reproxy.star", "reproxy")
 
 __filegroups = {}
 __filegroups.update(clang.filegroups)
 __handlers = {}
 __handlers.update(clang.handlers)
-__handlers.update(reproxy.handlers)
 
 def __step_config(ctx, step_config):
     config.check(ctx)
-    step_config["platforms"] = {}
-
     step_config = clang.step_config(ctx, step_config)
-    if reproxy.enabled(ctx):
-        step_config = reproxy.step_config(ctx, step_config)
     return step_config
 
 chromium = module(
diff --git a/build/private_code_test/BUILD.gn b/build/private_code_test/BUILD.gn
index 8fcdd540..d7a1efa 100644
--- a/build/private_code_test/BUILD.gn
+++ b/build/private_code_test/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 
diff --git a/build/private_code_test/private_code_test.gni b/build/private_code_test/private_code_test.gni
index 6ce82f0..23c7471f 100644
--- a/build/private_code_test/private_code_test.gni
+++ b/build/private_code_test/private_code_test.gni
@@ -1,4 +1,4 @@
-# Copyright 2023 The Chromium Authors. All rights reserved.
+# 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.
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 05b29a9..4cb1642 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=118
 MINOR=0
-BUILD=5980
+BUILD=5981
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index b248e89..0bbb5b86 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -314,6 +314,7 @@
       "//chrome/browser/android/browserservices/verification:java",
       "//chrome/browser/android/crypto:java",
       "//chrome/browser/android/customtabs/branding:java",
+      "//chrome/browser/android/intents:java",
       "//chrome/browser/android/lifecycle:java",
       "//chrome/browser/android/messages:java",
       "//chrome/browser/android/metrics:java",
@@ -920,6 +921,7 @@
       "//chrome/browser/android/crypto:java",
       "//chrome/browser/android/customtabs/branding:junit",
       "//chrome/browser/android/httpclient:junit_tests",
+      "//chrome/browser/android/intents:java",
       "//chrome/browser/android/lifecycle:java",
       "//chrome/browser/android/metrics:java",
       "//chrome/browser/autofill/android:java",
@@ -1280,6 +1282,7 @@
       "//cc:cc_java",
       "//chrome/android:chrome_java",
       "//chrome/browser/android/browserservices/intents:java",
+      "//chrome/browser/android/intents:java",
       "//chrome/browser/autofill/android:java",
       "//chrome/browser/flags:java",
       "//chrome/browser/profiles/android:java",
@@ -1375,6 +1378,7 @@
       "//chrome/browser/android/browserservices/intents:java",
       "//chrome/browser/android/browserservices/verification:java",
       "//chrome/browser/android/crypto:java",
+      "//chrome/browser/android/intents:java",
       "//chrome/browser/browser_controls/android:java",
       "//chrome/browser/commerce/android:java",
       "//chrome/browser/commerce/subscriptions/android:subscriptions_java",
@@ -1524,6 +1528,7 @@
       "//chrome/browser/android/crypto:java",
       "//chrome/browser/android/customtabs/branding:java",
       "//chrome/browser/android/httpclient:javatests",
+      "//chrome/browser/android/intents:java",
       "//chrome/browser/android/lifecycle:java",
       "//chrome/browser/android/metrics:java",
       "//chrome/browser/android/metrics:ukm_java_test_support",
@@ -2724,6 +2729,7 @@
       "//build/config/android/test/resource_overlay:unit_device_javatests",
       "//chrome/android/features/keyboard_accessory:unit_device_javatests",
       "//chrome/android/features/tab_ui:unit_device_javatests",
+      "//chrome/browser/android/intents:unit_device_javatests",
       "//chrome/browser/back_press/android:unit_device_javatests",
       "//chrome/browser/content_creation/notes/internal/android:unit_device_javatests",
       "//chrome/browser/download/internal/android:unit_device_javatests",
@@ -3371,7 +3377,7 @@
     "java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsDelegate.java",
     "java/src/org/chromium/chrome/browser/autofill/settings/SettingsLauncherHelper.java",
     "java/src/org/chromium/chrome/browser/autofill/settings/VirtualCardEnrollmentFields.java",
-    "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVCNEnrollBottomSheetBridge.java",
+    "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridge.java",
     "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java",
     "java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTask.java",
     "java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskScheduler.java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index 30587f58..8e37222 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -479,6 +479,7 @@
   "java/res/layout/autofill_server_data_label.xml",
   "java/res/layout/autofill_server_data_text_label.xml",
   "java/res/layout/autofill_update_address_profile_prompt.xml",
+  "java/res/layout/autofill_vcn_enroll_bottom_sheet_content.xml",
   "java/res/layout/bookmark_add_new_folder_input_layout.xml",
   "java/res/layout/bookmark_edit.xml",
   "java/res/layout/bookmark_folder_picker.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 65c2a16..bbd4140 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -145,7 +145,12 @@
   "java/src/org/chromium/chrome/browser/autofill/settings/CreditCardNumberFormattingTextWatcher.java",
   "java/src/org/chromium/chrome/browser/autofill/settings/SettingsLauncherHelper.java",
   "java/src/org/chromium/chrome/browser/autofill/settings/VirtualCardEnrollmentFields.java",
-  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVCNEnrollBottomSheetBridge.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridge.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinator.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediator.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetProperties.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetView.java",
+  "java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinder.java",
   "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java",
   "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java",
   "java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTask.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 89d99c5f..22aff18 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -40,6 +40,9 @@
   "junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java",
   "junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialogTest.java",
   "junit/src/org/chromium/chrome/browser/autofill/settings/SettingsLauncherHelperTest.java",
+  "junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridgeTest.java",
+  "junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinatorTest.java",
+  "junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediatorTest.java",
   "junit/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskSchedulerTest.java",
   "junit/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskTest.java",
   "junit/src/org/chromium/chrome/browser/background_sync/BackgroundSyncGooglePlayServicesCheckerTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index d203836..da55888 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -74,6 +74,7 @@
   "javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragmentTest.java",
   "javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java",
   "javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillTestRule.java",
+  "javatests/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinderTest.java",
   "javatests/src/org/chromium/chrome/browser/automotive/backbuttontoolbar/BackButtonToolbarTest.java",
   "javatests/src/org/chromium/chrome/browser/background_sync/BackgroundSyncTest.java",
   "javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java",
diff --git a/chrome/android/java/res/layout/autofill_vcn_enroll_bottom_sheet_content.xml b/chrome/android/java/res/layout/autofill_vcn_enroll_bottom_sheet_content.xml
new file mode 100644
index 0000000..998aeb7
--- /dev/null
+++ b/chrome/android/java/res/layout/autofill_vcn_enroll_bottom_sheet_content.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:orientation="vertical">
+
+    <!-- Drag handlebar -->
+    <org.chromium.ui.widget.ChromeImageView
+        android:importantForAccessibility="no"
+        android:layout_gravity="center_horizontal"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:src="@drawable/drag_handlebar" />
+
+    <ScrollView
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent">
+
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="vertical">
+
+            <!-- "Make it more secure with a virtual card next time?" dialog title -->
+            <androidx.appcompat.widget.DialogTitle
+                android:id="@+id/dialog_title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="center"
+                android:textAppearance="@style/TextAppearance.Headline.Primary" />
+
+            <!-- "Yes" button -->
+            <org.chromium.ui.widget.ButtonCompat
+                android:id="@+id/accept_button"
+                android:descendantFocusability="blocksDescendants"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:ellipsize="end"
+                android:singleLine="true"
+                style="@style/FilledButton.Flat" />
+
+            <!-- "Skip" button -->
+            <org.chromium.ui.widget.ButtonCompat
+                android:id="@+id/cancel_button"
+                android:descendantFocusability="blocksDescendants"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:ellipsize="end"
+                android:singleLine="true"
+                style="@style/TextButton" />
+        </LinearLayout>
+    </ScrollView>
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 9ffc889..ee4c3c028 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -16,7 +16,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.PowerManager;
-import android.os.SystemClock;
 import android.provider.Browser;
 import android.provider.MediaStore;
 import android.provider.Settings;
@@ -191,11 +190,6 @@
             "org.chromium.chrome.browser.open_regular_overview_mode";
 
     /**
-     * Key to associate a timestamp with an intent.
-     */
-    private static final String EXTRA_TIMESTAMP_MS = "org.chromium.chrome.browser.timestamp";
-
-    /**
      * For multi-window, passes the id of the window. On Android S, this is synonymous with
      * the id of 'activity instance' among multiple instances that can be chosen on instance
      * switcher UI, ranging from 0 ~ max_instances - 1. -1 for an invalid id.
@@ -915,33 +909,6 @@
     }
 
     /**
-     * Adds a timestamp to an intent, as returned by {@link SystemClock#elapsedRealtime()}.
-     *
-     * To track page load time, this needs to be called as close as possible to
-     * the entry point (in {@link Activity#onCreate()} for instance).
-     */
-    public static void addTimestampToIntent(Intent intent) {
-        addTimestampToIntent(intent, SystemClock.elapsedRealtime());
-    }
-
-    /**
-     * Adds provided timestamp to an intent.
-     *
-     * To track page load time, the value passed in should be as close as possible to
-     * the entry point (in {@link Activity#onCreate()} for instance).
-     */
-    public static void addTimestampToIntent(Intent intent, long timeStamp) {
-        intent.putExtra(EXTRA_TIMESTAMP_MS, timeStamp);
-    }
-
-    /**
-     * @return the timestamp associated with an intent, or -1.
-     */
-    public static long getTimestampFromIntent(Intent intent) {
-        return intent.getLongExtra(EXTRA_TIMESTAMP_MS, -1);
-    }
-
-    /**
      * Returns true if the app should ignore a given intent.
      *
      * @param intent Intent to check.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index 0fa028c6..52d7183 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.chrome.browser.notifications.NotificationPlatformBridge;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
@@ -123,8 +124,8 @@
 
         // Needs to be called as early as possible, to accurately capture the
         // time at which the intent was received.
-        if (mIntent != null && IntentHandler.getTimestampFromIntent(mIntent) == -1) {
-            IntentHandler.addTimestampToIntent(mIntent);
+        if (mIntent != null && BrowserIntentUtils.getStartupRealtimeMillis(mIntent) == -1) {
+            BrowserIntentUtils.addStartupTimestampsToIntent(mIntent);
         }
 
         recordIntentMetrics();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 07541d1c..70351c8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -120,6 +120,7 @@
 import org.chromium.chrome.browser.history.HistoryManagerUtils;
 import org.chromium.chrome.browser.init.AsyncInitializationActivity;
 import org.chromium.chrome.browser.init.ProcessInitializationHandler;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
 import org.chromium.chrome.browser.keyboard_accessory.ManualFillingComponent;
 import org.chromium.chrome.browser.keyboard_accessory.ManualFillingComponentFactory;
 import org.chromium.chrome.browser.keyboard_accessory.ManualFillingComponentSupplier;
@@ -1321,7 +1322,7 @@
                 onDeferredStartupForMultiWindowMode();
             }
 
-            long intentTimestamp = IntentHandler.getTimestampFromIntent(getIntent());
+            long intentTimestamp = BrowserIntentUtils.getStartupRealtimeMillis(getIntent());
             if (intentTimestamp != -1) {
                 recordIntentToCreationTime(getOnCreateTimestampMs() - intentTimestamp);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridge.java
index 690f4a1..075cab85 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridge.java
@@ -4,29 +4,33 @@
 
 package org.chromium.chrome.browser.autofill;
 
-import android.content.Context;
-import android.view.View;
+import android.net.Uri;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.browser.customtabs.CustomTabsIntent;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.components.autofill.payments.AutofillSaveCardUiInfo;
-import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
+import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.ui.base.WindowAndroid;
 
+import java.util.function.Consumer;
+
 /**
  * Bridge class providing an entry point for autofill client to trigger the save card bottom sheet.
  */
 @JNINamespace("autofill")
-public class AutofillSaveCardBottomSheetBridge {
+public class AutofillSaveCardBottomSheetBridge
+        extends EmptyBottomSheetObserver implements AutofillSaveCardBottomSheetContent.Delegate {
     private long mNativeAutofillSaveCardBottomSheetBridge;
     private WindowAndroid mWindow;
     private BottomSheetController mBottomSheetController;
+    private AutofillSaveCardBottomSheetContent mBottomSheetContent;
 
     @CalledByNative
     @VisibleForTesting
@@ -35,6 +39,7 @@
         mNativeAutofillSaveCardBottomSheetBridge = nativeAutofillSaveCardBottomSheetBridge;
         mWindow = window;
         mBottomSheetController = BottomSheetControllerProvider.from(window);
+        mBottomSheetController.addObserver(this);
     }
 
     /**
@@ -43,71 +48,87 @@
      * The bottom sheet may not be shown in some cases.
      * {@see BottomSheetController#requestShowContent}
      *
-     * @return True if shown.
+     * @param uiInfo An object providing text and images to the bottom sheet
+     * view.
      */
     @CalledByNative
-    public boolean requestShowContent(AutofillSaveCardUiInfo uiInfo) {
-        return mBottomSheetController.requestShowContent(
-                new BottomSheetContentImpl(mWindow.getApplicationContext()), /* animate= */ true);
+    public void requestShowContent(AutofillSaveCardUiInfo uiInfo) {
+        if (mNativeAutofillSaveCardBottomSheetBridge != 0) {
+            mBottomSheetContent = new AutofillSaveCardBottomSheetContent(
+                    mWindow.getContext().get(), /*delegate=*/this);
+            mBottomSheetContent.setUiInfo(uiInfo);
+            if (mBottomSheetController.requestShowContent(mBottomSheetContent, /*animate=*/true)) {
+                AutofillSaveCardBottomSheetBridgeJni.get().onUiShown(
+                        mNativeAutofillSaveCardBottomSheetBridge);
+            } else {
+                mBottomSheetContent = null;
+            }
+        }
     }
 
-    // TODO(crbug.com/1454271): Implement save card bottom sheet.
+    // AutofillSaveCardBottomSheetContent.Delegate implementation follows:
+    @Override
+    public void didClickLegalMessageUrl(String url) {
+        new CustomTabsIntent.Builder().setShowTitle(true).build().launchUrl(
+                mBottomSheetContent.getContentView().getContext(), Uri.parse(url));
+    }
+
+    @Override
+    public void onSheetClosed(@StateChangeReason int reason) {
+        switch (reason) {
+            case StateChangeReason.BACK_PRESS: // Intentionally fall through.
+            case StateChangeReason.SWIPE: // Intentionally fall through.
+            case StateChangeReason.TAP_SCRIM:
+                callBridgeAndReset(
+                        (nativePointer)
+                                -> AutofillSaveCardBottomSheetBridgeJni.get().onUiCanceled(
+                                        nativePointer));
+                break;
+            case StateChangeReason.INTERACTION_COMPLETE:
+                // Expecting didClickConfirm() and didClickCancel() call the delegate in this case.
+                break;
+            default:
+                callBridgeAndReset(
+                        (nativePointer)
+                                -> AutofillSaveCardBottomSheetBridgeJni.get().onUiIgnored(
+                                        nativePointer));
+                break;
+        }
+    }
+
+    @Override
+    public void didClickConfirm() {
+        mBottomSheetController.hideContent(
+                mBottomSheetContent, /*animate=*/true, StateChangeReason.INTERACTION_COMPLETE);
+        callBridgeAndReset(
+                (nativePointer)
+                        -> AutofillSaveCardBottomSheetBridgeJni.get().onUiAccepted(nativePointer));
+    }
+
+    @Override
+    public void didClickCancel() {
+        mBottomSheetController.hideContent(
+                mBottomSheetContent, /*animate=*/true, StateChangeReason.INTERACTION_COMPLETE);
+        callBridgeAndReset(
+                (nativePointer)
+                        -> AutofillSaveCardBottomSheetBridgeJni.get().onUiCanceled(nativePointer));
+    }
+
+    private void callBridgeAndReset(Consumer<Long> nativeMethod) {
+        if (mBottomSheetContent != null && mNativeAutofillSaveCardBottomSheetBridge != 0) {
+            nativeMethod.accept(mNativeAutofillSaveCardBottomSheetBridge);
+        }
+        mBottomSheetContent = null;
+    }
+
+    @CalledByNative
     @VisibleForTesting
-    static final class BottomSheetContentImpl implements BottomSheetContent {
-        private View mView;
-
-        private BottomSheetContentImpl(Context context) {
-            mView = new View(context);
-        }
-
-        @Override
-        public View getContentView() {
-            return mView;
-        }
-
-        @Nullable
-        @Override
-        public View getToolbarView() {
-            return null;
-        }
-
-        @Override
-        public int getVerticalScrollOffset() {
-            return 0;
-        }
-
-        @Override
-        public void destroy() {}
-
-        @Override
-        public int getPriority() {
-            return ContentPriority.HIGH;
-        }
-
-        @Override
-        public boolean swipeToDismissEnabled() {
-            return false;
-        }
-
-        @Override
-        public int getSheetContentDescriptionStringId() {
-            return android.R.string.ok;
-        }
-
-        @Override
-        public int getSheetHalfHeightAccessibilityStringId() {
-            return android.R.string.ok;
-        }
-
-        @Override
-        public int getSheetFullHeightAccessibilityStringId() {
-            return android.R.string.ok;
-        }
-
-        @Override
-        public int getSheetClosedAccessibilityStringId() {
-            return android.R.string.ok;
-        }
+    /*package*/ void destroy() {
+        mBottomSheetController.removeObserver(this);
+        callBridgeAndReset(
+                (nativePointer)
+                        -> AutofillSaveCardBottomSheetBridgeJni.get().onUiIgnored(nativePointer));
+        mNativeAutofillSaveCardBottomSheetBridge = 0;
     }
 
     @NativeMethods
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVCNEnrollBottomSheetBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVCNEnrollBottomSheetBridge.java
deleted file mode 100644
index 53e3dc8..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVCNEnrollBottomSheetBridge.java
+++ /dev/null
@@ -1,22 +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.
-
-package org.chromium.chrome.browser.autofill.vcn;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.content_public.browser.WebContents;
-
-/** Bridge for the virtual card enrollment bottom sheet. */
-@JNINamespace("autofill")
-/*package*/ class AutofillVCNEnrollBottomSheetBridge {
-    @CalledByNative
-    private AutofillVCNEnrollBottomSheetBridge() {}
-
-    @CalledByNative
-    private boolean requestShowContent(
-            long nativeAutofillVCNEnrollBottomSheetBridge, WebContents webContents) {
-        return false;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridge.java
new file mode 100644
index 0000000..c123369
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridge.java
@@ -0,0 +1,84 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.base.WindowAndroid;
+
+/** Bridge for the virtual card enrollment bottom sheet. */
+@JNINamespace("autofill")
+/*package*/ class AutofillVcnEnrollBottomSheetBridge {
+    private long mNativeAutofillVcnEnrollBottomSheetBridge;
+    private AutofillVcnEnrollBottomSheetCoordinator mCoordinator;
+
+    @CalledByNative
+    @VisibleForTesting
+    /*package*/ AutofillVcnEnrollBottomSheetBridge() {}
+
+    @CalledByNative
+    @VisibleForTesting
+    /*package*/ boolean requestShowContent(long nativeAutofillVcnEnrollBottomSheetBridge,
+            WebContents webContents, String messageText, String acceptButtonLabel,
+            String cancelButtonLabel) {
+        if (webContents == null || webContents.isDestroyed()) return false;
+
+        WindowAndroid window = webContents.getTopLevelNativeWindow();
+        if (window == null) return false;
+
+        if (mNativeAutofillVcnEnrollBottomSheetBridge != 0) return false;
+        mNativeAutofillVcnEnrollBottomSheetBridge = nativeAutofillVcnEnrollBottomSheetBridge;
+
+        mCoordinator = new AutofillVcnEnrollBottomSheetCoordinator(window.getContext().get(),
+                messageText, acceptButtonLabel, cancelButtonLabel, this::onAccept, this::onCancel,
+                this::onDismiss);
+
+        return mCoordinator.requestShowContent(window);
+    }
+
+    @VisibleForTesting
+    /*package*/ void onAccept() {
+        if (mNativeAutofillVcnEnrollBottomSheetBridge == 0) return;
+        AutofillVcnEnrollBottomSheetBridgeJni.get().onAccept(
+                mNativeAutofillVcnEnrollBottomSheetBridge);
+        mNativeAutofillVcnEnrollBottomSheetBridge = 0;
+    }
+
+    @VisibleForTesting
+    /*package*/ void onCancel() {
+        if (mNativeAutofillVcnEnrollBottomSheetBridge == 0) return;
+        AutofillVcnEnrollBottomSheetBridgeJni.get().onCancel(
+                mNativeAutofillVcnEnrollBottomSheetBridge);
+        mNativeAutofillVcnEnrollBottomSheetBridge = 0;
+    }
+
+    @VisibleForTesting
+    /*package*/ void onDismiss() {
+        if (mNativeAutofillVcnEnrollBottomSheetBridge == 0) return;
+        AutofillVcnEnrollBottomSheetBridgeJni.get().onDismiss(
+                mNativeAutofillVcnEnrollBottomSheetBridge);
+        mNativeAutofillVcnEnrollBottomSheetBridge = 0;
+    }
+
+    @CalledByNative
+    @VisibleForTesting
+    /*package*/ void hide() {
+        mNativeAutofillVcnEnrollBottomSheetBridge = 0;
+        if (mCoordinator == null) return;
+        mCoordinator.hide();
+        mCoordinator = null;
+    }
+
+    @NativeMethods
+    interface Natives {
+        void onAccept(long nativeAutofillVCNEnrollBottomSheetBridge);
+        void onCancel(long nativeAutofillVCNEnrollBottomSheetBridge);
+        void onDismiss(long nativeAutofillVCNEnrollBottomSheetBridge);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinator.java
new file mode 100644
index 0000000..3036e28
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinator.java
@@ -0,0 +1,65 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import android.content.Context;
+
+import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+
+/** Coordinator controller for the virtual card enrollment bottom sheet. */
+/*package*/ class AutofillVcnEnrollBottomSheetCoordinator {
+    private final AutofillVcnEnrollBottomSheetMediator mMediator;
+
+    /**
+     * Constructs a coordinator controller for the virtual card enrollment bottom sheet.
+     *
+     * @param context The activity context.
+     * @param messageText The prompt message for the bottom sheet, e.g., "Make it more secure with a
+     *                    virtual card next time?"
+     * @param acceptButtonLabel The label for the button that enrolls a virtual card.
+     * @param cancelButtonLabel The label for the button that cancels enrollment.
+     * @param onAccept The callback to invoke when the user accepts the enrollment prompt.
+     * @param onCancel The callback to invoke when the user cancels the enrollment prompt.
+     * @param onDismiss The callback to invoke when the user dismisses the bottom sheet.
+     */
+    /*package*/ AutofillVcnEnrollBottomSheetCoordinator(Context context, String messageText,
+            String acceptButtonLabel, String cancelButtonLabel, Runnable onAccept,
+            Runnable onCancel, Runnable onDismiss) {
+        PropertyModel model =
+                new PropertyModel.Builder(AutofillVcnEnrollBottomSheetProperties.ALL_KEYS)
+                        .with(AutofillVcnEnrollBottomSheetProperties.MESSAGE_TEXT, messageText)
+                        .with(AutofillVcnEnrollBottomSheetProperties.ACCEPT_BUTTON_LABEL,
+                                acceptButtonLabel)
+                        .with(AutofillVcnEnrollBottomSheetProperties.CANCEL_BUTTON_LABEL,
+                                cancelButtonLabel)
+                        .build();
+
+        AutofillVcnEnrollBottomSheetView view = new AutofillVcnEnrollBottomSheetView(context);
+
+        PropertyModelChangeProcessor.create(
+                model, view, AutofillVcnEnrollBottomSheetViewBinder::bind);
+
+        mMediator = new AutofillVcnEnrollBottomSheetMediator(view.mContentView, view.mAcceptButton,
+                view.mCancelButton, onAccept, onCancel, onDismiss);
+    }
+
+    /**
+     * Requests to show the bottom sheet.
+     *
+     * @param window The window where the bottom sheet should be shown.
+     *
+     * @return True if shown.
+     */
+    /*package*/ boolean requestShowContent(WindowAndroid window) {
+        return mMediator.requestShowContent(window);
+    }
+
+    /** Hides the virtual card enrollment bottom sheet, if present. */
+    /*package*/ void hide() {
+        mMediator.hide();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediator.java
new file mode 100644
index 0000000..2b78345
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediator.java
@@ -0,0 +1,148 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.chrome.R;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
+import org.chromium.ui.base.WindowAndroid;
+
+/** The mediator controller for the virtual card enrollment bottom sheet. */
+/*package*/ class AutofillVcnEnrollBottomSheetMediator
+        implements BottomSheetContent, View.OnClickListener {
+    private final View mContentView;
+    private final View mAcceptButton;
+    private final View mCancelButton;
+    private final Runnable mOnAccept;
+    private final Runnable mOnCancel;
+    private final Runnable mOnDismiss;
+    private BottomSheetController mBottomSheetController;
+
+    /**
+     * Constructs the mediator controller for the virtual card enrollment bottom sheet.
+     *
+     * @param contentView The bottom sheet content.
+     * @param acceptButton The button that the user taps when they accept the enrollment prompt.
+     * @param cancelButton The button that the user taps when they cancel the enrollment prompt.
+     * @param onAccept The callback to invoke when the user accepts the enrollment prompt.
+     * @param onCancel The callback to invoke when the user cancels the enrollment prompt.
+     * @param onDismiss The callback to invoke when the user dismisses the bottom sheet.
+     */
+    /*package*/ AutofillVcnEnrollBottomSheetMediator(View contentView, View acceptButton,
+            View cancelButton, Runnable onAccept, Runnable onCancel, Runnable onDismiss) {
+        mContentView = contentView;
+
+        mAcceptButton = acceptButton;
+        mAcceptButton.setOnClickListener(this);
+
+        mCancelButton = cancelButton;
+        mCancelButton.setOnClickListener(this);
+
+        mOnAccept = onAccept;
+        mOnCancel = onCancel;
+        mOnDismiss = onDismiss;
+    }
+
+    /**
+     * Requests to show the bottom sheet.
+     *
+     * @param window The window where the bottom sheet should be shown.
+     *
+     * @return True if shown.
+     */
+    /*package*/ boolean requestShowContent(WindowAndroid window) {
+        mBottomSheetController = BottomSheetControllerProvider.from(window);
+        if (mBottomSheetController == null) return false;
+
+        return mBottomSheetController.requestShowContent(this, /*animate=*/true);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mAcceptButton) {
+            mOnAccept.run();
+            hide();
+        } else if (v == mCancelButton) {
+            mOnCancel.run();
+            hide();
+        } else {
+            assert false : "Unknown view clicked";
+        }
+    }
+
+    /** Hides the bottom sheet, if present. */
+    /*package*/ void hide() {
+        if (mBottomSheetController == null) return;
+        mBottomSheetController.hideContent(this, /*animate=*/true,
+                BottomSheetController.StateChangeReason.INTERACTION_COMPLETE);
+    }
+
+    @Override
+    public View getContentView() {
+        return mContentView;
+    }
+
+    @Nullable
+    @Override
+    public View getToolbarView() {
+        return null;
+    }
+
+    @Override
+    public int getVerticalScrollOffset() {
+        return 0;
+    }
+
+    @Override
+    public void destroy() {
+        mOnDismiss.run();
+    }
+
+    @Override
+    public int getPriority() {
+        return ContentPriority.HIGH;
+    }
+
+    @Override
+    public boolean swipeToDismissEnabled() {
+        return false;
+    }
+
+    @Override
+    public int getSheetContentDescriptionStringId() {
+        return R.string.autofill_virtual_card_enroll_content_description;
+    }
+
+    @Override
+    public int getSheetHalfHeightAccessibilityStringId() {
+        assert false : "Half height is disabled for virtual card enrollment bottom sheet";
+        return R.string.autofill_virtual_card_enroll_content_description;
+    }
+
+    @Override
+    public int getSheetFullHeightAccessibilityStringId() {
+        return R.string.autofill_virtual_card_enroll_full_height_content_description;
+    }
+
+    @Override
+    public int getSheetClosedAccessibilityStringId() {
+        return R.string.autofill_virtual_card_enroll_closed_description;
+    }
+
+    @Override
+    public int getPeekHeight() {
+        return BottomSheetContent.HeightMode.DISABLED;
+    }
+
+    @Override
+    public float getFullHeightRatio() {
+        return BottomSheetContent.HeightMode.WRAP_CONTENT;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetProperties.java
new file mode 100644
index 0000000..65dc245
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetProperties.java
@@ -0,0 +1,26 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
+
+/** The model of the autofill virtual card enrollment bottom sheet UI. */
+/*package*/ abstract class AutofillVcnEnrollBottomSheetProperties {
+    /** The prompt message for the bottom sheet. */
+    /*package*/ static final ReadableObjectPropertyKey<String> MESSAGE_TEXT =
+            new ReadableObjectPropertyKey<>();
+
+    /** The label for the button that enrolls a virtual card. */
+    /*package*/ static final ReadableObjectPropertyKey<String> ACCEPT_BUTTON_LABEL =
+            new ReadableObjectPropertyKey<>();
+
+    /** The label for the button that cancels enrollment. */
+    /*package*/ static final ReadableObjectPropertyKey<String> CANCEL_BUTTON_LABEL =
+            new ReadableObjectPropertyKey<>();
+
+    /*package*/ static final PropertyKey[] ALL_KEYS = {
+            MESSAGE_TEXT, ACCEPT_BUTTON_LABEL, CANCEL_BUTTON_LABEL};
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetView.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetView.java
new file mode 100644
index 0000000..1bff8e7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetView.java
@@ -0,0 +1,41 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+
+/** The view of the autofill virtual card enrollment bottom sheet UI. */
+/*package*/ class AutofillVcnEnrollBottomSheetView {
+    /** The view that contains all other views. */
+    /*package*/ final ViewGroup mContentView;
+
+    /** The title of the bottom sheet UI. */
+    /*package*/ final TextView mDialogTitle;
+
+    /** The button that accepts the enrollment prompt. */
+    /*package*/ final Button mAcceptButton;
+
+    /** The button that cancels the enrollment. */
+    /*package*/ final Button mCancelButton;
+
+    /**
+     * Creates the view of the autofill virtual card enrollment bottom sheet UI.
+     *
+     * @param context The context for inflating the UI layout XML file.
+     */
+    /*package*/ AutofillVcnEnrollBottomSheetView(Context context) {
+        mContentView = (ViewGroup) LayoutInflater.from(context).inflate(
+                R.layout.autofill_vcn_enroll_bottom_sheet_content, null);
+        mDialogTitle = mContentView.findViewById(R.id.dialog_title);
+        mAcceptButton = mContentView.findViewById(R.id.accept_button);
+        mCancelButton = mContentView.findViewById(R.id.cancel_button);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinder.java
new file mode 100644
index 0000000..7be481f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinder.java
@@ -0,0 +1,34 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/** The view-binder of the autofill virtual card enrollment bottom sheet UI. */
+/*package*/ abstract class AutofillVcnEnrollBottomSheetViewBinder {
+    /**
+     * Updates the view based on changes in the model.
+     *
+     * @param model The updated model to read.
+     * @param view The view to update.
+     * @param propertyKey The property of the model that has changed.
+     */
+    /*package*/ static void bind(
+            PropertyModel model, AutofillVcnEnrollBottomSheetView view, PropertyKey propertyKey) {
+        if (AutofillVcnEnrollBottomSheetProperties.MESSAGE_TEXT == propertyKey) {
+            view.mDialogTitle.setText(
+                    model.get(AutofillVcnEnrollBottomSheetProperties.MESSAGE_TEXT));
+
+        } else if (AutofillVcnEnrollBottomSheetProperties.ACCEPT_BUTTON_LABEL == propertyKey) {
+            view.mAcceptButton.setText(
+                    model.get(AutofillVcnEnrollBottomSheetProperties.ACCEPT_BUTTON_LABEL));
+
+        } else if (AutofillVcnEnrollBottomSheetProperties.CANCEL_BUTTON_LABEL == propertyKey) {
+            view.mCancelButton.setText(
+                    model.get(AutofillVcnEnrollBottomSheetProperties.CANCEL_BUTTON_LABEL));
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
index 49eeca8..bc84c57e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/sharing/TwaSharingController.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.browserservices.trustedwebactivityui.sharing;
 
+import android.content.Intent;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Pair;
@@ -24,6 +25,7 @@
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.webapps.WebApkPostShareTargetNavigator;
+import org.chromium.content_public.browser.LoadUrlParams;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -71,6 +73,7 @@
         if (shareTarget == null || shareData == null) {
             return Promise.fulfilled(false);
         }
+        Intent intent = intentDataProvider.getIntent();
 
         return mVerifierDelegate.verify(shareTarget.getAction())
                 .then((Function<Boolean, Boolean>) (verified) -> {
@@ -86,7 +89,9 @@
                     }
 
                     mNavigationController.navigate(
-                            computeStartUrlForGETShareTarget(shareData, shareTarget));
+                            new LoadUrlParams(
+                                    computeStartUrlForGETShareTarget(shareData, shareTarget)),
+                            intent);
                     mUmaRecorder.recordShareTargetRequest(ShareRequestMethod.GET);
                     return true;
                 });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
index 969cddd..974b0e33 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -7,20 +7,26 @@
 import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.APP_CONTEXT;
 
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Rect;
 import android.net.Uri;
+import android.os.Process;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
 import androidx.browser.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
+import org.chromium.chrome.browser.customtabs.ClientManager.CalledWarmup;
 import org.chromium.chrome.browser.customtabs.features.TabInteractionRecorder;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
+import org.chromium.chrome.browser.metrics.SimpleStartupForegroundSessionDetector;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabHidingType;
@@ -50,9 +56,12 @@
     private int mContentBitmapWidth;
     private int mContentBitmapHeight;
 
-    private long mIntentReceivedTimestamp;
-    private long mPageLoadStartedTimestamp;
-    private long mFirstCommitTimestamp;
+    private long mIntentReceivedRealtimeMillis;
+    private long mLaunchedForSpeculationRealtimeMillis;
+    @Nullable
+    private Boolean mUsedHiddenTabSpeculation;
+    private long mPageLoadStartedRealtimeMillis;
+    private long mFirstCommitRealtimeMillis;
 
     @IntDef({State.RESET, State.WAITING_LOAD_START, State.WAITING_LOAD_FINISH})
     @Retention(RetentionPolicy.SOURCE)
@@ -97,16 +106,22 @@
      * If a load is already happening, we track its PLT.
      * If not, we track NavigationCommit timing + PLT for the next load.
      */
-    public void trackNextPageLoadFromTimestamp(Tab tab, long timestamp) {
-        mIntentReceivedTimestamp = timestamp;
+    public void trackNextPageLoadForLaunch(Tab tab, Intent sourceIntent) {
+        mIntentReceivedRealtimeMillis = BrowserIntentUtils.getStartupRealtimeMillis(sourceIntent);
         if (tab.isLoading()) {
-            mPageLoadStartedTimestamp = -1;
+            mPageLoadStartedRealtimeMillis = -1;
             mCurrentState = State.WAITING_LOAD_FINISH;
         } else {
             mCurrentState = State.WAITING_LOAD_START;
         }
     }
 
+    public void trackNextPageLoadForHiddenTab(boolean usedSpeculation, Intent sourceIntent) {
+        mUsedHiddenTabSpeculation = usedSpeculation;
+        mLaunchedForSpeculationRealtimeMillis =
+                BrowserIntentUtils.getStartupRealtimeMillis(sourceIntent);
+    }
+
     @Override
     public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
         if (mCustomTabsConnection != null) {
@@ -117,14 +132,14 @@
     @Override
     public void onPageLoadStarted(Tab tab, GURL url) {
         if (mCurrentState == State.WAITING_LOAD_START) {
-            mPageLoadStartedTimestamp = SystemClock.elapsedRealtime();
+            mPageLoadStartedRealtimeMillis = SystemClock.elapsedRealtime();
             mCurrentState = State.WAITING_LOAD_FINISH;
         } else if (mCurrentState == State.WAITING_LOAD_FINISH) {
             if (mCustomTabsConnection != null) {
                 mCustomTabsConnection.sendNavigationInfo(
                         mSession, tab.getUrl().getSpec(), tab.getTitle(), (Uri) null);
             }
-            mPageLoadStartedTimestamp = SystemClock.elapsedRealtime();
+            mPageLoadStartedRealtimeMillis = SystemClock.elapsedRealtime();
         }
         if (mCustomTabsConnection != null) {
             mCustomTabsConnection.setSendNavigationInfoForSession(mSession, false);
@@ -141,11 +156,13 @@
     public void onPageLoadFinished(Tab tab, GURL url) {
         long pageLoadFinishedTimestamp = SystemClock.elapsedRealtime();
 
-        if (mCurrentState == State.WAITING_LOAD_FINISH && mIntentReceivedTimestamp > 0) {
+        if (mCurrentState == State.WAITING_LOAD_FINISH && mIntentReceivedRealtimeMillis > 0) {
             String histogramPrefix = mOpenedByChrome ? "ChromeGeneratedCustomTab" : "CustomTabs";
-            long timeToPageLoadFinishedMs = pageLoadFinishedTimestamp - mIntentReceivedTimestamp;
-            if (mPageLoadStartedTimestamp > 0) {
-                long timeToPageLoadStartedMs = mPageLoadStartedTimestamp - mIntentReceivedTimestamp;
+            long timeToPageLoadFinishedMs =
+                    pageLoadFinishedTimestamp - mIntentReceivedRealtimeMillis;
+            if (mPageLoadStartedRealtimeMillis > 0) {
+                long timeToPageLoadStartedMs =
+                        mPageLoadStartedRealtimeMillis - mIntentReceivedRealtimeMillis;
                 // Intent to Load Start is recorded here to make sure we do not record
                 // failed/aborted page loads.
                 RecordHistogram.recordCustomTimesHistogram(
@@ -160,8 +177,9 @@
                     timeToPageLoadFinishedMs, 10, DateUtils.MINUTE_IN_MILLIS * 10, 100);
 
             // Not all page loads go through a navigation commit (prerender for instance).
-            if (mPageLoadStartedTimestamp != 0) {
-                long timeToFirstCommitMs = mFirstCommitTimestamp - mIntentReceivedTimestamp;
+            if (mPageLoadStartedRealtimeMillis != 0) {
+                long timeToFirstCommitMs =
+                        mFirstCommitRealtimeMillis - mIntentReceivedRealtimeMillis;
                 // Current median is 550ms, and long tail is very long. ZoomedIn gives good view of
                 // the median and ZoomedOut gives a good overview.
                 RecordHistogram.recordCustomTimesHistogram(
@@ -185,10 +203,42 @@
 
     @Override
     public void onDidFinishNavigationInPrimaryMainFrame(Tab tab, NavigationHandle navigation) {
-        boolean firstNavigation = mFirstCommitTimestamp == 0;
+        boolean firstNavigation = mFirstCommitRealtimeMillis == 0;
         boolean isFirstMainFrameCommit = firstNavigation && navigation.hasCommitted()
                 && !navigation.isErrorPage() && !navigation.isSameDocument();
-        if (isFirstMainFrameCommit) mFirstCommitTimestamp = SystemClock.elapsedRealtime();
+        if (!isFirstMainFrameCommit) return;
+
+        mFirstCommitRealtimeMillis = SystemClock.elapsedRealtime();
+
+        if (mCustomTabsConnection == null) return;
+
+        String histogram = null;
+        long duration = 0;
+        @CalledWarmup
+        int warmedState = mCustomTabsConnection.getWarmupState(mSession);
+        boolean warmedUp = warmedState == CalledWarmup.SESSION_NO_WARMUP_ALREADY_CALLED
+                || warmedState == CalledWarmup.SESSION_WARMUP;
+        // Note that this will exclude Webapp launches in all cases due to either
+        // mUsedHiddenTabSpeculation being null, or mIntentReceivedTimestamp being 0.
+        if (mUsedHiddenTabSpeculation != null && mUsedHiddenTabSpeculation) {
+            duration = mFirstCommitRealtimeMillis - mLaunchedForSpeculationRealtimeMillis;
+            histogram = "CustomTabs.Startup.TimeToFirstCommitNavigation.Speculated";
+        } else if (mIntentReceivedRealtimeMillis > 0) {
+            if (warmedUp) {
+                duration = mFirstCommitRealtimeMillis - mIntentReceivedRealtimeMillis;
+                histogram = "CustomTabs.Startup.TimeToFirstCommitNavigation.WarmedUp";
+            } else if (SimpleStartupForegroundSessionDetector.runningCleanForegroundSession()) {
+                duration = mFirstCommitRealtimeMillis - Process.getStartElapsedRealtime();
+                histogram = "CustomTabs.Startup.TimeToFirstCommitNavigation.Cold";
+            } else {
+                duration = mFirstCommitRealtimeMillis - mIntentReceivedRealtimeMillis;
+                histogram = "CustomTabs.Startup.TimeToFirstCommitNavigation.Warm";
+            }
+        }
+        if (histogram != null) {
+            RecordHistogram.recordCustomTimesHistogram(
+                    histogram, duration, 20, DateUtils.SECOND_IN_MILLIS * 20, 50);
+        }
     }
 
     @Override
@@ -208,7 +258,7 @@
 
     private void resetPageLoadTracking() {
         mCurrentState = State.RESET;
-        mIntentReceivedTimestamp = -1;
+        mIntentReceivedRealtimeMillis = -1;
     }
 
     private void captureNavigationInfo(final Tab tab) {
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 996c0ef..0e9df6a 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
@@ -60,6 +60,7 @@
 import org.chromium.chrome.browser.browserservices.SessionHandler;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.ActivityLayoutState;
+import org.chromium.chrome.browser.customtabs.ClientManager.CalledWarmup;
 import org.chromium.chrome.browser.customtabs.content.EngagementSignalsHandler;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -1820,6 +1821,13 @@
         return false;
     }
 
+    /**
+     * @return The CalledWarmup state for the session.
+     */
+    public @CalledWarmup int getWarmupState(CustomTabsSessionToken session) {
+        return mClientManager.getWarmupState(session);
+    }
+
     public static void setInstanceForTesting(CustomTabsConnection connection) {
         var oldValue = sInstance;
         sInstance = connection;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java
index 728bd1f8..2638839 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java
@@ -12,7 +12,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.text.TextUtils;
 
 import androidx.annotation.IntDef;
@@ -185,18 +184,10 @@
     }
 
     /**
-     * Navigates to given url.
-     */
-    public void navigate(String url) {
-        navigate(new LoadUrlParams(url), SystemClock.elapsedRealtime());
-    }
-
-    /**
      * Performs navigation using given {@link LoadUrlParams}.
-     * Uses provided timestamp as the initial time for tracking page loading times
-     * (see {@link CustomTabObserver}).
+     * The source Intent is used for tracking page loading times (see {@link CustomTabObserver}).
      */
-    public void navigate(final LoadUrlParams params, long timeStamp) {
+    public void navigate(final LoadUrlParams params, Intent sourceIntent) {
         Tab tab = mTabProvider.getTab();
         if (tab == null) {
             assert false;
@@ -211,7 +202,7 @@
 
         // TODO(pkotwicz): Figure out whether we want to record these metrics for WebAPKs.
         if (mIntentDataProvider.getWebappExtras() == null) {
-            mCustomTabObserver.get().trackNextPageLoadFromTimestamp(tab, timeStamp);
+            mCustomTabObserver.get().trackNextPageLoadForLaunch(tab, sourceIntent);
         }
 
         IntentHandler.addReferrerAndHeaders(params, mIntentDataProvider.getIntent());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
index 27a1df6..e1a94ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
@@ -9,7 +9,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.IntentUtils;
-import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
 import org.chromium.chrome.browser.customtabs.CustomTabObserver;
@@ -67,7 +66,7 @@
                         getGurlForUrl(params.getUrl()), passwordChangeUsername);
             }
 
-            mNavigationController.navigate(params, getTimestamp(intentDataProvider));
+            mNavigationController.navigate(params, intentDataProvider.getIntent());
         }
     }
 
@@ -99,7 +98,11 @@
 
         // No actual load to do if the hidden tab already has the exact correct url.
         String speculatedUrl = mTabProvider.getSpeculatedUrl();
-        if (TextUtils.equals(speculatedUrl, url)) {
+
+        boolean useSpeculation = TextUtils.equals(speculatedUrl, url);
+        mCustomTabObserver.get().trackNextPageLoadForHiddenTab(
+                useSpeculation, intentDataProvider.getIntent());
+        if (useSpeculation) {
             if (tab.isLoading()) {
                 // CustomTabObserver and CustomTabActivityNavigationObserver are attached
                 // as observers in CustomTabActivityTabController, not when the navigation is
@@ -120,7 +123,7 @@
             params.setShouldReplaceCurrentEntry(true);
         }
 
-        mNavigationController.navigate(params, getTimestamp(intentDataProvider));
+        mNavigationController.navigate(params, intentDataProvider.getIntent());
     }
 
     @Override
@@ -137,10 +140,6 @@
             params.setShouldClearHistoryList(true);
         }
 
-        mNavigationController.navigate(params, getTimestamp(intentDataProvider));
-    }
-
-    private long getTimestamp(BrowserServicesIntentDataProvider intentDataProvider) {
-        return IntentHandler.getTimestampFromIntent(intentDataProvider.getIntent());
+        mNavigationController.navigate(params, intentDataProvider.getIntent());
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
index f123446..8f27631 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
@@ -16,7 +16,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Base64;
 
@@ -37,6 +36,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabLocator;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
 import org.chromium.components.webapk.lib.client.WebApkValidator;
 import org.chromium.components.webapps.ShortcutSource;
 
@@ -139,9 +139,9 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        long createTimestamp = SystemClock.elapsedRealtime();
         // Triggers UnsafeIntentLaunch lint warning. https://crbug.com/1412281
         Intent intent = getIntent();
+        BrowserIntentUtils.addStartupTimestampsToIntent(intent);
 
         if (WebappActionsNotificationManager.handleNotificationAction(intent)) {
             finish();
@@ -174,7 +174,7 @@
         }
 
         if (launchData != null) {
-            launchWebapp(this, intent, launchData, createTimestamp);
+            launchWebapp(this, intent, launchData);
             return;
         }
 
@@ -232,9 +232,9 @@
         return (isValidMacForUrl(launchData.url, webappMac) || wasIntentFromChrome(intent));
     }
 
-    private static void launchWebapp(Activity launchingActivity, Intent intent,
-            @NonNull LaunchData launchData, long createTimestamp) {
-        Intent launchIntent = createIntentToLaunchForWebapp(intent, launchData, createTimestamp);
+    private static void launchWebapp(
+            Activity launchingActivity, Intent intent, @NonNull LaunchData launchData) {
+        Intent launchIntent = createIntentToLaunchForWebapp(intent, launchData);
 
         WarmupManager.getInstance().maybePrefetchDnsForUrlInBackground(
                 launchingActivity, launchData.url);
@@ -319,7 +319,7 @@
     /** Returns intent to launch for the web app. */
     @VisibleForTesting
     public static Intent createIntentToLaunchForWebapp(
-            Intent intent, @NonNull LaunchData launchData, long createTimestamp) {
+            Intent intent, @NonNull LaunchData launchData) {
         String launchActivityClassName = selectWebappActivitySubclass(launchData);
 
         Intent launchIntent = new Intent();
@@ -329,7 +329,6 @@
         // Firing intents with the exact same data should relaunch a particular Activity.
         launchIntent.setData(Uri.parse(WebappActivity.WEBAPP_SCHEME + "://" + launchData.id));
 
-        IntentHandler.addTimestampToIntent(launchIntent, createTimestamp);
         if (launchData.isForWebApk) {
             WebappIntentUtils.copyWebApkLaunchIntentExtras(intent, launchIntent);
         } else {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerUnitTest.java
index b682bd6..5018250 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerUnitTest.java
@@ -17,7 +17,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.provider.Browser;
 
 import androidx.browser.customtabs.CustomTabsService;
@@ -323,7 +322,7 @@
         WebappLauncherActivity.LaunchData launchData = new WebappLauncherActivity.LaunchData("id",
                 GOOGLE_URL, null /* webApkPackageName */, false /* isSplashProvidedByWebApk */);
         mIntent = WebappLauncherActivity.createIntentToLaunchForWebapp(
-                webappLauncherActivityIntent, launchData, 0);
+                webappLauncherActivityIntent, launchData);
         Assert.assertEquals(GOOGLE_URL, IntentHandler.getUrlFromIntent(mIntent));
     }
 
@@ -526,23 +525,6 @@
     @Test
     @SmallTest
     @Feature({"Android-AppBase"})
-    public void testAddTimestampToIntent() {
-        Intent intent = new Intent();
-        Assert.assertEquals(-1, IntentHandler.getTimestampFromIntent(intent));
-        // Check both before and after to make sure that the returned value is
-        // really from {@link SystemClock#elapsedRealtime()}.
-        long before = SystemClock.elapsedRealtime();
-        IntentHandler.addTimestampToIntent(intent);
-        long after = SystemClock.elapsedRealtime();
-        Assert.assertTrue("Time should be increasing",
-                before <= IntentHandler.getTimestampFromIntent(intent));
-        Assert.assertTrue(
-                "Time should be increasing", IntentHandler.getTimestampFromIntent(intent) <= after);
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Android-AppBase"})
     public void testGeneratedReferrer() {
         Context context = ApplicationProvider.getApplicationContext();
         String packageName = context.getPackageName();
@@ -667,7 +649,7 @@
         WebappLauncherActivity.LaunchData launchData = new WebappLauncherActivity.LaunchData("id",
                 GOOGLE_URL, null /* webApkPackageName */, false /* isSplashProvidedByWebApk */);
         Intent intent = WebappLauncherActivity.createIntentToLaunchForWebapp(
-                webappLauncherActivityIntent, launchData, 0);
+                webappLauncherActivityIntent, launchData);
 
         assertFalse(mIntentHandler.shouldIgnoreIntent(intent));
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinderTest.java
new file mode 100644
index 0000000..e919a678
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetViewBinderTest.java
@@ -0,0 +1,82 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isEmptyString;
+
+import android.widget.Button;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.Batch;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
+
+/** Tests for {@link AutofillVcnEnrollBottomSheetViewBinder}. */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@Batch(Batch.PER_CLASS)
+public final class AutofillVcnEnrollBottomSheetViewBinderTest extends BlankUiTestActivityTestCase {
+    private PropertyModel.Builder mModel;
+    private AutofillVcnEnrollBottomSheetView mView;
+
+    @Override
+    public void setUpTest() throws Exception {
+        super.setUpTest();
+
+        mModel = new PropertyModel.Builder(AutofillVcnEnrollBottomSheetProperties.ALL_KEYS);
+        mView = new AutofillVcnEnrollBottomSheetView(getActivity());
+        bind(mModel);
+    }
+
+    // Builds the model from the given builder and binds it to the view.
+    private void bind(PropertyModel.Builder modelBuilder) {
+        PropertyModelChangeProcessor.create(
+                modelBuilder.build(), mView, AutofillVcnEnrollBottomSheetViewBinder::bind);
+    }
+
+    @Test
+    @SmallTest
+    public void testMessageTextInDialogTitle() {
+        assertThat(String.valueOf(mView.mDialogTitle.getText()), isEmptyString());
+
+        bind(mModel.with(AutofillVcnEnrollBottomSheetProperties.MESSAGE_TEXT, null));
+        assertThat(String.valueOf(mView.mDialogTitle.getText()), isEmptyString());
+
+        bind(mModel.with(AutofillVcnEnrollBottomSheetProperties.MESSAGE_TEXT, "Message text"));
+        assertThat(String.valueOf(mView.mDialogTitle.getText()), equalTo("Message text"));
+    }
+
+    @Test
+    @SmallTest
+    public void testAcceptButtonLabel() {
+        runButtonLabelTest(
+                mView.mAcceptButton, AutofillVcnEnrollBottomSheetProperties.ACCEPT_BUTTON_LABEL);
+    }
+
+    @Test
+    @SmallTest
+    public void testCancelButtonLabel() {
+        runButtonLabelTest(
+                mView.mCancelButton, AutofillVcnEnrollBottomSheetProperties.CANCEL_BUTTON_LABEL);
+    }
+
+    private void runButtonLabelTest(Button button, ReadableObjectPropertyKey<String> property) {
+        assertThat(String.valueOf(button.getText()), isEmptyString());
+
+        bind(mModel.with(property, null));
+        assertThat(String.valueOf(button.getText()), isEmptyString());
+
+        bind(mModel.with(property, "Button Action Text"));
+        assertThat(String.valueOf(button.getText()), equalTo("Button Action Text"));
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 45f5b3c..232c30c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -2265,7 +2265,8 @@
         // lifetime.
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             final CustomTabActivity activity = mCustomTabActivityTestRule.getActivity();
-            activity.getComponent().resolveNavigationController().navigate("about:blank");
+            activity.getComponent().resolveNavigationController().navigate(
+                    new LoadUrlParams("about:blank"), intent);
         });
 
         if (allowMetrics) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationTest.java
index 0d5acf8..d3f7a00 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationTest.java
@@ -99,7 +99,7 @@
                 mActivityTestRule.getActivity().getString(R.string.webapp_tap_to_copy_url),
                 notification.extras.getString(Notification.EXTRA_TEXT));
         Assert.assertEquals("Share", notification.actions[0].title);
-        Assert.assertEquals("Open in Chrome", notification.actions[1].title);
+        Assert.assertEquals("Open in Chrome browser", notification.actions[1].title);
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW);
         filter.addDataScheme("http");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridgeTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridgeTest.java
index 7986949..4d14532 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridgeTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillSaveCardBottomSheetBridgeTest.java
@@ -6,16 +6,22 @@
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.notNullValue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Robolectric.buildActivity;
+import static org.robolectric.Shadows.shadowOf;
 
-import android.content.Context;
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
 
-import androidx.test.core.app.ApplicationProvider;
+import androidx.browser.customtabs.CustomTabsIntent;
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
@@ -27,31 +33,54 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
+import org.robolectric.shadows.ShadowActivity;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.components.autofill.payments.AutofillSaveCardUiInfo;
+import org.chromium.components.autofill.payments.CardDetail;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory;
 import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController;
 import org.chromium.ui.base.WindowAndroid;
 
 /** Unit tests for {@link AutofillSaveCardBottomSheetBridge}. */
 @RunWith(BaseRobolectricTestRunner.class)
+@SmallTest
 public final class AutofillSaveCardBottomSheetBridgeTest {
     private static final long MOCK_POINTER = 0xb00fb00f;
 
+    private static final String HTTPS_EXAMPLE_TEST = "https://example.test";
+
     @Rule
     public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
+
     private AutofillSaveCardBottomSheetBridge mAutofillSaveCardBottomSheetBridge;
 
+    @Mock
+    private AutofillSaveCardBottomSheetBridge.Natives mBridgeNatives;
+
+    private ShadowActivity mShadowActivity;
+
     private WindowAndroid mWindow;
 
     @Mock
     private ManagedBottomSheetController mBottomSheetController;
 
+    private AutofillSaveCardUiInfo mUiInfo;
+
     @Before
     public void setUp() {
-        Context mApplicationContext = ApplicationProvider.getApplicationContext();
-        mWindow = new WindowAndroid(mApplicationContext);
+        mJniMocker.mock(AutofillSaveCardBottomSheetBridgeJni.TEST_HOOKS, mBridgeNatives);
+        mUiInfo = new AutofillSaveCardUiInfo.Builder()
+                          .withCardDetail(new CardDetail(/*iconId*/ 0, "label", "subLabel"))
+                          .build();
+        Activity activity = buildActivity(Activity.class).create().get();
+        mShadowActivity = shadowOf(activity);
+        mWindow = new WindowAndroid(activity);
         BottomSheetControllerFactory.attach(mWindow, mBottomSheetController);
         mAutofillSaveCardBottomSheetBridge =
                 new AutofillSaveCardBottomSheetBridge(MOCK_POINTER, mWindow);
@@ -64,31 +93,232 @@
     }
 
     @Test
-    @SmallTest
-    public void requestShowContent_callsControllerRequestShowContent() {
-        mAutofillSaveCardBottomSheetBridge.requestShowContent(/*saveCardDelegate=*/null);
+    public void testRequestShowContent_callsControllerRequestShowContent() {
+        requestShowContent(/*didShow=*/true);
 
         verify(mBottomSheetController)
-                .requestShowContent(
-                        any(AutofillSaveCardBottomSheetBridge.BottomSheetContentImpl.class),
+                .requestShowContent(any(AutofillSaveCardBottomSheetContent.class),
                         /* animate= */ eq(true));
     }
 
     @Test
-    @SmallTest
-    public void requestShowContent_bottomSheetContentImplIsStubbed() {
-        mAutofillSaveCardBottomSheetBridge.requestShowContent(/*saveCardDelegate=*/null);
+    public void testRequestShowContent_callsNativeOnUiShown_whenShown() {
+        requestShowContent(/*didShow=*/true);
 
-        ArgumentCaptor<AutofillSaveCardBottomSheetBridge.BottomSheetContentImpl> contentCaptor =
-                ArgumentCaptor.forClass(
-                        AutofillSaveCardBottomSheetBridge.BottomSheetContentImpl.class);
+        verify(mBridgeNatives).onUiShown(MOCK_POINTER);
+    }
+
+    @Test
+    public void testRequestShowContent_doesNotCallNativeOnUiShown_whenNotShown() {
+        requestShowContent(/*didShow=*/false);
+
+        verify(mBridgeNatives, never()).onUiShown(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDidClickLegalMessageUrl_launchesCustomTabIntent() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+
+        bottomSheetContent.getDelegate().didClickLegalMessageUrl(HTTPS_EXAMPLE_TEST);
+
+        Intent intent = mShadowActivity.getNextStartedActivity();
+        assertThat(intent.getData(), equalTo(Uri.parse(HTTPS_EXAMPLE_TEST)));
+        assertThat(intent.getAction(), equalTo(Intent.ACTION_VIEW));
+        assertThat(intent.getExtras().get(CustomTabsIntent.EXTRA_TITLE_VISIBILITY_STATE),
+                equalTo(CustomTabsIntent.SHOW_PAGE_TITLE));
+    }
+
+    @Test
+    public void testDidClickConfirm_hidesBottomSheetContent() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+
+        bottomSheetContent.getDelegate().didClickConfirm();
+
         verify(mBottomSheetController)
-                .requestShowContent(contentCaptor.capture(), /* animate= */ anyBoolean());
-        AutofillSaveCardBottomSheetBridge.BottomSheetContentImpl content = contentCaptor.getValue();
-        assertThat(content.getContentView(), notNullValue());
-        assertThat(content.getSheetContentDescriptionStringId(), equalTo(android.R.string.ok));
-        assertThat(content.getSheetHalfHeightAccessibilityStringId(), equalTo(android.R.string.ok));
-        assertThat(content.getSheetFullHeightAccessibilityStringId(), equalTo(android.R.string.ok));
-        assertThat(content.getSheetClosedAccessibilityStringId(), equalTo(android.R.string.ok));
+                .hideContent(bottomSheetContent, /*animate=*/true,
+                        StateChangeReason.INTERACTION_COMPLETE);
+    }
+
+    @Test
+    public void testDidClickConfirm_callsNativeOnUiAccepted() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+
+        bottomSheetContent.getDelegate().didClickConfirm();
+
+        verify(mBridgeNatives).onUiAccepted(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDidClickConfirm_doesNotCallBridgeNatives_whenAlreadyClickedConfirm() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+        bottomSheetContent.getDelegate().didClickConfirm();
+        clearInvocations(mBridgeNatives);
+
+        bottomSheetContent.getDelegate().didClickConfirm();
+
+        verify(mBridgeNatives, never()).onUiAccepted(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDidClickConfirm_doesNotCallBridgeNatives_afterDestroy() {
+        requestShowContent(/*didShow=*/true);
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        mAutofillSaveCardBottomSheetBridge.didClickConfirm();
+
+        verify(mBridgeNatives, never())
+                .onUiAccepted(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+    }
+
+    @Test
+    public void testDidClickCancel_hidesBottomSheetContent() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+
+        bottomSheetContent.getDelegate().didClickCancel();
+
+        verify(mBottomSheetController)
+                .hideContent(bottomSheetContent, /*animate=*/true,
+                        StateChangeReason.INTERACTION_COMPLETE);
+    }
+
+    @Test
+    public void testDidClickCancel_callsNativeOnUiCanceled() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+
+        bottomSheetContent.getDelegate().didClickCancel();
+
+        verify(mBridgeNatives).onUiCanceled(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDidClickCancel_doesNotCallBridgeNatives_whenAlreadyClickedCancel() {
+        AutofillSaveCardBottomSheetContent bottomSheetContent =
+                requestShowContent(/*didShow=*/true);
+        bottomSheetContent.getDelegate().didClickCancel();
+        clearInvocations(mBridgeNatives);
+
+        bottomSheetContent.getDelegate().didClickCancel();
+
+        verify(mBridgeNatives, never())
+                .onUiIgnored(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+    }
+
+    @Test
+    public void testDidClickCancel_doesNotCallBridgeNatives_afterDestroy() {
+        requestShowContent(/*didShow=*/true);
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        mAutofillSaveCardBottomSheetBridge.didClickCancel();
+
+        verify(mBridgeNatives, never())
+                .onUiCanceled(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+    }
+
+    @Test
+    public void testSheetClosedOnBackPress_callsNativeOnUiCanceled() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.onSheetClosed(StateChangeReason.BACK_PRESS);
+
+        verify(mBridgeNatives).onUiCanceled(MOCK_POINTER);
+    }
+
+    @Test
+    public void testSheetClosedOnSwipe_callsNativeOnUiCanceled() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.onSheetClosed(StateChangeReason.SWIPE);
+
+        verify(mBridgeNatives).onUiCanceled(MOCK_POINTER);
+    }
+
+    @Test
+    public void testSheetClosedOnTapScrim_callsNativeOnUiCanceled() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.onSheetClosed(StateChangeReason.TAP_SCRIM);
+
+        verify(mBridgeNatives).onUiCanceled(MOCK_POINTER);
+    }
+
+    @Test
+    public void testSheetClosedOnInteractionComplete_doesNotCallOnUiCanceledNorOnUiAccepted() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.onSheetClosed(StateChangeReason.INTERACTION_COMPLETE);
+
+        verify(mBridgeNatives, never())
+                .onUiCanceled(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+        verify(mBridgeNatives, never())
+                .onUiAccepted(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+    }
+
+    @Test
+    public void testSheetClosedWithoutUserInteraction_callsNativeOnUiIgnored() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.onSheetClosed(StateChangeReason.PROMOTE_TAB);
+
+        verify(mBridgeNatives).onUiIgnored(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDestroy_stopsObservingTheBottomSheetController() {
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        verify(mBottomSheetController).removeObserver(mAutofillSaveCardBottomSheetBridge);
+    }
+
+    @Test
+    public void testDestroy_callsNativeOnUiIgnored_withoutOtherInteraction() {
+        requestShowContent(/*didShow=*/true);
+
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        verify(mBridgeNatives).onUiIgnored(MOCK_POINTER);
+    }
+
+    @Test
+    public void testDestroy_doesNotCallBridgeNatives_withoutBottomSheetShown() {
+        requestShowContent(/*didShow=*/false);
+
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        verify(mBridgeNatives, never())
+                .onUiIgnored(/*nativeAutofillSaveCardBottomSheetBridge=*/anyLong());
+    }
+
+    @Test
+    public void testRequestShowContent_doesNotCreateABottomSheet_afterDestroy() {
+        mAutofillSaveCardBottomSheetBridge.destroy();
+
+        mAutofillSaveCardBottomSheetBridge.requestShowContent(mUiInfo);
+
+        verify(mBottomSheetController, never()).requestShowContent(any(), anyBoolean());
+    }
+
+    /**
+     * Calls the bridge's requestShowContent while capturing the bottom sheet content.
+     *
+     * The bridge must be initialized; otherwise, we fail to capture the BottomSheet with an
+     * exception from Mockito.
+     *
+     * @param didShow The value returned by the mocked call
+     *                {@link ManagedBottomSheetController#requestShowContent}.
+     * @return The captured value, a AutofillSaveCardBottomSheetContent.
+     */
+    private AutofillSaveCardBottomSheetContent requestShowContent(boolean didShow) {
+        ArgumentCaptor<AutofillSaveCardBottomSheetContent> bottomSheetContent =
+                ArgumentCaptor.forClass(AutofillSaveCardBottomSheetContent.class);
+        when(mBottomSheetController.requestShowContent(bottomSheetContent.capture(), anyBoolean()))
+                .thenReturn(didShow);
+        mAutofillSaveCardBottomSheetBridge.requestShowContent(mUiInfo);
+        return bottomSheetContent.getValue();
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridgeTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridgeTest.java
new file mode 100644
index 0000000..eaec94c
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetBridgeTest.java
@@ -0,0 +1,268 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory;
+import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.base.WindowAndroid;
+
+/** Unit test for {@link AutofillVcnEnrollBottomSheetBridge}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@SmallTest
+public final class AutofillVcnEnrollBottomSheetBridgeTest {
+    private static final long NATIVE_AUTOFILL_VCN_ENROLL_BOTTOM_SHEET_BRIDGE = 0xa1fabe7a;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
+
+    @Mock
+    private AutofillVcnEnrollBottomSheetBridge.Natives mBridgeNatives;
+    @Mock
+    private WebContents mWebContents;
+    @Mock
+    private ManagedBottomSheetController mBottomSheetController;
+
+    private WindowAndroid mWindow;
+    private AutofillVcnEnrollBottomSheetBridge mBridge;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mJniMocker.mock(AutofillVcnEnrollBottomSheetBridgeJni.TEST_HOOKS, mBridgeNatives);
+        Activity activity = Robolectric.buildActivity(Activity.class).create().get();
+        mWindow = new WindowAndroid(activity);
+        BottomSheetControllerFactory.attach(mWindow, mBottomSheetController);
+        mBridge = new AutofillVcnEnrollBottomSheetBridge();
+    }
+
+    @After
+    public void tearDown() {
+        BottomSheetControllerFactory.detach(mBottomSheetController);
+        mWindow.destroy();
+    }
+
+    private void requestShowContent(WebContents webContents) {
+        mBridge.requestShowContent(NATIVE_AUTOFILL_VCN_ENROLL_BOTTOM_SHEET_BRIDGE, webContents,
+                "Message text", "Accept button label", "Cancel button label");
+    }
+
+    @Test
+    public void testCannotShowWithNullWebContents() {
+        requestShowContent(/*webContents=*/null);
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testCannotShowWithDestroyedWebContents() {
+        when(mWebContents.isDestroyed()).thenReturn(true);
+
+        requestShowContent(mWebContents);
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testCannotShowWithoutTopLevelNativeWindow() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(null);
+
+        requestShowContent(mWebContents);
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testShowBottomSheet() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+
+        requestShowContent(mWebContents);
+
+        verify(mBottomSheetController)
+                .requestShowContent(any(AutofillVcnEnrollBottomSheetMediator.class),
+                        /*animate=*/eq(true));
+    }
+
+    @Test
+    public void testCannotAcceptWithoutShowing() {
+        mBridge.onAccept();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testAcceptAfterShowing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+
+        mBridge.onAccept();
+
+        verify(mBridgeNatives).onAccept(eq(NATIVE_AUTOFILL_VCN_ENROLL_BOTTOM_SHEET_BRIDGE));
+    }
+
+    @Test
+    public void testSecondAcceptDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.onAccept();
+        clearInvocations(mBridgeNatives);
+
+        mBridge.onAccept();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testDismissAfterAcceptDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.onAccept();
+        clearInvocations(mBridgeNatives);
+
+        mBridge.onDismiss();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testCannotCancelWithoutShowing() {
+        mBridge.onCancel();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testCancelAfterShowing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+
+        mBridge.onCancel();
+
+        verify(mBridgeNatives).onCancel(eq(NATIVE_AUTOFILL_VCN_ENROLL_BOTTOM_SHEET_BRIDGE));
+    }
+
+    @Test
+    public void testSecondCancelDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.onCancel();
+        clearInvocations(mBridgeNatives);
+
+        mBridge.onCancel();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testDismissAfterCancelDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.onCancel();
+        clearInvocations(mBridgeNatives);
+
+        mBridge.onDismiss();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testCannotDismissWithoutShowing() {
+        mBridge.onDismiss();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testDismissAfterShowing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+
+        mBridge.onDismiss();
+
+        verify(mBridgeNatives).onDismiss(eq(NATIVE_AUTOFILL_VCN_ENROLL_BOTTOM_SHEET_BRIDGE));
+    }
+
+    @Test
+    public void testSecondDismissDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.onDismiss();
+        clearInvocations(mBridgeNatives);
+
+        mBridge.onDismiss();
+
+        verifyNoInteractions(mBridgeNatives);
+    }
+
+    @Test
+    public void testHideWithoutShowing() {
+        mBridge.hide();
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testHideAfterShowing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+
+        mBridge.hide();
+
+        verify(mBottomSheetController)
+                .hideContent(any(), eq(true),
+                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
+    }
+
+    @Test
+    public void testSecondHideDoesNothing() {
+        when(mWebContents.isDestroyed()).thenReturn(false);
+        when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindow);
+        requestShowContent(mWebContents);
+        mBridge.hide();
+        clearInvocations(mBottomSheetController);
+
+        mBridge.hide();
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinatorTest.java
new file mode 100644
index 0000000..158cdbf
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetCoordinatorTest.java
@@ -0,0 +1,87 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.robolectric.Robolectric.buildActivity;
+
+import android.app.Activity;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+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.test.BaseRobolectricTestRunner;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory;
+import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController;
+import org.chromium.ui.base.WindowAndroid;
+
+/** Unit test for {@link AutofillVcnEnrollBottomSheetCoordinator}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@SmallTest
+public final class AutofillVcnEnrollBottomSheetCoordinatorTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private ManagedBottomSheetController mBottomSheetController;
+
+    private WindowAndroid mWindow;
+    private AutofillVcnEnrollBottomSheetCoordinator mCoordinator;
+
+    @Before
+    public void setUp() {
+        Activity activity = buildActivity(Activity.class).create().get();
+        mWindow = new WindowAndroid(activity);
+        BottomSheetControllerFactory.attach(mWindow, mBottomSheetController);
+        mCoordinator = new AutofillVcnEnrollBottomSheetCoordinator(mWindow.getContext().get(),
+                "Message text", "Accept Button Text", "Cancel Button Text", /*onAccept=*/() -> {},
+                /*onCancel=*/() -> {}, /*onDismiss=*/() -> {});
+    }
+
+    @After
+    public void tearDown() {
+        BottomSheetControllerFactory.detach(mBottomSheetController);
+        mWindow.destroy();
+    }
+
+    @Test
+    public void testShow() {
+        mCoordinator.requestShowContent(mWindow);
+
+        verify(mBottomSheetController)
+                .requestShowContent(any(AutofillVcnEnrollBottomSheetMediator.class),
+                        /*animate=*/eq(true));
+    }
+
+    @Test
+    public void testHideAfterShow() {
+        mCoordinator.requestShowContent(mWindow);
+        mCoordinator.hide();
+
+        verify(mBottomSheetController)
+                .hideContent(any(AutofillVcnEnrollBottomSheetMediator.class),
+                        /*animate=*/eq(true),
+                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
+    }
+
+    @Test
+    public void testHideWithoutShow() {
+        mCoordinator.hide();
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediatorTest.java
new file mode 100644
index 0000000..af0cd03
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediatorTest.java
@@ -0,0 +1,215 @@
+// 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.
+
+package org.chromium.chrome.browser.autofill.vcn;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+import android.app.Activity;
+import android.content.Context;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+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.robolectric.Robolectric;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.R;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory;
+import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController;
+import org.chromium.ui.base.WindowAndroid;
+
+/** Unit test for {@link AutofillVcnEnrollBottomSheetMediator}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@SmallTest
+public final class AutofillVcnEnrollBottomSheetMediatorTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private ManagedBottomSheetController mBottomSheetController;
+
+    private WindowAndroid mWindow;
+    private View mContentView;
+    private View mAcceptButton;
+    private View mCancelButton;
+    private boolean mAccepted;
+    private boolean mCancelled;
+    private boolean mDismissed;
+    private AutofillVcnEnrollBottomSheetMediator mMediator;
+
+    @Before
+    public void setUp() {
+        Activity activity = Robolectric.buildActivity(Activity.class).create().get();
+        mWindow = new WindowAndroid(activity);
+        BottomSheetControllerFactory.attach(mWindow, mBottomSheetController);
+        Context context = mWindow.getContext().get();
+        mContentView = new View(context);
+        mAcceptButton = new View(context);
+        mCancelButton = new View(context);
+        mAccepted = false;
+        mCancelled = false;
+        mDismissed = false;
+        mMediator = new AutofillVcnEnrollBottomSheetMediator(mContentView, mAcceptButton,
+                mCancelButton, this::onAccept, this::onCancel, this::onDismiss);
+    }
+
+    private void onAccept() {
+        mAccepted = true;
+    }
+    private void onCancel() {
+        mCancelled = true;
+    }
+    private void onDismiss() {
+        mDismissed = true;
+    }
+
+    @After
+    public void tearDown() {
+        BottomSheetControllerFactory.detach(mBottomSheetController);
+        mWindow.destroy();
+    }
+
+    @Test
+    public void testShowBottomSheet() {
+        mMediator.requestShowContent(mWindow);
+
+        verify(mBottomSheetController)
+                .requestShowContent(/*content=*/eq(mMediator), /*animate=*/eq(true));
+    }
+
+    @Test
+    public void testClickAcceptButtonAfterShowing() {
+        mMediator.requestShowContent(mWindow);
+
+        mMediator.onClick(mAcceptButton);
+
+        assertTrue(mAccepted);
+        verifyBottomSheetControllerHideContentCalled();
+    }
+
+    @Test
+    public void testClickCancelButtonAfterShowing() {
+        mMediator.requestShowContent(mWindow);
+
+        mMediator.onClick(mCancelButton);
+
+        assertTrue(mCancelled);
+        verifyBottomSheetControllerHideContentCalled();
+    }
+
+    @Test
+    public void testHideBottomSheetAfterShowing() {
+        mMediator.requestShowContent(mWindow);
+        mMediator.hide();
+
+        verifyBottomSheetControllerHideContentCalled();
+    }
+
+    private void verifyBottomSheetControllerHideContentCalled() {
+        verify(mBottomSheetController)
+                .hideContent(/*content=*/eq(mMediator), /*animate=*/eq(true),
+                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
+    }
+
+    @Test
+    public void testClickAcceptButtonWithoutShowing() {
+        mMediator.onClick(mAcceptButton);
+
+        assertTrue(mAccepted);
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testClickCancelButtonWithoutShowing() {
+        mMediator.onClick(mCancelButton);
+
+        assertTrue(mCancelled);
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testHideBottomSheetWithoutShowing() {
+        mMediator.hide();
+
+        verifyNoInteractions(mBottomSheetController);
+    }
+
+    @Test
+    public void testContentView() {
+        assertThat(mMediator.getContentView(), equalTo(mContentView));
+    }
+
+    @Test
+    public void testBottomSheetHasNoToolbar() {
+        assertThat(mMediator.getToolbarView(), nullValue());
+    }
+
+    @Test
+    public void testNoVerticalScrollOffset() {
+        assertThat(mMediator.getVerticalScrollOffset(), equalTo(0));
+    }
+
+    @Test
+    public void testDismissBottomSheet() {
+        mMediator.destroy();
+
+        assertTrue(mDismissed);
+    }
+
+    @Test
+    public void testBottomSheetPriority() {
+        assertThat(mMediator.getPriority(), equalTo(BottomSheetContent.ContentPriority.HIGH));
+    }
+
+    @Test
+    public void testCannotSwipeToDismissBottomSheet() {
+        assertThat(mMediator.swipeToDismissEnabled(), equalTo(false));
+    }
+
+    @Test
+    public void testBottomSheetAccessibilityContentDescriotion() {
+        assertThat(mMediator.getSheetContentDescriptionStringId(),
+                equalTo(R.string.autofill_virtual_card_enroll_content_description));
+    }
+
+    @Test
+    public void testBottomSheetFullHeightAccessibilityDescription() {
+        assertThat(mMediator.getSheetFullHeightAccessibilityStringId(),
+                equalTo(R.string.autofill_virtual_card_enroll_full_height_content_description));
+    }
+
+    @Test
+    public void testBottomSheetClosedAccessibilityDescription() {
+        assertThat(mMediator.getSheetClosedAccessibilityStringId(),
+                equalTo(R.string.autofill_virtual_card_enroll_closed_description));
+    }
+
+    @Test
+    public void testBottomSheetCannotPeek() {
+        assertThat(mMediator.getPeekHeight(), equalTo(BottomSheetContent.HeightMode.DISABLED));
+    }
+
+    @Test
+    public void testContentDeterminesBottomSheetHeight() {
+        assertThat(mMediator.getFullHeightRatio(),
+                equalTo((float) BottomSheetContent.HeightMode.WRAP_CONTENT));
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
index 6f679d0d..e401116 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -155,7 +155,8 @@
         env.changeTab(newTab);
 
         clearInvocations(env.tabFromFactory);
-        mNavigationController.navigate(OTHER_URL);
+        LoadUrlParams params = new LoadUrlParams(OTHER_URL);
+        mNavigationController.navigate(params, new Intent());
         verify(newTab).loadUrl(any());
         verify(env.tabFromFactory, never()).loadUrl(any());
     }
@@ -184,7 +185,7 @@
 
         clearInvocations(env.tabFromFactory);
         LoadUrlParams params = new LoadUrlParams(SPECULATED_URL);
-        mNavigationController.navigate(params, 0);
+        mNavigationController.navigate(params, new Intent());
         verify(hiddenTab).loadUrl(params);
     }
 
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index e3a4b63c..1121017c 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -4114,10 +4114,10 @@
     Sites are blocked from asking you to use info they've saved about you
   </message>
   <message name="IDS_SETTINGS_STORAGE_ACCESS_ALLOWED_EXCEPTIONS" desc="A sub title on the Embedded content settings page. When a user grants a site permission, that site appears in this list of sites.">
-    You allowed these sites to use info they've saved about you
+    Allowed to use info they've saved about you
   </message>
   <message name="IDS_SETTINGS_STORAGE_ACCESS_BLOCKED_EXCEPTIONS" desc="A sub title on the Embedded content settings page. When a user denies a site permission, that site appears in this list of sites.">
-    You blocked these sites from using info they've saved about you
+    Blocked from using info they've saved about you
   </message>
   <message name="IDS_SETTINGS_STORAGE_ACCESS_RESET_ALL" desc="Label for the trashcan button to reset the permission for allowing or blocking a website to access its unpartitioned cookies while embedded in all other sites.">
     Remove <ph name="SITE">$1<ex>google.com</ex></ph>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_ALLOWED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_ALLOWED_EXCEPTIONS.png.sha1
index 901dfd9..edd91d4 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_ALLOWED_EXCEPTIONS.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_ALLOWED_EXCEPTIONS.png.sha1
@@ -1 +1 @@
-795fb07979d26adb17d18e39e885f07341dc8bbc
+7bab753deef21fc31cb6b3f97d1c22b32851435d
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_BLOCKED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_BLOCKED_EXCEPTIONS.png.sha1
index 901dfd9..edd91d4 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_BLOCKED_EXCEPTIONS.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_STORAGE_ACCESS_BLOCKED_EXCEPTIONS.png.sha1
@@ -1 +1 @@
-795fb07979d26adb17d18e39e885f07341dc8bbc
+7bab753deef21fc31cb6b3f97d1c22b32851435d
\ No newline at end of file
diff --git a/chrome/browser/android/browserservices/intents/BUILD.gn b/chrome/browser/android/browserservices/intents/BUILD.gn
index 537ab53..9c5e6c52 100644
--- a/chrome/browser/android/browserservices/intents/BUILD.gn
+++ b/chrome/browser/android/browserservices/intents/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     "//base:base_java",
     "//chrome/android/webapk/libs/common:common_java",
+    "//chrome/browser/android/intents:java",
     "//chrome/browser/flags:java",
     "//components/webapps/browser/android:java",
     "//content/public/android:content_main_dex_java",
@@ -47,6 +48,7 @@
     "//chrome/android/webapk/libs/common:common_java",
     "//chrome/android/webapk/libs/common:splash_java",
     "//chrome/android/webapk/test:junit_test_support",
+    "//chrome/browser/android/intents:java",
     "//chrome/test/android:chrome_java_unit_test_support",
     "//components/webapk/android/libs/common:java",
     "//components/webapps/browser/android:java",
diff --git a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtils.java b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtils.java
index ad3dc1e..d25aa5e0 100644
--- a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtils.java
+++ b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtils.java
@@ -9,6 +9,7 @@
 import android.provider.Browser;
 
 import org.chromium.base.IntentUtils;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
 import org.chromium.ui.util.ColorUtils;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
@@ -30,7 +31,8 @@
             WebappConstants.EXTRA_ORIENTATION, WebappConstants.EXTRA_THEME_COLOR,
             WebappConstants.EXTRA_BACKGROUND_COLOR, WebappConstants.EXTRA_IS_ICON_GENERATED,
             WebappConstants.EXTRA_IS_ICON_ADAPTIVE, WebappConstants.EXTRA_DARK_THEME_COLOR,
-            WebappConstants.EXTRA_DARK_BACKGROUND_COLOR};
+            WebappConstants.EXTRA_DARK_BACKGROUND_COLOR, BrowserIntentUtils.EXTRA_STARTUP_UPTIME_MS,
+            BrowserIntentUtils.EXTRA_STARTUP_REALTIME_MS};
 
     /**
      * WebAPK intent extras. Used for copying intent extras for {@link WebappActivity} launch
@@ -44,7 +46,8 @@
             WebApkConstants.EXTRA_NEW_STYLE_SPLASH_SHOWN_TIME,
             WebApkConstants.EXTRA_WEBAPK_SELECTED_SHARE_TARGET_ACTIVITY_CLASS_NAME,
             Intent.EXTRA_SUBJECT, Intent.EXTRA_TEXT, Intent.EXTRA_STREAM,
-            Browser.EXTRA_APPLICATION_ID};
+            Browser.EXTRA_APPLICATION_ID, BrowserIntentUtils.EXTRA_STARTUP_UPTIME_MS,
+            BrowserIntentUtils.EXTRA_STARTUP_REALTIME_MS};
 
     /**
      * Converts color from signed Integer where an unspecified color is represented as null to
diff --git a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtilsTest.java b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtilsTest.java
index dd59528..2870c12 100644
--- a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtilsTest.java
+++ b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/WebappIntentUtilsTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 
 import android.content.Intent;
@@ -16,6 +17,7 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.intents.BrowserIntentUtils;
 
 import java.util.ArrayList;
 
@@ -56,6 +58,7 @@
         fromIntent.putExtra(WebappConstants.EXTRA_BACKGROUND_COLOR, 1L);
         fromIntent.putExtra(WebappConstants.EXTRA_DARK_THEME_COLOR, 2L);
         fromIntent.putExtra(WebappConstants.EXTRA_DARK_BACKGROUND_COLOR, 3L);
+        BrowserIntentUtils.addStartupTimestampsToIntent(fromIntent);
 
         Intent toIntent = new Intent();
         WebappIntentUtils.copyWebappLaunchIntentExtras(fromIntent, toIntent);
@@ -67,6 +70,8 @@
         assertEquals(1L, toIntent.getLongExtra(WebappConstants.EXTRA_BACKGROUND_COLOR, 0L));
         assertEquals(2L, toIntent.getLongExtra(WebappConstants.EXTRA_DARK_THEME_COLOR, 0L));
         assertEquals(3L, toIntent.getLongExtra(WebappConstants.EXTRA_DARK_BACKGROUND_COLOR, 0L));
+        assertNotEquals(-1L, BrowserIntentUtils.getStartupRealtimeMillis(toIntent));
+        assertNotEquals(-1L, BrowserIntentUtils.getStartupUptimeMillis(toIntent));
     }
 
     /**
diff --git a/chrome/browser/android/consent_auditor/DIR_METADATA b/chrome/browser/android/consent_auditor/DIR_METADATA
index c75f2f8..4a58e65 100644
--- a/chrome/browser/android/consent_auditor/DIR_METADATA
+++ b/chrome/browser/android/consent_auditor/DIR_METADATA
@@ -1 +1 @@
-mixins: "//components/consent_auditor/COMMON_METADATA"
+mixins: "//components/sync/COMMON_METADATA"
diff --git a/chrome/browser/android/intents/BUILD.gn b/chrome/browser/android/intents/BUILD.gn
new file mode 100644
index 0000000..2ce73d2
--- /dev/null
+++ b/chrome/browser/android/intents/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+  sources =
+      [ "java/src/org/chromium/chrome/browser/intents/BrowserIntentUtils.java" ]
+  deps = [ "//base:base_java" ]
+}
+
+android_library("unit_device_javatests") {
+  testonly = true
+  sources = [ "java/src/org/chromium/chrome/browser/intents/BrowserIntentUtilsUnitTest.java" ]
+  deps = [
+    ":java",
+    "//base:base_java",
+    "//base:base_java_test_support",
+    "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/androidx:androidx_test_core_java",
+    "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/hamcrest:hamcrest_java",
+    "//third_party/hamcrest:hamcrest_library_java",
+    "//third_party/junit",
+  ]
+}
diff --git a/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtils.java b/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtils.java
new file mode 100644
index 0000000..f3bebf7
--- /dev/null
+++ b/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtils.java
@@ -0,0 +1,52 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.intents;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.SystemClock;
+
+/**
+ * Modularized Intent utilities for use by other feature modules and chrome_java.
+ */
+public class BrowserIntentUtils {
+    /**
+     * Key to associate a startup timestamp in the uptimeMillis timebase with an intent.
+     */
+    public static final String EXTRA_STARTUP_UPTIME_MS =
+            "org.chromium.chrome.browser.startup.uptime";
+
+    /**
+     * Key to associate a startup timestamp in the elapsedRealtime timebase with an intent.
+     */
+    public static final String EXTRA_STARTUP_REALTIME_MS =
+            "org.chromium.chrome.browser.startup.realtime";
+
+    /**
+     * Adds two timestamps to an intent, as returned by {@link SystemClock#elapsedRealtime()}.
+     *
+     * To track page load time, this needs to be called as close as possible to
+     * the entry point (in {@link Activity#onCreate()} for instance).
+     */
+    public static void addStartupTimestampsToIntent(Intent intent) {
+        intent.putExtra(EXTRA_STARTUP_REALTIME_MS, SystemClock.elapsedRealtime());
+        intent.putExtra(EXTRA_STARTUP_UPTIME_MS, SystemClock.uptimeMillis());
+    }
+
+    /**
+     * @return the startup timestamp associated with an intent in the elapsedRealtime timebase, or
+     *         -1.
+     */
+    public static long getStartupRealtimeMillis(Intent intent) {
+        return intent.getLongExtra(EXTRA_STARTUP_REALTIME_MS, -1);
+    }
+
+    /**
+     * @return the startup timestamp associated with an intent in the uptimeMillis timebase, or -1.
+     */
+    public static long getStartupUptimeMillis(Intent intent) {
+        return intent.getLongExtra(EXTRA_STARTUP_UPTIME_MS, -1);
+    }
+}
diff --git a/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtilsUnitTest.java b/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtilsUnitTest.java
new file mode 100644
index 0000000..db60091d
--- /dev/null
+++ b/chrome/browser/android/intents/java/src/org/chromium/chrome/browser/intents/BrowserIntentUtilsUnitTest.java
@@ -0,0 +1,48 @@
+// 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.
+
+package org.chromium.chrome.browser.intents;
+
+import android.content.Intent;
+import android.os.SystemClock;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
+
+@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
+public class BrowserIntentUtilsUnitTest {
+    @Test
+    @SmallTest
+    public void testAddTimestampToIntent() {
+        Intent intent = new Intent();
+        Assert.assertEquals(-1, BrowserIntentUtils.getStartupRealtimeMillis(intent));
+        Assert.assertEquals(-1, BrowserIntentUtils.getStartupUptimeMillis(intent));
+        // Check both before and after to make sure that the returned value is
+        // really from {@link SystemClock#elapsedRealtime()}.
+        long before = SystemClock.elapsedRealtime();
+        BrowserIntentUtils.addStartupTimestampsToIntent(intent);
+        long after = SystemClock.elapsedRealtime();
+        Assert.assertTrue("Time should be increasing",
+                before <= BrowserIntentUtils.getStartupRealtimeMillis(intent));
+        Assert.assertTrue("Time should be increasing",
+                BrowserIntentUtils.getStartupRealtimeMillis(intent) <= after);
+
+        // Check both before and after to make sure that the returned value is
+        // really from {@link SystemClock#uptimeMillis()}.
+        before = SystemClock.uptimeMillis();
+        BrowserIntentUtils.addStartupTimestampsToIntent(intent);
+        after = SystemClock.uptimeMillis();
+        Assert.assertTrue("Time should be increasing",
+                before <= BrowserIntentUtils.getStartupUptimeMillis(intent));
+        Assert.assertTrue("Time should be increasing",
+                BrowserIntentUtils.getStartupUptimeMillis(intent) <= after);
+    }
+}
diff --git a/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc b/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc
index 3b665632..bf58a487 100644
--- a/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc
+++ b/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc
@@ -467,8 +467,12 @@
       "<span lang='en-US'>The first paragraph</span>"
       "<span lang='fr-FR'>le deuxième paragraphe</span></div>");
 
-  sm_.ExpectSpeechPatternWithLocale("The first paragraph*", "en-US");
-  sm_.ExpectSpeechPatternWithLocale("le deuxième paragraphe*", "fr-FR");
+  sm_.ExpectSpeech(test::SpeechMonitor::Expectation("The first paragraph*")
+                       .AsPattern()
+                       .WithLocale("en-US"));
+  sm_.ExpectSpeech(test::SpeechMonitor::Expectation("le deuxième paragraphe*")
+                       .AsPattern()
+                       .WithLocale("fr-FR"));
   sm_.Replay();
 }
 
diff --git a/chrome/browser/ash/accessibility/speech_monitor.cc b/chrome/browser/ash/accessibility/speech_monitor.cc
index 31d4a3b..3692811c 100644
--- a/chrome/browser/ash/accessibility/speech_monitor.cc
+++ b/chrome/browser/ash/accessibility/speech_monitor.cc
@@ -18,6 +18,65 @@
 
 }  // namespace
 
+SpeechMonitor::Expectation::Expectation(const std::string& text)
+    : text_(text) {}
+SpeechMonitor::Expectation::~Expectation() = default;
+SpeechMonitor::Expectation::Expectation(const Expectation&) = default;
+
+base::circular_deque<SpeechMonitorUtterance>::const_iterator
+SpeechMonitor::Expectation::Matches(
+    const base::circular_deque<SpeechMonitorUtterance>& queue) const {
+  std::vector<std::string> all_text;
+  for (auto it = queue.begin(); it != queue.end(); it++) {
+    if (base::Contains(disallowed_text_, it->text)) {
+      break;
+    }
+
+    all_text.push_back(it->text);
+    std::string joined_all_text = base::JoinString(all_text, " ");
+    bool text_match = as_pattern_
+                          ? (base::MatchPattern(it->text, text_) ||
+                             base::MatchPattern(joined_all_text, "*" + text_))
+                          : (it->text == text_ ||
+                             joined_all_text.find(text_) != std::string::npos);
+    if (!text_match) {
+      continue;
+    }
+
+    bool locale_match = !locale_ || it->lang == locale_;
+    if (!locale_match) {
+      continue;
+    }
+
+    return it;
+  }
+  return queue.end();
+}
+
+std::string SpeechMonitor::Expectation::ToString() const {
+  std::string ret = "\"" + text_ + "\"";
+  std::string options = OptionsToString();
+  if (!options.empty()) {
+    ret += " {" + options + "}";
+  }
+  return ret;
+}
+
+std::string SpeechMonitor::Expectation::OptionsToString() const {
+  std::vector<std::string> option_str;
+  if (as_pattern_) {
+    option_str.push_back("pattern: true");
+  }
+  if (locale_) {
+    option_str.push_back("locale: " + locale_.value());
+  }
+  if (disallowed_text_.size() > 0) {
+    option_str.push_back("disallowed: [" +
+                         base::JoinString(disallowed_text_, ", ") + "]");
+  }
+  return base::JoinString(option_str, ", ");
+}
+
 SpeechMonitor::SpeechMonitor() {
   content::TtsController::SkipAddNetworkChangeObserverForTests(true);
   content::TtsController::GetInstance()->SetTtsPlatform(this);
@@ -133,58 +192,31 @@
   return delay_for_last_utterance_ms_;
 }
 
-void SpeechMonitor::ExpectSpeech(const std::string& text,
+void SpeechMonitor::ExpectSpeech(const Expectation& expectation,
                                  const base::Location& location) {
   CHECK(!replay_loop_runner_.get());
   replay_queue_.push_back(
-      {[this, text]() {
-         std::vector<std::string> all_text;
-         for (auto it = utterance_queue_.begin(); it != utterance_queue_.end();
-              it++) {
-           all_text.push_back(it->text);
-           std::string joined_all_text = base::JoinString(all_text, " ");
-           if (it->text == text ||
-               joined_all_text.find(text) != std::string::npos) {
-             // Erase all utterances that came before the
-             // match as well as the match itself.
-             utterance_queue_.erase(utterance_queue_.begin(), it + 1);
-             return true;
-           }
+      {[this, expectation]() {
+         auto itr = expectation.Matches(utterance_queue_);
+         if (itr != utterance_queue_.end()) {
+           // Erase all utterances that came before the
+           // match as well as the match itself.
+           utterance_queue_.erase(utterance_queue_.begin(), itr + 1);
+           return true;
          }
          return false;
        },
-       "ExpectSpeech(\"" + text + "\") " + location.ToString()});
+       "ExpectSpeech(" + expectation.ToString() + ") " + location.ToString()});
+}
+
+void SpeechMonitor::ExpectSpeech(const std::string& text,
+                                 const base::Location& location) {
+  ExpectSpeech(Expectation(text), location);
 }
 
 void SpeechMonitor::ExpectSpeechPattern(const std::string& pattern,
                                         const base::Location& location) {
-  ExpectSpeechPatternWithLocale(pattern, "", location);
-}
-
-void SpeechMonitor::ExpectSpeechPatternWithLocale(
-    const std::string& pattern,
-    const std::string& locale,
-    const base::Location& location) {
-  CHECK(!replay_loop_runner_.get());
-  replay_queue_.push_back(
-      {[this, pattern, locale]() {
-         std::vector<std::string> all_text;
-         for (auto it = utterance_queue_.begin(); it != utterance_queue_.end();
-              it++) {
-           all_text.push_back(it->text);
-           std::string joined_all_text = base::JoinString(all_text, " ");
-           if ((base::MatchPattern(it->text, pattern) &&
-                (locale.empty() || it->lang == locale)) ||
-               base::MatchPattern(joined_all_text, "*" + pattern)) {
-             // Erase all utterances that came before the
-             // match as well as the match itself.
-             utterance_queue_.erase(utterance_queue_.begin(), it + 1);
-             return true;
-           }
-         }
-         return false;
-       },
-       "ExpectSpeechPattern(\"" + pattern + "\") " + location.ToString()});
+  ExpectSpeech(Expectation(pattern).AsPattern(), location);
 }
 
 void SpeechMonitor::ExpectNextSpeechIsNot(const std::string& text,
diff --git a/chrome/browser/ash/accessibility/speech_monitor.h b/chrome/browser/ash/accessibility/speech_monitor.h
index 55e7cad..d337eae 100644
--- a/chrome/browser/ash/accessibility/speech_monitor.h
+++ b/chrome/browser/ash/accessibility/speech_monitor.h
@@ -38,6 +38,48 @@
 
   virtual ~SpeechMonitor();
 
+  // Holds an expectation for utterances.
+  class Expectation {
+   public:
+    explicit Expectation(const std::string& text);
+    ~Expectation();
+    Expectation(const Expectation&);
+
+    // Sets to perform regular expression matching.
+    Expectation& AsPattern(bool enable = true) {
+      as_pattern_ = true;
+      return *this;
+    }
+
+    // Sets the expected locale for the given text.
+    Expectation& WithLocale(const std::string& locale) {
+      locale_ = locale;
+      return *this;
+    }
+
+    // Sets the unexpected utterances until this consumes the expectation.
+    Expectation& WithoutText(const std::vector<std::string>& text) {
+      disallowed_text_ = text;
+      return *this;
+    }
+
+    // Checks the given list of utterances matches this expectation.
+    // Returns the iterator that points the matched item in the given list.
+    // If not matched, returns the end() of the given list.
+    base::circular_deque<SpeechMonitorUtterance>::const_iterator Matches(
+        const base::circular_deque<SpeechMonitorUtterance>& queue) const;
+
+    std::string ToString() const;
+
+   private:
+    std::string OptionsToString() const;
+
+    std::string text_;
+    bool as_pattern_ = false;
+    absl::optional<std::string> locale_;
+    std::vector<std::string> disallowed_text_;
+  };
+
   // Use these apis if you want to write an async test e.g.
   // sm_.ExpectSpeech("foo");
   // sm_.Call([this]() { DoSomething(); })
@@ -47,14 +89,12 @@
 #pragma clang diagnostic ignored "-Wpredefined-identifier-outside-function"
 
   // Adds an expectation of spoken text.
+  void ExpectSpeech(const Expectation& expectation,
+                    const base::Location& location = FROM_HERE);
   void ExpectSpeech(const std::string& text,
                     const base::Location& location = FROM_HERE);
   void ExpectSpeechPattern(const std::string& pattern,
                            const base::Location& location = FROM_HERE);
-  void ExpectSpeechPatternWithLocale(
-      const std::string& pattern,
-      const std::string& locale,
-      const base::Location& location = FROM_HERE);
   void ExpectNextSpeechIsNot(const std::string& text,
                              const base::Location& location = FROM_HERE);
   void ExpectNextSpeechIsNotPattern(const std::string& pattern,
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
index a417e52..b39062c 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -2440,14 +2440,8 @@
     candidate_window.mutable_candidates()->at(1).label = u"label 3";
     candidate_window_view_->UpdateCandidates(candidate_window);
   });
-  // TODO(hirokisato): We should check unexpected utterances are not skipped
-  // when consuming "value 2", otherwise there's a race between when we check
-  // "NextSpeechIsNot" and when speech is created, and test may pass
-  // unexpectedly.
-  sm_.ExpectNextSpeechIsNot("value 0");
-  sm_.ExpectNextSpeechIsNot("value 1");
-  sm_.ExpectNextSpeechIsNot("value 3");
-  sm_.ExpectSpeech("value 2");
+  sm_.ExpectSpeech(test::SpeechMonitor::Expectation("value 2").WithoutText(
+      {"value 0", "value 1", "value 3"}));
 
   sm_.Replay();
 }
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index 24aea83..90d0bf2 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -63,6 +63,8 @@
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom-shared.h"
 #include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h"
+#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
+#include "chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h"
 #include "chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h"
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
@@ -441,14 +443,10 @@
                        drive::util::ConnectionStatus::kConnected;
   if (!integration_service || !integration_service->IsMounted() ||
       !integration_service->GetDriveFsInterface()) {
-    UMA_HISTOGRAM_ENUMERATION(kDriveErrorMetricName,
-                              OfficeDriveOpenErrors::kDriveFsInterface);
     return GetUserFallbackChoice(
         profile, task, file_urls, modal_parent,
         ash::office_fallback::FallbackReason::kDriveUnavailable);
   } else if (offline) {
-    UMA_HISTOGRAM_ENUMERATION(kDriveErrorMetricName,
-                              OfficeDriveOpenErrors::kOffline);
     // TODO(petermarshall): Quick Office vs. other default handler.
     return GetUserFallbackChoice(
         profile, task, file_urls, modal_parent,
@@ -469,8 +467,6 @@
                              const std::vector<FileSystemURL>& file_urls,
                              gfx::NativeWindow modal_parent) {
   if (content::GetNetworkConnectionTracker()->IsOffline()) {
-    UMA_HISTOGRAM_ENUMERATION(kOneDriveErrorMetricName,
-                              OfficeOneDriveOpenErrors::kOffline);
     return GetUserFallbackChoice(
         profile, task, file_urls, modal_parent,
         ash::office_fallback::FallbackReason::kOffline);
@@ -575,6 +571,39 @@
   return drive::util::IsEncryptedMimeType(entry.mime_type);
 }
 
+void LogOneDriveOpenErrorUmaAfterFallback(
+    ash::office_fallback::FallbackReason fallback_reason,
+    ash::cloud_upload::OfficeTaskResult task_result) {
+  switch (fallback_reason) {
+    case ash::office_fallback::FallbackReason::kOffline:
+      UMA_HISTOGRAM_ENUMERATION(kOneDriveErrorMetricName,
+                                OfficeOneDriveOpenErrors::kOffline);
+      break;
+    case ash::office_fallback::FallbackReason::kDriveUnavailable:
+      NOTREACHED();
+      break;
+  }
+  UMA_HISTOGRAM_ENUMERATION(ash::cloud_upload::kOneDriveTaskResultMetricName,
+                            task_result);
+}
+
+void LogGoogleDriveOpenErrorUmaAfterFallback(
+    ash::office_fallback::FallbackReason fallback_reason,
+    ash::cloud_upload::OfficeTaskResult task_result) {
+  switch (fallback_reason) {
+    case ash::office_fallback::FallbackReason::kOffline:
+      UMA_HISTOGRAM_ENUMERATION(kDriveErrorMetricName,
+                                OfficeDriveOpenErrors::kOffline);
+      break;
+    case ash::office_fallback::FallbackReason::kDriveUnavailable:
+      UMA_HISTOGRAM_ENUMERATION(kDriveErrorMetricName,
+                                OfficeDriveOpenErrors::kDriveFsInterface);
+      break;
+  }
+  UMA_HISTOGRAM_ENUMERATION(ash::cloud_upload::kGoogleDriveTaskResultMetricName,
+                            task_result);
+}
+
 }  // namespace
 
 ResultingTasks::ResultingTasks() = default;
@@ -1016,23 +1045,29 @@
   return;
 }
 
-void OnDialogChoiceReceived(Profile* profile,
-                            const TaskDescriptor& task,
-                            const std::vector<FileSystemURL>& file_urls,
-                            gfx::NativeWindow modal_parent,
-                            const std::string& choice) {
+void OnDialogChoiceReceived(
+    Profile* profile,
+    const TaskDescriptor& task,
+    const std::vector<FileSystemURL>& file_urls,
+    gfx::NativeWindow modal_parent,
+    const std::string& choice,
+    ash::office_fallback::FallbackReason fallback_reason) {
   if (choice == ash::office_fallback::kDialogChoiceQuickOffice) {
     if (IsWebDriveOfficeTask(task)) {
-      UMA_HISTOGRAM_ENUMERATION(
-          ash::cloud_upload::kGoogleDriveTaskResultMetricName,
+      LogGoogleDriveOpenErrorUmaAfterFallback(
+          fallback_reason,
           ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice);
     } else if (IsOpenInOfficeTask(task)) {
-      UMA_HISTOGRAM_ENUMERATION(
-          ash::cloud_upload::kOneDriveTaskResultMetricName,
+      LogOneDriveOpenErrorUmaAfterFallback(
+          fallback_reason,
           ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice);
     }
     LaunchQuickOffice(profile, file_urls);
   } else if (choice == ash::office_fallback::kDialogChoiceTryAgain) {
+    // When retrying, the original open result is thrown away, so that
+    // (likely the same) result codes from repeated retries are not counted.
+    // Only the last open result is recorded: when the user either selects
+    // QO or cancels.
     if (IsWebDriveOfficeTask(task)) {
       ExecuteWebDriveOfficeTask(profile, task, file_urls, modal_parent);
     } else if (IsOpenInOfficeTask(task)) {
@@ -1040,13 +1075,11 @@
     }
   } else if (choice == ash::office_fallback::kDialogChoiceCancel) {
     if (IsWebDriveOfficeTask(task)) {
-      UMA_HISTOGRAM_ENUMERATION(
-          ash::cloud_upload::kGoogleDriveTaskResultMetricName,
-          ash::cloud_upload::OfficeTaskResult::kFailedToOpen);
+      LogGoogleDriveOpenErrorUmaAfterFallback(
+          fallback_reason, ash::cloud_upload::OfficeTaskResult::kCancelled);
     } else if (IsOpenInOfficeTask(task)) {
-      UMA_HISTOGRAM_ENUMERATION(
-          ash::cloud_upload::kOneDriveTaskResultMetricName,
-          ash::cloud_upload::OfficeTaskResult::kFailedToOpen);
+      LogOneDriveOpenErrorUmaAfterFallback(
+          fallback_reason, ash::cloud_upload::OfficeTaskResult::kCancelled);
     }
   }
 }
diff --git a/chrome/browser/ash/file_manager/file_tasks.h b/chrome/browser/ash/file_manager/file_tasks.h
index e44732e4..20e6872 100644
--- a/chrome/browser/ash/file_manager/file_tasks.h
+++ b/chrome/browser/ash/file_manager/file_tasks.h
@@ -402,11 +402,13 @@
 // If user's `choice` is `kDialogChoiceQuickOffice`, launch QuickOffice.
 // If user's `choice` is `kDialogChoiceTryAgain`, execute the `task`.
 // If user's `choice` is `kDialogChoiceCancel`, do nothing.
-void OnDialogChoiceReceived(Profile* profile,
-                            const TaskDescriptor& task,
-                            const std::vector<FileSystemURL>& file_urls,
-                            gfx::NativeWindow modal_parent,
-                            const std::string& choice);
+void OnDialogChoiceReceived(
+    Profile* profile,
+    const TaskDescriptor& task,
+    const std::vector<FileSystemURL>& file_urls,
+    gfx::NativeWindow modal_parent,
+    const std::string& choice,
+    ash::office_fallback::FallbackReason fallback_reason);
 
 // Shows a new dialog for users to choose what to do next. Returns True
 // if a new dialog has been effectively created.
diff --git a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
index 7a43c166..8e5f675 100644
--- a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
@@ -1192,7 +1192,8 @@
   // Run dialog callback, simulate user choosing to "try-again". Will succeed
   // because system is online.
   OnDialogChoiceReceived(profile(), web_drive_office_task, file_urls, nullptr,
-                         ash::office_fallback::kDialogChoiceTryAgain);
+                         ash::office_fallback::kDialogChoiceTryAgain,
+                         ash::office_fallback::FallbackReason::kOffline);
 
   // Wait for file to open in web drive office.
   navigation_observer_office.Wait();
@@ -1525,7 +1526,8 @@
   // Run dialog callback, simulate user choosing to "try-again". Will succeed
   // because system is online, and the file doesn't need to be moved.
   OnDialogChoiceReceived(profile(), open_in_office_task, file_urls, nullptr,
-                         ash::office_fallback::kDialogChoiceTryAgain);
+                         ash::office_fallback::kDialogChoiceTryAgain,
+                         ash::office_fallback::FallbackReason::kOffline);
 
   auto launches = web_app_publisher_->GetLaunches();
   ASSERT_EQ(1u, launches.size());
@@ -1573,7 +1575,8 @@
   // Run dialog callback, simulate user choosing to "cancel". The file will not
   // open.
   OnDialogChoiceReceived(profile(), open_in_office_task, file_urls, nullptr,
-                         ash::office_fallback::kDialogChoiceCancel);
+                         ash::office_fallback::kDialogChoiceCancel,
+                         ash::office_fallback::FallbackReason::kOffline);
 
   ASSERT_EQ(0u, web_app_publisher_->GetLaunches().size());
 }
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
index a2fbb13..f03c54746 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -1135,12 +1135,7 @@
   ~DemoSetupQuickStartEnabledTest() override = default;
 
   DemoSetupQuickStartEnabledTest() {
-    feature_list_.InitWithFeatures(
-        {
-            features::kEnableOobeNetworkScreenSkip,
-            features::kOobeQuickStart,
-        },
-        {});
+    feature_list_.InitAndEnableFeature(features::kOobeQuickStart);
   }
 
  private:
diff --git a/chrome/browser/ash/login/screens/network_screen.cc b/chrome/browser/ash/login/screens/network_screen.cc
index 4bd8e12..85d49d2 100644
--- a/chrome/browser/ash/login/screens/network_screen.cc
+++ b/chrome/browser/ash/login/screens/network_screen.cc
@@ -258,8 +258,7 @@
 }
 
 bool NetworkScreen::UpdateStatusIfConnectedToEthernet() {
-  if (!features::IsOobeNetworkScreenSkipEnabled() ||
-      switches::IsOOBENetworkScreenSkippingDisabledForTesting()) {
+  if (switches::IsOOBENetworkScreenSkippingDisabledForTesting()) {
     return false;
   }
 
diff --git a/chrome/browser/ash/login/screens/network_screen_browsertest.cc b/chrome/browser/ash/login/screens/network_screen_browsertest.cc
index f5e7968..bb7dc177 100644
--- a/chrome/browser/ash/login/screens/network_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/network_screen_browsertest.cc
@@ -57,11 +57,6 @@
 class NetworkScreenTest : public OobeBaseTest {
  public:
   NetworkScreenTest() {
-    feature_list_.InitWithFeatures(
-        {
-            features::kEnableOobeNetworkScreenSkip,
-        },
-        {});
     needs_network_screen_skip_check_ = true;
   }
 
diff --git a/chrome/browser/ash/login/screens/welcome_screen_browsertest.cc b/chrome/browser/ash/login/screens/welcome_screen_browsertest.cc
index d013647..8ecb236 100644
--- a/chrome/browser/ash/login/screens/welcome_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/welcome_screen_browsertest.cc
@@ -1117,7 +1117,8 @@
   test::ExecuteOobeJS(kSetAvailableVoices);
   test::SpeechMonitor monitor;
   GiveChromeVoxHintForTesting();
-  monitor.ExpectSpeechPatternWithLocale("*", "fr");
+  monitor.ExpectSpeech(
+      test::SpeechMonitor::Expectation("*").AsPattern().WithLocale("fr"));
   monitor.Replay();
   WaitForSpokenSuccessMetric();
 }
@@ -1143,7 +1144,8 @@
   test::OobeJS().ExpectAttributeEQ("open", kChromeVoxHintDialog, false);
   GiveChromeVoxHintForTesting();
   // Expect speech in English, even though the system locale is French.
-  monitor.ExpectSpeechPatternWithLocale("*", "en-US");
+  monitor.ExpectSpeech(
+      test::SpeechMonitor::Expectation("*").AsPattern().WithLocale("en-US"));
   monitor.Replay();
   WaitForSpokenSuccessMetric();
 }
diff --git a/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.cc b/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.cc
index 88c30efe..c1c84f4 100644
--- a/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.cc
+++ b/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.cc
@@ -122,7 +122,8 @@
 
 MultiDeviceSetupServiceFactory::~MultiDeviceSetupServiceFactory() = default;
 
-KeyedService* MultiDeviceSetupServiceFactory::BuildServiceInstanceFor(
+std::unique_ptr<KeyedService>
+MultiDeviceSetupServiceFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
   if (!multidevice_setup::AreAnyMultiDeviceFeaturesAllowed(
           Profile::FromBrowserContext(context)->GetPrefs())) {
@@ -132,7 +133,7 @@
     return nullptr;
   }
 
-  return new MultiDeviceSetupServiceHolder(context);
+  return std::make_unique<MultiDeviceSetupServiceHolder>(context);
 }
 
 }  // namespace multidevice_setup
diff --git a/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.h b/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.h
index d42f768c..af08a3d7 100644
--- a/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.h
+++ b/chrome/browser/ash/multidevice_setup/multidevice_setup_service_factory.h
@@ -32,7 +32,7 @@
   ~MultiDeviceSetupServiceFactory() override;
 
   // BrowserContextKeyedServiceFactory implementation:
-  KeyedService* BuildServiceInstanceFor(
+  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
       content::BrowserContext* context) const override;
 };
 
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 5bd7b6d..964f8b8 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/translate/translate_test_utils.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/translate/translate_bubble_model.h"
@@ -2695,6 +2696,11 @@
       fenced_frame_test_helper_;
 };
 
+INSTANTIATE_TEST_SUITE_P(AutofillInteractiveTest,
+                         AutofillInteractiveFencedFrameTest,
+                         ::testing::Values(FrameType::kFencedFrame,
+                                           FrameType::kIFrame));
+
 // TODO(https://crbug.com/1175735): Check back if flakiness is fixed now.
 IN_PROC_BROWSER_TEST_P(AutofillInteractiveFencedFrameTest,
                        SimpleCrossSiteFill) {
@@ -2751,15 +2757,17 @@
                             .execution_target = cross_frame_host}));
 }
 
+// Tests that deleting the subframe that has opened the Autofill popup closes
+// the popup.
 // TODO(https://crbug.com/1175735): Check back if flakiness is fixed now.
 IN_PROC_BROWSER_TEST_P(AutofillInteractiveFencedFrameTest,
-                       DeletingFrameUnderSuggestion) {
+                       DeletingFrameClosesPopup) {
   CreateTestProfile();
 
   // Main frame is on a.com, fenced frame is on b.com.
-  GURL url =
-      https_server()->GetURL("a.com", "/autofill/cross_origin_iframe.html");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(),
+      https_server()->GetURL("a.com", "/autofill/cross_origin_iframe.html")));
 
   content::RenderFrameHost* cross_frame_host =
       LoadSubFrame("/autofill/autofill_test_form.html");
@@ -2779,8 +2787,8 @@
   // Let |test_delegate()| also observe autofill events in the iframe.
   test_delegate()->Observe(*cross_driver->autofill_manager());
 
-  // Focus the form in the iframe/fenced frame and simulate choosing a
-  // suggestion via keyboard.
+  // Open the Autofill popup but do not accept the suggestion yet. Deleting the
+  // subframe should close the popup.
   ASSERT_TRUE(
       AutofillFlow(GetElementById("NAME_FIRST"), this,
                    {.do_accept = false, .execution_target = cross_frame_host}));
@@ -2793,14 +2801,27 @@
       GetParam() == FrameType::kIFrame ? "crossFrame" : "crossFF");
   ASSERT_TRUE(content::ExecJs(GetWebContents(), script_delete));
 
-  // The popup should have disappeared with the iframe.
   EXPECT_FALSE(IsPopupShown());
 }
 
-INSTANTIATE_TEST_SUITE_P(AutofillInteractiveTest,
-                         AutofillInteractiveFencedFrameTest,
-                         ::testing::Values(FrameType::kFencedFrame,
-                                           FrameType::kIFrame));
+// Tests that when changing the tab while the popup is open, closes the popup.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ChangingTabClosesPopup) {
+  CreateTestProfile();
+  SetTestUrlResponse(kTestShippingFormString);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestUrl()));
+  // Open the Autofill popup but do not accept the suggestion yet. Selecting
+  // another tab should close the popup.
+  content::WebContents* original_tab = GetWebContents();
+  ASSERT_TRUE(
+      AutofillFlow(GetElementById("firstname"), this, {.do_accept = false}));
+  EXPECT_TRUE(IsPopupShown());
+  AddBlankTabAndShow(browser());
+  ASSERT_NE(original_tab, GetWebContents());
+  chrome::CloseWebContents(browser(), GetWebContents(),
+                           /*add_to_history=*/false);
+  ASSERT_EQ(original_tab, GetWebContents());
+  EXPECT_FALSE(IsPopupShown());
+}
 
 // Test fixture for refill behavior.
 //
diff --git a/chrome/browser/autofill/content_autofill_driver_browsertest.cc b/chrome/browser/autofill/content_autofill_driver_browsertest.cc
index 6107951b..e38339f 100644
--- a/chrome/browser/autofill/content_autofill_driver_browsertest.cc
+++ b/chrome/browser/autofill/content_autofill_driver_browsertest.cc
@@ -145,19 +145,6 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest,
-                       SwitchTabAndHideAutofillPopup) {
-  EXPECT_CALL(autofill_client(),
-              HideAutofillPopup(PopupHidingReason::kTabGone));
-
-  scoped_refptr<content::MessageLoopRunner> runner =
-      new content::MessageLoopRunner;
-  web_contents_hidden_callback_ = runner->QuitClosure();
-  chrome::AddSelectedTabWithURL(browser(), GURL(url::kAboutBlankURL),
-                                ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
-  runner->Run();
-}
-
-IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest,
                        SameDocumentNavigationHideAutofillPopup) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
       browser(),
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.cc b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.cc
index 289127c..41cf3ca 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.cc
@@ -49,10 +49,20 @@
 }
 
 EventManager::EventManager(content::BrowserContext* context)
-    : event_router_(context), browser_context_(context) {}
+    : event_router_(context), browser_context_(context) {
+  extensions::ExtensionRegistry::Get(context)->AddObserver(this);
+}
 
 EventManager::~EventManager() = default;
 
+void EventManager::OnExtensionUnloaded(
+    content::BrowserContext* browser_context,
+    const extensions::Extension* extension,
+    extensions::UnloadedExtensionReason reason) {
+  app_ui_observers_.erase(extension->id());
+  event_router_.ResetReceiversForExtension(extension->id());
+}
+
 EventManager::RegisterEventResult EventManager::RegisterExtensionForEvent(
     extensions::ExtensionId extension_id,
     crosapi::TelemetryEventCategoryEnum category) {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.h b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.h
index b7cdbdc..2cf868fc 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.h
+++ b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.h
@@ -15,6 +15,10 @@
 #include "chromeos/crosapi/mojom/telemetry_extension_exception.mojom.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/browser/extension_registry_factory.h"
+#include "extensions/browser/extension_registry_observer.h"
+#include "extensions/browser/unloaded_extension_reason.h"
+#include "extensions/common/extension.h"
 #include "extensions/common/extension_id.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -22,7 +26,8 @@
 
 class AppUiObserver;
 
-class EventManager : public extensions::BrowserContextKeyedAPI {
+class EventManager : public extensions::BrowserContextKeyedAPI,
+                     public extensions::ExtensionRegistryObserver {
  public:
   enum RegisterEventResult {
     kSuccess,
@@ -43,6 +48,11 @@
 
   ~EventManager() override;
 
+  // `ExtensionRegistryObserver`:
+  void OnExtensionUnloaded(content::BrowserContext* browser_context,
+                           const extensions::Extension* extension,
+                           extensions::UnloadedExtensionReason reason) override;
+
   // Registers an extension for a certain event category. This results in a
   // subscription with cros_healthd which is cut when either:
   // 1. The app UI associated with the extension is closed.
@@ -88,4 +98,17 @@
 
 }  // namespace chromeos
 
+namespace extensions {
+
+template <>
+struct BrowserContextFactoryDependencies<chromeos::EventManager> {
+  static void DeclareFactoryDependencies(
+      extensions::BrowserContextKeyedAPIFactory<chromeos::EventManager>*
+          factory) {
+    factory->DependsOn(ExtensionRegistryFactory::GetInstance());
+  }
+};
+
+}  // namespace extensions
+
 #endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_TELEMETRY_API_EVENTS_EVENT_MANAGER_H_
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
index 913785c8..b3435ee2 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/containers/flat_map.h"
+#include "base/memory/scoped_refptr.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/events/event_manager.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/events/event_router.h"
@@ -19,6 +20,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/ssl_status.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_id.h"
 #include "net/base/net_errors.h"
@@ -26,6 +28,7 @@
 #include "net/cert/x509_certificate.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/test/scoped_feature_list.h"
@@ -85,8 +88,9 @@
     ssl.cert_status = cert_status;
   }
 
-  void CreateExtension(const std::string& extension_id,
-                       const std::vector<std::string> external_connectables) {
+  scoped_refptr<const extensions::Extension> CreateExtension(
+      const std::string& extension_id,
+      const std::vector<std::string> external_connectables) {
     base::Value::List matches;
     for (const auto& match : external_connectables) {
       matches.Append(match);
@@ -102,6 +106,8 @@
             .SetLocation(extensions::mojom::ManifestLocation::kInternal)
             .Build();
     extensions::ExtensionRegistry::Get(profile())->AddEnabled(extension);
+
+    return extension;
   }
 
   EventManager* event_manager() { return EventManager::Get(profile()); }
@@ -322,6 +328,29 @@
   EXPECT_FALSE(event_router().IsExtensionObserving(extension_id_2));
 }
 
+TEST_F(TelemetryExtensionEventManagerTest, RemoveExtensionCutsConnection) {
+  const std::string extension_id = "gogonhoemckpdpadfnjnpgbjpbjnodgc";
+  auto extension =
+      CreateExtension(extension_id, {"*://googlechromelabs.github.io/*"});
+
+  OpenAppUiUrlAndSetCertificateWithStatus(
+      GURL("https://googlechromelabs.github.io/"),
+      /*cert_status=*/net::OK);
+  EXPECT_EQ(EventManager::kSuccess,
+            event_manager()->RegisterExtensionForEvent(
+                extension_id, crosapi::TelemetryEventCategoryEnum::kAudioJack));
+  EXPECT_TRUE(app_ui_observers().contains(extension_id));
+  EXPECT_TRUE(event_router().IsExtensionObserving(extension_id));
+
+  EXPECT_TRUE(extensions::ExtensionRegistry::Get(profile())->RemoveEnabled(
+      extension_id));
+  extensions::ExtensionRegistry::Get(profile())->TriggerOnUnloaded(
+      extension.get(), extensions::UnloadedExtensionReason::TERMINATE);
+
+  EXPECT_FALSE(app_ui_observers().contains(extension_id));
+  EXPECT_FALSE(event_router().IsExtensionObserving(extension_id));
+}
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(TelemetryExtensionEventManagerTest, RegisterEventIWASuccess) {
   base::test::ScopedFeatureList feature_list;
diff --git a/chrome/browser/consent_auditor/DIR_METADATA b/chrome/browser/consent_auditor/DIR_METADATA
index c75f2f8..4a58e65 100644
--- a/chrome/browser/consent_auditor/DIR_METADATA
+++ b/chrome/browser/consent_auditor/DIR_METADATA
@@ -1 +1 @@
-mixins: "//components/consent_auditor/COMMON_METADATA"
+mixins: "//components/sync/COMMON_METADATA"
diff --git a/chrome/browser/content_settings/content_settings_manager_delegate.cc b/chrome/browser/content_settings/content_settings_manager_delegate.cc
index 2b2283f..72a153e 100644
--- a/chrome/browser/content_settings/content_settings_manager_delegate.cc
+++ b/chrome/browser/content_settings/content_settings_manager_delegate.cc
@@ -32,9 +32,13 @@
     bool allowed) {
   auto* rfh =
       content::RenderFrameHost::FromID(render_process_id, render_frame_id);
-  content_settings::PageSpecificContentSettings::StorageAccessed(
-      content_settings::mojom::ContentSettingsManager::StorageType::FILE_SYSTEM,
-      render_process_id, render_frame_id, rfh->GetStorageKey(), !allowed);
+  if (rfh) {
+    content_settings::PageSpecificContentSettings::StorageAccessed(
+        content_settings::mojom::ContentSettingsManager::StorageType::
+            FILE_SYSTEM,
+        render_process_id, render_frame_id, rfh->GetStorageKey(), !allowed);
+  }
+
   std::move(callback).Run(allowed);
 }
 
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl.cc b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
index ddef8d9..c28ec9a3 100644
--- a/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
@@ -42,8 +42,7 @@
 constexpr auto kAddressFieldTypes =
     base::MakeFixedFlatSet<autofill::FieldTypeGroup>(
         {autofill::FieldTypeGroup::kName, autofill::FieldTypeGroup::kEmail,
-         autofill::FieldTypeGroup::kPhoneHome,
-         autofill::FieldTypeGroup::kAddressHome});
+         autofill::FieldTypeGroup::kPhone, autofill::FieldTypeGroup::kAddress});
 
 bool IsVisibleTextField(const autofill::AutofillField& field) {
   return field.IsFocusable() && field.IsTextInputElement();
@@ -66,8 +65,7 @@
 
 bool IsNameOrAddress(autofill::FieldTypeGroup type_group) {
   return type_group == autofill::FieldTypeGroup::kName ||
-         type_group == autofill::FieldTypeGroup::kAddressHome ||
-         type_group == autofill::FieldTypeGroup::kAddressBilling;
+         type_group == autofill::FieldTypeGroup::kAddress;
 }
 
 // Returns `true` if `form` is considered an address form containing only an
@@ -414,8 +412,7 @@
                                             autofill::FormType::kAddressForm)] =
             FillingState::kFilling;
         static_cast<autofill::BrowserAutofillManager*>(autofill_manager_.get())
-            ->SetFastCheckoutRunId(autofill::FieldTypeGroup::kAddressHome,
-                                   run_id_);
+            ->SetFastCheckoutRunId(autofill::FieldTypeGroup::kAddress, run_id_);
         autofill_manager_->FillProfileForm(
             *autofill_profile, form->ToFormData(), *field,
             autofill::AutofillTriggerDetails(
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc b/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
index 9b025d893..079a765 100644
--- a/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl_unittest.cc
@@ -799,7 +799,7 @@
               {.trigger_source =
                    autofill::AutofillTriggerSource::kFastCheckout})));
   EXPECT_CALL(*autofill_manager(),
-              SetFastCheckoutRunId(autofill::FieldTypeGroup::kAddressHome,
+              SetFastCheckoutRunId(autofill::FieldTypeGroup::kAddress,
                                    fast_checkout_client()->run_id_));
   fast_checkout_client()->OnAfterLoadedServerPredictions(*autofill_manager());
   EXPECT_THAT(
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 22420506..bd5aeee 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -339,6 +339,7 @@
     &kWebOtpCrossDeviceSimpleString,
     &content_creation::kWebNotesStylizeEnabled,
     &kWebApkAllowIconUpdate,
+    &kWebApkBackupAndRestoreBackend,
     &kWebApkInstallService,
     &kWebApkTrampolineOnInitialIntent,
     &features::kDnsOverHttps,
@@ -1158,6 +1159,10 @@
              "WebApkAllowIconUpdate",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kWebApkBackupAndRestoreBackend,
+             "WebApkBackupAndRestoreBackend",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Enables the Chrome Android WebAPK-install service.
 BASE_FEATURE(kWebApkInstallService,
              "WebApkInstallService",
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 3a2c7c16..af1bec8 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -208,6 +208,7 @@
 BASE_DECLARE_FEATURE(kVoiceButtonInTopToolbar);
 BASE_DECLARE_FEATURE(kWebOtpCrossDeviceSimpleString);
 BASE_DECLARE_FEATURE(kWebApkAllowIconUpdate);
+BASE_DECLARE_FEATURE(kWebApkBackupAndRestoreBackend);
 BASE_DECLARE_FEATURE(kWebApkInstallService);
 BASE_DECLARE_FEATURE(kWebApkTrampolineOnInitialIntent);
 
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 a7d799f..6617ece7 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
@@ -487,6 +487,7 @@
     public static final String VOICE_SEARCH_AUDIO_CAPTURE_POLICY = "VoiceSearchAudioCapturePolicy";
     public static final String WEBNOTES_STYLIZE = "WebNotesStylize";
     public static final String WEB_APK_ALLOW_ICON_UPDATA = "WebApkAllowIconUpdate";
+    public static final String WEB_APK_BACKUP_AND_RESTORE_BACKEND = "WebApkBackupAndRestoreBackend";
     public static final String WEB_APK_INSTALL_SERVICE = "WebApkInstallService";
     public static final String WEB_APK_TRAMPOLINE_ON_INITIAL_INTENT =
             "WebApkTrampolineOnInitialIntent";
diff --git a/chrome/browser/notifications/persistent_notification_handler.cc b/chrome/browser/notifications/persistent_notification_handler.cc
index 147171a..476a1cea 100644
--- a/chrome/browser/notifications/persistent_notification_handler.cc
+++ b/chrome/browser/notifications/persistent_notification_handler.cc
@@ -99,7 +99,6 @@
     const absl::optional<std::u16string>& reply,
     base::OnceClosure completed_closure) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(origin.is_valid());
 
   NotificationMetricsLogger* metrics_logger =
       NotificationMetricsLoggerFactory::GetForBrowserContext(profile);
@@ -129,18 +128,22 @@
   else
     metrics_logger->LogPersistentNotificationClick();
 
-  // Notification clicks are considered a form of engagement with the |origin|,
-  // thus we log the interaction with the Site Engagement service.
-  site_engagement::SiteEngagementService::Get(profile)
-      ->HandleNotificationInteraction(origin);
+  // TODO(crbug.com/1477232)
+  if (!origin.is_empty()) {
+    // Notification clicks are considered a form of engagement with the
+    // |origin|, thus we log the interaction with the Site Engagement service.
+    site_engagement::SiteEngagementService::Get(profile)
+        ->HandleNotificationInteraction(origin);
 
-  if (base::FeatureList::IsEnabled(
-          permissions::features::kNotificationInteractionHistory)) {
-    auto* service =
-        NotificationsEngagementServiceFactory::GetForProfile(profile);
-    // This service might be missing for incognito profiles and in tests.
-    if (service)
-      service->RecordNotificationInteraction(origin);
+    if (base::FeatureList::IsEnabled(
+            permissions::features::kNotificationInteractionHistory)) {
+      auto* service =
+          NotificationsEngagementServiceFactory::GetForProfile(profile);
+      // This service might be missing for incognito profiles and in tests.
+      if (service) {
+        service->RecordNotificationInteraction(origin);
+      }
+    }
   }
 
   content::NotificationEventDispatcher::GetInstance()
diff --git a/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.cc b/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.cc
index f4031ca..14876826 100644
--- a/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.cc
+++ b/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.cc
@@ -19,6 +19,7 @@
   // Create the content setting UI.
   SetLayoutManager(std::make_unique<views::FillLayout>());
   SetPaintToLayer(ui::LAYER_NOT_DRAWN);
+  SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
 
   // Add the semi-opaque background layer.
   auto* background =
@@ -73,3 +74,35 @@
   SetVisible(false);
   std::move(result_cb_).Run(result);
 }
+
+bool AutoPipSettingOverlayView::DoesIntersectRect(const views::View* target,
+                                                  const gfx::Rect& rect) const {
+  DCHECK_EQ(target, this);
+  if (allow_button_->HitTestRect(
+          ConvertRectToTarget(target, allow_button_, rect))) {
+    return true;
+  }
+
+  if (block_button_->HitTestRect(
+          ConvertRectToTarget(this, block_button_, rect))) {
+    return true;
+  }
+
+  return false;
+}
+
+views::View* AutoPipSettingOverlayView::TargetForRect(views::View* root,
+                                                      const gfx::Rect& rect) {
+  // The background does not consume events.
+  if (allow_button_->HitTestRect(
+          ConvertRectToTarget(root, allow_button_, rect))) {
+    return allow_button_;
+  }
+
+  if (block_button_->HitTestRect(
+          ConvertRectToTarget(root, block_button_, rect))) {
+    return block_button_;
+  }
+
+  return nullptr;
+}
diff --git a/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.h b/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.h
index b3bdde9..f3a9d4ff 100644
--- a/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.h
+++ b/chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.h
@@ -7,10 +7,12 @@
 
 #include "base/functional/callback.h"
 #include "ui/views/view.h"
+#include "ui/views/view_targeter_delegate.h"
 
 // Creates and manages the content setting overlay for autopip.  This is used
 // both for video-only and document pip on desktop.  It is not used on Android.
-class AutoPipSettingOverlayView : public views::View {
+class AutoPipSettingOverlayView : public views::View,
+                                  public views::ViewTargeterDelegate {
  public:
   enum class UiResult {
     // User selected 'Allow'.
@@ -31,6 +33,11 @@
   AutoPipSettingOverlayView(const AutoPipSettingOverlayView&) = delete;
   AutoPipSettingOverlayView(AutoPipSettingOverlayView&&) = delete;
 
+  // views::ViewTargeterDelegate
+  bool DoesIntersectRect(const views::View* target,
+                         const gfx::Rect& rect) const override;
+  views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;
+
   const views::View* get_block_button_for_testing() const {
     return block_button_;
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
index 1c17597..f35637e7 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -78,6 +78,7 @@
   "background/editing/editing.js",
   "background/editing/intent_handler.js",
   "background/editing/text_edit_handler.js",
+  "background/editing/typing_echo.js",
   "background/es6_loader.js",
   "background/event/base_automation_handler.js",
   "background/event/desktop_automation_handler.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
index 49752e7..080d133 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -38,7 +38,7 @@
 import {ClipboardHandler} from './clipboard_handler.js';
 import {Color} from './color.js';
 import {CommandHandlerInterface} from './command_handler_interface.js';
-import {TypingEcho} from './editing/editable_text_base.js';
+import {TypingEcho} from './editing/typing_echo.js';
 import {DesktopAutomationInterface} from './event/desktop_automation_interface.js';
 import {EventSource} from './event_source.js';
 import {GestureInterface} from './gesture_interface.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base.js
index 79280610..5a5169f 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base.js
@@ -19,6 +19,8 @@
 import {ChromeVoxState} from '../chromevox_state.js';
 import {TtsInterface} from '../tts_interface.js';
 
+import {TypingEcho} from './typing_echo.js';
+
 /**
  * A class containing the information needed to speak
  * a text change event to the user.
@@ -55,46 +57,6 @@
   }
 }
 
-
-/**
- * A list of typing echo options.
- * This defines the way typed characters get spoken.
- * CHARACTER: echoes typed characters.
- * WORD: echoes a word once a breaking character is typed (i.e. spacebar).
- * CHARACTER_AND_WORD: combines CHARACTER and WORD behavior.
- * NONE: speaks nothing when typing.
- * COUNT: The number of possible echo levels.
- * @enum
- */
-export const TypingEcho = {
-  CHARACTER: 0,
-  WORD: 1,
-  CHARACTER_AND_WORD: 2,
-  NONE: 3,
-  COUNT: 4,
-};
-
-
-/**
- * @param {number} cur Current typing echo.
- * @return {number} Next typing echo.
- */
-TypingEcho.cycle = function(cur) {
-  return (cur + 1) % TypingEcho.COUNT;
-};
-
-
-/**
- * Return if characters should be spoken given the typing echo option.
- * @param {number} typingEcho Typing echo option.
- * @return {boolean} Whether the character should be spoken.
- */
-TypingEcho.shouldSpeakChar = function(typingEcho) {
-  return typingEcho === TypingEcho.CHARACTER_AND_WORD ||
-      typingEcho === TypingEcho.CHARACTER;
-};
-
-
 /**
  * A class representing an abstracted editable text control.
  */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base_test.js
index f478443..2ec6d38 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_text_base_test.js
@@ -98,8 +98,10 @@
       importModule(
           'ChromeVoxState', '/chromevox/background/chromevox_state.js'),
       importModule(
-          ['ChromeVoxEditableTextBase', 'TextChangedEvent', 'TypingEcho'],
+          ['ChromeVoxEditableTextBase', 'TextChangedEvent'],
           '/chromevox/background/editing/editable_text_base.js'),
+      importModule(
+          'TypingEcho', '/chromevox/background/editing/typing_echo.js'),
       importModule('TtsInterface', '/chromevox/common/tts_interface.js'),
       importModule('LocalStorage', '/common/local_storage.js'),
     ]);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/typing_echo.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/typing_echo.js
new file mode 100644
index 0000000..144d231
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/typing_echo.js
@@ -0,0 +1,41 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * A list of typing echo options.
+ * This defines the way typed characters get spoken.
+ * CHARACTER: echoes typed characters.
+ * WORD: echoes a word once a breaking character is typed (i.e. spacebar).
+ * CHARACTER_AND_WORD: combines CHARACTER and WORD behavior.
+ * NONE: speaks nothing when typing.
+ * COUNT: The number of possible echo levels.
+ * @enum
+ */
+export const TypingEcho = {
+  CHARACTER: 0,
+  WORD: 1,
+  CHARACTER_AND_WORD: 2,
+  NONE: 3,
+  COUNT: 4,
+};
+
+
+/**
+ * @param {number} cur Current typing echo.
+ * @return {number} Next typing echo.
+ */
+TypingEcho.cycle = function(cur) {
+  return (cur + 1) % TypingEcho.COUNT;
+};
+
+
+/**
+ * Return if characters should be spoken given the typing echo option.
+ * @param {number} typingEcho Typing echo option.
+ * @return {boolean} Whether the character should be spoken.
+ */
+TypingEcho.shouldSpeakChar = function(typingEcho) {
+  return typingEcho === TypingEcho.CHARACTER_AND_WORD ||
+      typingEcho === TypingEcho.CHARACTER;
+};
diff --git a/chrome/browser/resources/chromeos/login/components/web_view_loader.js b/chrome/browser/resources/chromeos/login/components/web_view_loader.js
index 6e7d554..878bc957 100644
--- a/chrome/browser/resources/chromeos/login/components/web_view_loader.js
+++ b/chrome/browser/resources/chromeos/login/components/web_view_loader.js
@@ -115,11 +115,6 @@
     if (clear_anchors) {
       // Add the CLEAR_ANCHORS_CONTENT_SCRIPT that will clear <a><\a>
       // (anchors) in order to prevent any navigation in the webview itself.
-      webview.addContentScripts([{
-        name: 'clearAnchors',
-        matches: ['<all_urls>'],
-        js: CLEAR_ANCHORS_CONTENT_SCRIPT,
-      }]);
       webview.addEventListener('contentload', () => {
         webview.executeScript(CLEAR_ANCHORS_CONTENT_SCRIPT, () => {
           if (chrome.runtime.lastError) {
@@ -132,7 +127,12 @@
     }
     if (inject_css) {
       webview.addEventListener('contentload', () => {
-        webview.insertCSS(WEB_VIEW_FONTS_CSS);
+        webview.insertCSS(WEB_VIEW_FONTS_CSS, () => {
+          if (chrome.runtime.lastError) {
+            console.warn(
+                'Failed to insertCSS: ' + chrome.runtime.lastError.message);
+          }
+        });
       });
     }
 
diff --git a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
index b04468d..3d43d91 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/consolidated_consent.js
@@ -91,7 +91,7 @@
  * @implements {MultiStepBehaviorInterface}
  */
 const ConsolidatedConsentScreenElementBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @polymer
@@ -406,6 +406,11 @@
     // Content.
     if (!this.isDemo_) {
       webview.executeScript({code: 'document.body.innerHTML;'}, (results) => {
+        if (chrome.runtime.lastError) {
+          console.warn(
+              'Failed to get consent contents: ' +
+              chrome.runtime.lastError.message);
+        }
         if (!results || results.length != 1 || typeof results[0] !== 'string') {
           return;
         }
@@ -415,8 +420,6 @@
 
     this.arcTosLoading_ = false;
     this.maybeSetLoadedStep_();
-    this.$.consolidatedConsentArcTosWebview.insertCSS(
-        {code: 'header{display:none !important}'});
   }
 
   onPrivacyPolicyContentLoad_() {
diff --git a/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js b/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js
index 0b01c3b..0d2e21cf 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js
@@ -58,7 +58,7 @@
  * @implements {MultiStepBehaviorInterface}
  */
 const FingerprintSetupBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @typedef {{
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
index 1d01a6b8..d78a485d7 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
@@ -59,7 +59,7 @@
  * @implements {MultiStepBehaviorInterface}
  */
 const GuestTosScreenElementBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @polymer
diff --git a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
index 362011da..7b08c59 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/offline_ad_login.js
@@ -77,7 +77,7 @@
  * @implements {OobeI18nBehaviorInterface}
  */
 const OfflineAdLoginBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @typedef {{
diff --git a/chrome/browser/resources/chromeos/login/screens/common/sync_consent.js b/chrome/browser/resources/chromeos/login/screens/common/sync_consent.js
index 2a6a4b6..1c943b23 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/sync_consent.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/sync_consent.js
@@ -74,7 +74,7 @@
  * @implements {MultiStepBehaviorInterface}
  */
 const SyncConsentScreenElementBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @typedef {{
diff --git a/chrome/browser/resources/chromeos/login/screens/common/tpm_error.js b/chrome/browser/resources/chromeos/login/screens/common/tpm_error.js
index 1f935f2..3a5ab7d7 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/tpm_error.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/tpm_error.js
@@ -39,7 +39,7 @@
  * @implements {MultiStepBehaviorInterface}
  */
 const TPMErrorMessageElementBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @typedef {{
diff --git a/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.html b/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.html
index f7c72519..f91e6121 100644
--- a/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.html
+++ b/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.html
@@ -89,7 +89,9 @@
   </div>
 </oobe-adaptive-dialog>
 
-<oobe-adaptive-dialog role="dialog" for-step="forgot" id="forgotPassword">
+<oobe-adaptive-dialog role="dialog" for-step="forgot" id="forgotPassword"
+    aria-label$="[[getForgotPasswordLabel_(locale,
+        isCryptohomeRecoveryUIFlowEnabled_)]]">
   <iron-icon slot="icon" icon="oobe-32:warning"></iron-icon>
   <template is="dom-if" if="[[!isCryptohomeRecoveryUIFlowEnabled_]]">
     <h1 slot="title">[[email]]</h1>
@@ -118,7 +120,8 @@
   </div>
   <div slot="bottom-buttons">
     <oobe-text-button id="cancelForgot" on-click="onCancel_"
-        text-key="cancel" hidden="[[!isCryptohomeRecoveryUIFlowEnabled_]]">
+        class="focus-on-show" text-key="cancel"
+        hidden="[[!isCryptohomeRecoveryUIFlowEnabled_]]">
     </oobe-text-button>
     <oobe-text-button id="tryAgain" on-click="onTryAgainClicked_"
         class="focus-on-show" text-key="passwordChangedTryAgain"
diff --git a/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.js b/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.js
index b818e260..b08a6e2f9 100644
--- a/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.js
+++ b/chrome/browser/resources/chromeos/login/screens/login/gaia_password_changed.js
@@ -177,6 +177,18 @@
   }
 
   /**
+   * Returns the label for the forgot password dialog.
+   * @param {string} locale The i18n locale.
+   * @returns {string} The translated label text.
+   */
+  getForgotPasswordLabel_(locale) {
+    if (this.isCryptohomeRecoveryUIFlowEnabled_) {
+      return this.i18nDynamic(locale, 'dataLossWarningTitle');
+    }
+    return '';
+  }
+
+  /**
    * Returns the subtitle message for the data loss warning screen.
    * @param {string} locale The i18n locale.
    * @param {string} email The email address that the user is trying to recover.
diff --git a/chrome/browser/resources/chromeos/login/screens/login/update_required_card.js b/chrome/browser/resources/chromeos/login/screens/login/update_required_card.js
index 6e4b33e..dbf1707 100644
--- a/chrome/browser/resources/chromeos/login/screens/login/update_required_card.js
+++ b/chrome/browser/resources/chromeos/login/screens/login/update_required_card.js
@@ -49,7 +49,7 @@
  * @implements {OobeI18nBehaviorInterface}
  */
 const UpdateRequiredBase = mixinBehaviors(
-    [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement);
+    [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
 
 /**
  * @typedef {{
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_browser_proxy.ts b/chrome/browser/resources/settings/safety_hub/safety_hub_browser_proxy.ts
index e17c3a2..5cfbf1b 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_browser_proxy.ts
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_browser_proxy.ts
@@ -111,6 +111,15 @@
 
   /** Resets the notification permission for the origins. */
   resetNotificationPermissionForOrigins(origin: string[]): void;
+
+  /** Gets data for the password top card. */
+  getPasswordCardData(): Promise<CardInfo>;
+
+  /** Gets data for the Safe Browsing top card. */
+  getSafeBrowsingCardData(): Promise<CardInfo>;
+
+  /** Gets data for the version top card. */
+  getVersionCardData(): Promise<CardInfo>;
 }
 
 export class SafetyHubBrowserProxyImpl implements SafetyHubBrowserProxy {
@@ -163,6 +172,33 @@
     chrome.send('resetNotificationPermissionForOrigins', [origins]);
   }
 
+  getPasswordCardData() {
+    // TODO(crbug.com/1443466): Replace dummy response with handler response.
+    return Promise.resolve({
+      header: 'dummy header',
+      subheader: 'dummy subheader',
+      state: CardState.SAFE,
+    });
+  }
+
+  getSafeBrowsingCardData() {
+    // TODO(crbug.com/1443466): Replace dummy response with handler response.
+    return Promise.resolve({
+      header: 'dummy header',
+      subheader: 'dummy subheader',
+      state: CardState.SAFE,
+    });
+  }
+
+  getVersionCardData() {
+    // TODO(crbug.com/1443466): Replace dummy response with handler response.
+    return Promise.resolve({
+      header: 'dummy header',
+      subheader: 'dummy subheader',
+      state: CardState.SAFE,
+    });
+  }
+
   static getInstance(): SafetyHubBrowserProxy {
     return instance || (instance = new SafetyHubBrowserProxyImpl());
   }
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts b/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts
index 83b5585e..9c229c7b9 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts
@@ -19,7 +19,7 @@
 import {routes} from '../route.js';
 import {Router} from '../router.js';
 
-import {CardInfo, CardState, SafetyHubBrowserProxyImpl, SafetyHubEvent, UnusedSitePermissions} from './safety_hub_browser_proxy.js';
+import {CardInfo, SafetyHubBrowserProxy, SafetyHubBrowserProxyImpl, SafetyHubEvent, UnusedSitePermissions} from './safety_hub_browser_proxy.js';
 import {getTemplate} from './safety_hub_page.html.js';
 
 export interface SettingsSafetyHubPageElement {
@@ -73,6 +73,8 @@
   private safeBrowsingCardData_: CardInfo;
   private showUnusedSitePermissions_: boolean;
   private showNoRecommendationsState_: boolean;
+  private browserProxy_: SafetyHubBrowserProxy =
+      SafetyHubBrowserProxyImpl.getInstance();
 
   override connectedCallback() {
     super.connectedCallback();
@@ -82,24 +84,17 @@
   }
 
   private initializeCards_() {
-    // TODO(crbug.com/1443466): Replace dummy values with the real values.
-    const dummyText = this.i18n('privacyPageTitle');
-    this.passwordCardData_ = {
-      header: dummyText,
-      subheader: dummyText,
-      state: CardState.INFO,
-    };
-    this.versionCardData_ = {
-      header: dummyText,
-      subheader: dummyText,
-      state: CardState.INFO,
-    };
+    this.browserProxy_.getPasswordCardData().then((data: CardInfo) => {
+      this.passwordCardData_ = data;
+    });
 
-    this.safeBrowsingCardData_ = {
-      header: dummyText,
-      subheader: dummyText,
-      state: CardState.INFO,
-    };
+    this.browserProxy_.getSafeBrowsingCardData().then((data: CardInfo) => {
+      this.safeBrowsingCardData_ = data;
+    });
+
+    this.browserProxy_.getVersionCardData().then((data: CardInfo) => {
+      this.versionCardData_ = data;
+    });
   }
 
   private initializeModules_() {
@@ -108,11 +103,9 @@
         (sites: UnusedSitePermissions[]) =>
             this.onUnusedSitePermissionListChanged_(sites));
 
-    SafetyHubBrowserProxyImpl.getInstance()
-        .getRevokedUnusedSitePermissionsList()
-        .then(
-            (sites: UnusedSitePermissions[]) =>
-                this.onUnusedSitePermissionListChanged_(sites));
+    this.browserProxy_.getRevokedUnusedSitePermissionsList().then(
+        (sites: UnusedSitePermissions[]) =>
+            this.onUnusedSitePermissionListChanged_(sites));
   }
 
   private onPasswordsClick_() {
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index 864c74ed..6fc7b4d 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -24,8 +24,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/path_service.h"
@@ -509,8 +507,6 @@
                       base::OnceClosure completion_callback);
 
  private:
-  static void RecordUnpinShortcutProcessError(bool error);
-
   UnpinShortcutsHelper(const std::vector<base::FilePath>& shortcuts,
                        base::OnceClosure completion_callback);
 
@@ -525,11 +521,6 @@
 };
 
 // static
-void UnpinShortcutsHelper::RecordUnpinShortcutProcessError(bool error) {
-  base::UmaHistogramBoolean("Windows.UnpinShortcut.ProcessError", error);
-}
-
-// static
 void UnpinShortcutsHelper::DoUnpin(const std::vector<base::FilePath>& shortcuts,
                                    base::OnceClosure completion_callback) {
   // Self-deleting when the ShellHandler completes.
@@ -554,7 +545,6 @@
 
 void UnpinShortcutsHelper::OnConnectionError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  RecordUnpinShortcutProcessError(true);
   std::move(completion_callback_).Run();
   delete this;
 }
@@ -562,7 +552,6 @@
 void UnpinShortcutsHelper::OnUnpinShortcutResult() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  RecordUnpinShortcutProcessError(false);
   std::move(completion_callback_).Run();
   delete this;
 }
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.cc
index 9cd2920..e24d1af 100644
--- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.cc
+++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.cc
@@ -5,15 +5,20 @@
 #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_factory.h"
 #include <memory>
 
+#include "base/feature_list.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
+#include "chrome/browser/signin/account_consistency_mode_manager.h"
+#include "chrome/browser/signin/account_consistency_mode_manager_factory.h"
 #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service.h"
 #include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.h"
 #include "chrome/browser/signin/bound_session_credentials/bound_session_params_storage.h"
 #include "chrome/browser/signin/bound_session_credentials/unexportable_key_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/signin_features.h"
 #include "components/pref_registry/pref_registry_syncable.h"
+#include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_switches.h"
 #include "content/public/browser/network_service_instance.h"
 
@@ -40,6 +45,7 @@
               .WithGuest(ProfileSelection::kOwnInstance)
               .Build()) {
   DependsOn(UnexportableKeyServiceFactory::GetInstance());
+  DependsOn(AccountConsistencyModeManagerFactory::GetInstance());
 }
 
 BoundSessionCookieRefreshServiceFactory::
@@ -48,7 +54,6 @@
 std::unique_ptr<KeyedService>
 BoundSessionCookieRefreshServiceFactory::BuildServiceInstanceForBrowserContext(
     content::BrowserContext* context) const {
-  // TODO(b/297000904): Enable on Dice profiles under a feature flag.
   if (!switches::IsBoundSessionCredentialsEnabled()) {
     return nullptr;
   }
@@ -61,6 +66,23 @@
     // A bound session requires a crypto provider.
     return nullptr;
   }
+
+  static BASE_FEATURE(kEnableBoundSessionCredentialsOnDiceProfiles,
+                      "EnableBoundSessionCredentialsOnDiceProfiles",
+                      base::FEATURE_DISABLED_BY_DEFAULT);
+  signin::AccountConsistencyMethod account_consistency_method =
+      AccountConsistencyModeManager::GetMethodForProfile(profile);
+  bool should_create_service =
+      account_consistency_method ==
+          signin::AccountConsistencyMethod::kDisabled ||
+      (account_consistency_method == signin::AccountConsistencyMethod::kDice &&
+       base::FeatureList::IsEnabled(
+           kEnableBoundSessionCredentialsOnDiceProfiles));
+
+  if (!should_create_service) {
+    return nullptr;
+  }
+
   std::unique_ptr<BoundSessionCookieRefreshService>
       bound_session_cookie_refresh_service =
           std::make_unique<BoundSessionCookieRefreshServiceImpl>(
diff --git a/chrome/browser/signin/primary_account_policy_manager.cc b/chrome/browser/signin/primary_account_policy_manager.cc
index e8d4422..6437029 100644
--- a/chrome/browser/signin/primary_account_policy_manager.cc
+++ b/chrome/browser/signin/primary_account_policy_manager.cc
@@ -236,11 +236,11 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // Disabling signin in chrome and 'RestrictSigninToPattern' policy
-  // are not supported on Lacros. This code should be unreachable. The main
-  // profile should never be deleted.
-  DCHECK(false)
-      << "Disabling signin in chrome and 'RestrictSigninToPattern' policy "
-         "are not supported on Lacros.";
+  // are not supported on Lacros. This code should be unreachable, except in
+  // Guest sessions. The main profile should never be deleted.
+  DCHECK(!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed) &&
+         profile->IsGuestSession())
+      << "On Lacros, signin may only be disallowed in the guest session.";
 #else
   if (ChromeSigninClientFactory::GetForProfile(profile)
           ->IsClearPrimaryAccountAllowed(identity_manager->HasPrimaryAccount(
diff --git a/chrome/browser/signin/signin_browser_test_base.h b/chrome/browser/signin/signin_browser_test_base.h
index 21c2f50..f2dd7f3 100644
--- a/chrome/browser/signin/signin_browser_test_base.h
+++ b/chrome/browser/signin/signin_browser_test_base.h
@@ -15,6 +15,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/trusted_vault/trusted_vault_histograms.h"
 #include "services/network/test/test_url_loader_factory.h"
 
 // Template for adding account management utilities to any test fixture which is
@@ -89,6 +90,10 @@
     DCHECK_EQ(GetProfile()->IsMainProfile(), use_main_profile_);
 #endif
 
+    if (GetProfile()->IsOffTheRecord()) {
+      return;
+    }
+
     identity_test_env_profile_adaptor_ =
         std::make_unique<IdentityTestEnvironmentProfileAdaptor>(GetProfile());
     identity_test_env()->SetTestURLLoaderFactory(&test_url_loader_factory_);
diff --git a/chrome/browser/ui/android/autofill/autofill_save_card_bottom_sheet_bridge.cc b/chrome/browser/ui/android/autofill/autofill_save_card_bottom_sheet_bridge.cc
index 6c3db4c0..9c5477e3 100644
--- a/chrome/browser/ui/android/autofill/autofill_save_card_bottom_sheet_bridge.cc
+++ b/chrome/browser/ui/android/autofill/autofill_save_card_bottom_sheet_bridge.cc
@@ -53,8 +53,13 @@
           window_android->GetJavaObject());
 }
 
-AutofillSaveCardBottomSheetBridge::~AutofillSaveCardBottomSheetBridge() =
-    default;
+AutofillSaveCardBottomSheetBridge::~AutofillSaveCardBottomSheetBridge() {
+  if (java_autofill_save_card_bottom_sheet_bridge_) {
+    Java_AutofillSaveCardBottomSheetBridge_destroy(
+        base::android::AttachCurrentThread(),
+        java_autofill_save_card_bottom_sheet_bridge_);
+  }
+}
 
 void AutofillSaveCardBottomSheetBridge::RequestShowContent(
     const AutofillSaveCardUiInfo& ui_info,
diff --git a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.cc b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.cc
index 8a9a1ff..10651102 100644
--- a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.cc
+++ b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.cc
@@ -4,19 +4,27 @@
 
 #include "chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h"
 
+#include <utility>
+
 #include "base/android/jni_android.h"
-#include "chrome/android/chrome_jni_headers/AutofillVCNEnrollBottomSheetBridge_jni.h"
+#include "base/android/jni_string.h"
+#include "chrome/android/chrome_jni_headers/AutofillVcnEnrollBottomSheetBridge_jni.h"
 #include "components/autofill/core/browser/payments/autofill_virtual_card_enrollment_infobar_delegate_mobile.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
 #include "content/public/browser/web_contents.h"
 
 namespace autofill {
 
+using base::android::ConvertUTF16ToJavaString;
+
 AutofillVCNEnrollBottomSheetBridge::AutofillVCNEnrollBottomSheetBridge()
-    : java_bridge_(Java_AutofillVCNEnrollBottomSheetBridge_Constructor(
+    : java_bridge_(Java_AutofillVcnEnrollBottomSheetBridge_Constructor(
           base::android::AttachCurrentThread())) {}
 
-AutofillVCNEnrollBottomSheetBridge::~AutofillVCNEnrollBottomSheetBridge() =
-    default;
+AutofillVCNEnrollBottomSheetBridge::~AutofillVCNEnrollBottomSheetBridge() {
+  Java_AutofillVcnEnrollBottomSheetBridge_hide(
+      base::android::AttachCurrentThread(), java_bridge_);
+}
 
 bool AutofillVCNEnrollBottomSheetBridge::RequestShowContent(
     content::WebContents* web_contents,
@@ -32,9 +40,30 @@
     return false;
   }
 
-  return Java_AutofillVCNEnrollBottomSheetBridge_requestShowContent(
-      base::android::AttachCurrentThread(), java_bridge_,
-      reinterpret_cast<jlong>(this), java_web_contents);
+  delegate_ = std::move(delegate);
+
+  JNIEnv* env = base::android::AttachCurrentThread();
+
+  return Java_AutofillVcnEnrollBottomSheetBridge_requestShowContent(
+      env, java_bridge_, reinterpret_cast<jlong>(this), java_web_contents,
+      ConvertUTF16ToJavaString(env, delegate_->GetMessageText()),
+      ConvertUTF16ToJavaString(
+          env, delegate_->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK)),
+      ConvertUTF16ToJavaString(
+          env,
+          delegate_->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL)));
+}
+
+void AutofillVCNEnrollBottomSheetBridge::OnAccept(JNIEnv* env) {
+  delegate_->Accept();
+}
+
+void AutofillVCNEnrollBottomSheetBridge::OnCancel(JNIEnv* env) {
+  delegate_->Cancel();
+}
+
+void AutofillVCNEnrollBottomSheetBridge::OnDismiss(JNIEnv* env) {
+  delegate_->InfoBarDismissed();
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h
index 8b419541..e414180 100644
--- a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h
+++ b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h
@@ -38,8 +38,13 @@
       std::unique_ptr<AutofillVirtualCardEnrollmentInfoBarDelegateMobile>
           delegate);
 
+  void OnAccept(JNIEnv* env);
+  void OnCancel(JNIEnv* env);
+  void OnDismiss(JNIEnv* env);
+
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_bridge_;
+  std::unique_ptr<AutofillVirtualCardEnrollmentInfoBarDelegateMobile> delegate_;
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge_unittest.cc b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge_unittest.cc
index 9498e296..29bc875 100644
--- a/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge_unittest.cc
+++ b/chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge_unittest.cc
@@ -4,14 +4,48 @@
 
 #include "chrome/browser/ui/android/autofill/autofill_vcn_enroll_bottom_sheet_bridge.h"
 
+#include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/payments/autofill_virtual_card_enrollment_infobar_delegate_mobile.h"
+#include "components/autofill/core/browser/payments/test_legal_message_line.h"
+#include "components/autofill/core/browser/payments/virtual_card_enrollment_flow.h"
+#include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_unittest_util.h"
 
 namespace autofill {
 namespace {
 
-using AutofillVCNEnrollBottomSheetBridgeTest = ChromeRenderViewHostTestHarness;
+class AutofillVCNEnrollBottomSheetBridgeTest
+    : public ChromeRenderViewHostTestHarness {
+ public:
+  AutofillVCNEnrollBottomSheetBridgeTest()
+      : card_art_image_(gfx::test::CreateImage().AsImageSkia()) {}
+  ~AutofillVCNEnrollBottomSheetBridgeTest() override = default;
+
+  VirtualCardEnrollBubbleControllerImpl* BuildController() {
+    VirtualCardEnrollBubbleControllerImpl* controller =
+        static_cast<VirtualCardEnrollBubbleControllerImpl*>(
+            VirtualCardEnrollBubbleControllerImpl::GetOrCreate(web_contents()));
+    VirtualCardEnrollmentFields virtual_card_enrollment_fields;
+    virtual_card_enrollment_fields.credit_card = test::GetFullServerCard();
+    virtual_card_enrollment_fields.card_art_image = &card_art_image_;
+    virtual_card_enrollment_fields.google_legal_message = {
+        TestLegalMessageLine("google_test_legal_message")};
+    virtual_card_enrollment_fields.issuer_legal_message = {
+        TestLegalMessageLine("issuer_test_legal_message")};
+    virtual_card_enrollment_fields.virtual_card_enrollment_source =
+        VirtualCardEnrollmentSource::kUpstream;
+    controller->SetFieldsForTesting(virtual_card_enrollment_fields);
+    return controller;
+  }
+
+ private:
+  gfx::ImageSkia card_art_image_;
+};
 
 TEST_F(AutofillVCNEnrollBottomSheetBridgeTest,
        RequestShowContentWithoutWebContents) {
@@ -25,13 +59,59 @@
 
 TEST_F(AutofillVCNEnrollBottomSheetBridgeTest,
        RequestShowContentWithWebContents) {
+  auto delegate =
+      std::make_unique<AutofillVirtualCardEnrollmentInfoBarDelegateMobile>(
+          BuildController());
   AutofillVCNEnrollBottomSheetBridge bridge;
 
   bool did_show =
-      bridge.RequestShowContent(web_contents(), /*delegate=*/nullptr);
+      bridge.RequestShowContent(web_contents(), std::move(delegate));
 
   EXPECT_FALSE(did_show);
 }
 
+class MockDelegate : public AutofillVirtualCardEnrollmentInfoBarDelegateMobile {
+ public:
+  explicit MockDelegate(VirtualCardEnrollBubbleControllerImpl* controller)
+      : AutofillVirtualCardEnrollmentInfoBarDelegateMobile(controller) {}
+  ~MockDelegate() override = default;
+  MOCK_METHOD(void, InfoBarDismissed, (), (override));
+  MOCK_METHOD(bool, Accept, (), (override));
+  MOCK_METHOD(bool, Cancel, (), (override));
+};
+
+TEST_F(AutofillVCNEnrollBottomSheetBridgeTest, DismissCallback) {
+  auto delegate = std::make_unique<MockDelegate>(BuildController());
+  MockDelegate& delegate_reference = *delegate;
+  AutofillVCNEnrollBottomSheetBridge bridge;
+  bridge.RequestShowContent(web_contents(), std::move(delegate));
+
+  EXPECT_CALL(delegate_reference, InfoBarDismissed());
+
+  bridge.OnDismiss(/*env=*/nullptr);
+}
+
+TEST_F(AutofillVCNEnrollBottomSheetBridgeTest, AcceptCallback) {
+  auto delegate = std::make_unique<MockDelegate>(BuildController());
+  MockDelegate& delegate_reference = *delegate;
+  AutofillVCNEnrollBottomSheetBridge bridge;
+  bridge.RequestShowContent(web_contents(), std::move(delegate));
+
+  EXPECT_CALL(delegate_reference, Accept());
+
+  bridge.OnAccept(/*env=*/nullptr);
+}
+
+TEST_F(AutofillVCNEnrollBottomSheetBridgeTest, CancelCallback) {
+  auto delegate = std::make_unique<MockDelegate>(BuildController());
+  MockDelegate& delegate_reference = *delegate;
+  AutofillVCNEnrollBottomSheetBridge bridge;
+  bridge.RequestShowContent(web_contents(), std::move(delegate));
+
+  EXPECT_CALL(delegate_reference, Cancel());
+
+  bridge.OnCancel(/*env=*/nullptr);
+}
+
 }  // namespace
 }  // namespace autofill
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
index 309ec74..0512535 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
@@ -220,6 +220,7 @@
         TextView textView = view.findViewById(R.id.idp_signin);
         textView.setText(String.format(
                 context.getString(R.string.idp_signin_status_mismatch_dialog_body, idpForDisplay)));
+        textView.setMovementMethod(LinkMovementMethod.getInstance());
     }
 
     /**
@@ -350,6 +351,7 @@
                     model.get(HeaderProperties.IDP_FOR_DISPLAY),
                     model.get(HeaderProperties.RP_CONTEXT));
             headerTitleText.setText(title);
+            headerTitleText.setMovementMethod(LinkMovementMethod.getInstance());
 
             // Make instructions for closing the bottom sheet part of the header's content
             // description. This is needed because the bottom sheet's content description (which
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
index 35ef41c..93fea44 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
@@ -127,7 +127,7 @@
         assertEquals("Incorrect title",
                 mResources.getString(R.string.account_selection_sheet_title_explicit_signin,
                         "example.org", "idp.org"),
-                title.getText());
+                title.getText().toString());
         assertEquals("Incorrect subtitle", "", subtitle.getText());
     }
 
@@ -148,7 +148,7 @@
         assertEquals("Incorrect title",
                 mResources.getString(R.string.account_selection_sheet_title_explicit_signin,
                         "iframe-example.org", "idp.org"),
-                title.getText());
+                title.getText().toString());
         assertEquals("Incorrect subtitle",
                 mResources.getString(
                         R.string.account_selection_sheet_subtitle_explicit, "example.org"),
@@ -169,7 +169,7 @@
         TextView subtitle = mContentView.findViewById(R.id.header_subtitle);
 
         assertEquals("Incorrect title", mResources.getString(R.string.verify_sheet_title),
-                title.getText());
+                title.getText().toString());
         assertEquals("Incorrect subtitle", "", subtitle.getText());
     }
 
@@ -187,7 +187,8 @@
         TextView subtitle = mContentView.findViewById(R.id.header_subtitle);
 
         assertEquals("Incorrect title",
-                mResources.getString(R.string.verify_sheet_title_auto_reauthn), title.getText());
+                mResources.getString(R.string.verify_sheet_title_auto_reauthn),
+                title.getText().toString());
         assertEquals("Incorrect subtitle", "", subtitle.getText());
     }
 
@@ -301,7 +302,7 @@
 
             assertEquals("Incorrect title",
                     mResources.getString(rpContext.mTitleId, "example.org", "idp.org"),
-                    title.getText());
+                    title.getText().toString());
             assertEquals("Incorrect subtitle", "", subtitle.getText());
         }
     }
@@ -323,7 +324,7 @@
 
             assertEquals("Incorrect title",
                     mResources.getString(rpContext.mTitleId, "iframe-example.org", "idp.org"),
-                    title.getText());
+                    title.getText().toString());
             assertEquals("Incorrect subtitle",
                     mResources.getString(
                             R.string.account_selection_sheet_subtitle_explicit, "example.org"),
@@ -342,8 +343,8 @@
                 R.string.idp_signin_status_mismatch_dialog_body, idpEtldPlusOne);
         // We use toString() here because otherwise getText() returns a
         // Spanned, which is not equal to the string we get from the resources.
-        assertEquals(
-                "Incorrect IDP sign in mismatch body dialog text", expectedText, consent.getText());
+        assertEquals("Incorrect IDP sign in mismatch body dialog text", expectedText,
+                consent.getText().toString());
 
         mModel.set(ItemProperties.CONTINUE_BUTTON, buildContinueButton(null, null));
         ButtonCompat continueButton =
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.cc
index cf102d9..c3309609 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.cc
@@ -4,6 +4,11 @@
 
 #include "chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h"
 
+#include "ash/public/cpp/shelf_item_delegate.h"
+#include "ash/public/cpp/shelf_types.h"
+#include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
+#include "ui/events/event.h"
+
 AppServiceShortcutShelfItemController::AppServiceShortcutShelfItemController(
     const ash::ShelfID& shelf_id)
     : ash::ShelfItemDelegate(shelf_id) {}
@@ -11,6 +16,18 @@
 AppServiceShortcutShelfItemController::
     ~AppServiceShortcutShelfItemController() = default;
 
+void AppServiceShortcutShelfItemController::ItemSelected(
+    std::unique_ptr<ui::Event> event,
+    int64_t display_id,
+    ash::ShelfLaunchSource source,
+    ItemSelectedCallback callback,
+    const ItemFilterPredicate& filter_predicate) {
+  std::move(callback).Run(ash::SHELF_ACTION_NEW_WINDOW_CREATED, {});
+  ChromeShelfController::instance()->LaunchApp(ash::ShelfID(shelf_id()), source,
+                                               ui::EF_NONE, display_id);
+  return;
+}
+
 void AppServiceShortcutShelfItemController::ExecuteCommand(
     bool from_context_menu,
     int64_t command_id,
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h
index c966cef..93507a0 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h
@@ -21,6 +21,11 @@
   ~AppServiceShortcutShelfItemController() override;
 
   // ash::ShelfItemDelegate overrides:
+  void ItemSelected(std::unique_ptr<ui::Event> event,
+                    int64_t display_id,
+                    ash::ShelfLaunchSource source,
+                    ItemSelectedCallback callback,
+                    const ItemFilterPredicate& filter_predicate) override;
   void ExecuteCommand(bool from_context_menu,
                       int64_t command_id,
                       int32_t event_flags,
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller_browsertest.cc
new file mode 100644
index 0000000..7d13141
--- /dev/null
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller_browsertest.cc
@@ -0,0 +1,73 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller.h"
+
+#include "ash/public/cpp/shelf_model.h"
+#include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
+#include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/app_constants/constants.h"
+#include "components/services/app_service/public/cpp/shortcut/shortcut.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/test/browser_test.h"
+
+class AppServiceShortcutShelfItemControllerBrowserTest
+    : public InProcessBrowserTest {
+ protected:
+  AppServiceShortcutShelfItemControllerBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kCrosWebAppShortcutUiUpdate);
+  }
+
+  void SetUpOnMainThread() override { ASSERT_TRUE(controller()); }
+
+  apps::ShortcutId CreateWebAppBasedShortcut(
+      const GURL& app_url,
+      const std::u16string& shortcut_name) {
+    // Create web app based shortcut.
+    auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
+    web_app_info->start_url = app_url;
+    web_app_info->title = shortcut_name;
+    auto local_shortcut_id = web_app::test::InstallWebApp(
+        browser()->profile(), std::move(web_app_info));
+    return apps::GenerateShortcutId(app_constants::kChromeAppId,
+                                    local_shortcut_id);
+  }
+
+  ChromeShelfController* controller() {
+    return ChromeShelfController::instance();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(AppServiceShortcutShelfItemControllerBrowserTest,
+                       SelectItem) {
+  GURL app_url = GURL("https://example.org/");
+  std::u16string shortcut_name = u"Example";
+  apps::ShortcutId shortcut_id =
+      CreateWebAppBasedShortcut(app_url, shortcut_name);
+
+  PinAppWithIDToShelf(shortcut_id.value());
+
+  ash::ShelfItemDelegate* delegate =
+      controller()->shelf_model()->GetShelfItemDelegate(
+          ash::ShelfID(shortcut_id.value()));
+
+  ASSERT_TRUE(delegate);
+
+  ui_test_utils::UrlLoadObserver url_observer(
+      app_url, content::NotificationService::AllSources());
+  delegate->ItemSelected(/*event=*/nullptr, display::kInvalidDisplayId,
+                         ash::LAUNCH_FROM_UNKNOWN,
+                         /*callback=*/base::DoNothing(),
+                         /*filter_predicate=*/base::NullCallback());
+  url_observer.Wait();
+}
diff --git a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
index c4c7ad1..6bf3339 100644
--- a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
@@ -118,19 +118,16 @@
     }
   }
 
-  if (base::FeatureList::IsEnabled(features::kCrosWebAppShortcutUiUpdate)) {
-    std::u16string shortcut_title;
-    if (apps::AppServiceProxyFactory::GetForProfile(profile)
+  if (IsAppServiceShortcut(profile, app_id)) {
+    absl::optional<std::string> shortcut_name =
+        apps::AppServiceProxyFactory::GetForProfile(profile)
             ->ShortcutRegistryCache()
-            ->HasShortcut(apps::ShortcutId(app_id))) {
-      absl::optional<std::string> shortcut_name =
-          apps::AppServiceProxyFactory::GetForProfile(profile)
-              ->ShortcutRegistryCache()
-              ->GetShortcut(apps::ShortcutId(app_id))
-              ->name;
-      if (shortcut_name.has_value()) {
-        shortcut_title = base::UTF8ToUTF16(shortcut_name.value());
-      }
+            ->GetShortcut(apps::ShortcutId(app_id))
+            ->name;
+
+    std::u16string shortcut_title;
+    if (shortcut_name.has_value()) {
+      shortcut_title = base::UTF8ToUTF16(shortcut_name.value());
     }
 
     if (!shortcut_title.empty()) {
@@ -251,6 +248,15 @@
   }
 }
 
+// static
+bool ShelfControllerHelper::IsAppServiceShortcut(Profile* profile,
+                                                 const std::string& id) {
+  return base::FeatureList::IsEnabled(features::kCrosWebAppShortcutUiUpdate) &&
+         apps::AppServiceProxyFactory::GetForProfile(profile)
+             ->ShortcutRegistryCache()
+             ->HasShortcut(apps::ShortcutId(id));
+}
+
 bool ShelfControllerHelper::IsValidIDForCurrentUser(
     const std::string& app_id) const {
   if (IsValidIDForArcApp(app_id))
@@ -281,6 +287,12 @@
     return;
   }
 
+  // Launch the shortcut if the shelf item is a shortcut to an app.
+  if (IsAppServiceShortcut(profile_, app_id)) {
+    proxy->LaunchShortcut(apps::ShortcutId(app_id), display_id);
+    return;
+  }
+
   // For extensions, Launch with AppServiceProxy.LaunchAppWithParams.
 
   // |extension| could be null when it is being unloaded for updating.
diff --git a/chrome/browser/ui/ash/shelf/shelf_controller_helper.h b/chrome/browser/ui/ash/shelf/shelf_controller_helper.h
index 1471a90..d7fcbd3 100644
--- a/chrome/browser/ui/ash/shelf/shelf_controller_helper.h
+++ b/chrome/browser/ui/ash/shelf/shelf_controller_helper.h
@@ -72,6 +72,9 @@
   static ash::AppStatus ConvertPromiseStatusToAppStatus(
       apps::PromiseStatus promise_status);
 
+  // Check whether this item is an app service shortcut.
+  static bool IsAppServiceShortcut(Profile* profile, const std::string& id);
+
   // Returns true if |id| is valid for the currently active profile.
   // Used during restore to ignore no longer valid extensions.
   // Note that already running applications are ignored by the restore process.
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index f09d6644..a905698 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -117,8 +117,8 @@
              Profile*,
              password_manager::metrics_util::PasswordMigrationWarningTriggers)>
         show_pwd_migration_warning_callback)
-    : controller_common_(element_bounds, text_direction, container_view),
-      web_contents_(web_contents),
+    : content::WebContentsObserver(web_contents),
+      controller_common_(element_bounds, text_direction, container_view),
       delegate_(delegate),
       show_pwd_migration_warning_callback_(
           std::move(show_pwd_migration_warning_callback)) {
@@ -134,6 +134,26 @@
 
 AutofillPopupControllerImpl::~AutofillPopupControllerImpl() = default;
 
+void AutofillPopupControllerImpl::RenderFrameDeleted(
+    content::RenderFrameHost* rfh) {
+  // If the popup menu has been triggered from within an iframe and that frame
+  // is deleted, hide the popup. This is necessary because the popup may
+  // actually be shown by the AutofillExternalDelegate of an ancestor frame,
+  // which is not notified about `rfh`'s destruction and therefore won't close
+  // the popup.
+  if (key_press_observer_.handler &&
+      key_press_observer_.rfh == rfh->GetGlobalId()) {
+    Hide(PopupHidingReason::kRendererEvent);
+  }
+}
+
+void AutofillPopupControllerImpl::OnVisibilityChanged(
+    content::Visibility visibility) {
+  if (visibility == content::Visibility::HIDDEN) {
+    Hide(PopupHidingReason::kTabGone);
+  }
+}
+
 void AutofillPopupControllerImpl::Show(
     std::vector<Suggestion> suggestions,
     AutofillSuggestionTriggerSource trigger_source) {
@@ -142,7 +162,7 @@
     return;
   }
 
-  content::RenderFrameHost* rfh = web_contents_->GetFocusedFrame();
+  content::RenderFrameHost* rfh = web_contents()->GetFocusedFrame();
   if (!rfh) {
     Hide(PopupHidingReason::kNoFrameHasFocus);
     return;
@@ -169,7 +189,7 @@
     }
 
 #if BUILDFLAG(IS_ANDROID)
-    ManualFillingController::GetOrCreate(web_contents_)
+    ManualFillingController::GetOrCreate(web_contents())
         ->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                    !suggestions_.empty());
 #endif
@@ -188,7 +208,7 @@
   }
   time_view_shown_ = base::TimeTicks::Now();
 
-  content::RenderWidgetHost* rwh = rfh->GetRenderWidgetHost();
+  key_press_observer_.rfh = rfh->GetGlobalId();
   key_press_observer_.handler = base::BindRepeating(
       // Cannot bind HandleKeyPressEvent() directly because of its
       // return value.
@@ -197,9 +217,8 @@
         return weak_this && weak_this->HandleKeyPressEvent(event);
       },
       GetWeakPtr());
-  key_press_observer_.rwh_process_id = rwh->GetProcess()->GetID();
-  key_press_observer_.rwh_routing_id = rwh->GetRoutingID();
-  rwh->AddKeyPressEventCallback(key_press_observer_.handler);
+  rfh->GetRenderWidgetHost()->AddKeyPressEventCallback(
+      key_press_observer_.handler);
 
   delegate_->OnPopupShown();
 }
@@ -285,10 +304,9 @@
     delegate_->OnPopupHidden();
   }
   if (key_press_observer_.handler) {
-    content::RenderWidgetHost* rwh = content::RenderWidgetHost::FromID(
-        key_press_observer_.rwh_process_id, key_press_observer_.rwh_routing_id);
-    if (rwh) {
-      rwh->RemoveKeyPressEventCallback(key_press_observer_.handler);
+    if (auto* rfh = content::RenderFrameHost::FromID(key_press_observer_.rfh)) {
+      rfh->GetRenderWidgetHost()->RemoveKeyPressEventCallback(
+          key_press_observer_.handler);
     }
     key_press_observer_ = {};
   }
@@ -323,7 +341,7 @@
 #if BUILDFLAG(IS_ANDROID)
   // Assume that suggestions are (still) available. If this is wrong, the method
   // |HideViewAndDie| will be called soon after and will hide all suggestions.
-  ManualFillingController::GetOrCreate(web_contents_)
+  ManualFillingController::GetOrCreate(web_contents())
       ->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                  /*has_suggestions=*/true);
 #endif
@@ -370,7 +388,7 @@
   // reference.
   Suggestion suggestion = suggestions_[index];
 #if BUILDFLAG(IS_ANDROID)
-  auto mf_controller = ManualFillingController::GetOrCreate(web_contents_);
+  auto mf_controller = ManualFillingController::GetOrCreate(web_contents());
   // Accepting a suggestion should hide all suggestions. To prevent them from
   // coming up in Multi-Window mode, mark the source as unavailable.
   mf_controller->UpdateSourceAvailability(FillingSource::AUTOFILL,
@@ -378,8 +396,7 @@
   mf_controller->Hide();
 #endif
 
-  if (web_contents_ &&
-      suggestion.popup_item_id == PopupItemId::kVirtualCreditCardEntry) {
+  if (suggestion.popup_item_id == PopupItemId::kVirtualCreditCardEntry) {
     std::string event_name =
         suggestion.feature_for_iph ==
                 feature_engagement::kIPHAutofillVirtualCardCVCSuggestionFeature
@@ -387,16 +404,15 @@
             ? "autofill_virtual_card_cvc_suggestion_accepted"
             : "autofill_virtual_card_suggestion_accepted";
     feature_engagement::TrackerFactory::GetForBrowserContext(
-        web_contents_->GetBrowserContext())
+        web_contents()->GetBrowserContext())
         ->NotifyEvent(event_name);
   }
 
-  if (web_contents_ &&
-      suggestion.feature_for_iph ==
-          feature_engagement::
-              kIPHAutofillExternalAccountProfileSuggestionFeature.name) {
+  if (suggestion.feature_for_iph ==
+      feature_engagement::kIPHAutofillExternalAccountProfileSuggestionFeature
+          .name) {
     feature_engagement::TrackerFactory::GetForBrowserContext(
-        web_contents_->GetBrowserContext())
+        web_contents()->GetBrowserContext())
         ->NotifyEvent("autofill_external_account_profile_suggestion_accepted");
   }
 
@@ -414,8 +430,8 @@
           password_manager::features::
               kUnifiedPasswordManagerLocalPasswordsMigrationWarning)) {
     show_pwd_migration_warning_callback_.Run(
-        web_contents_->GetTopLevelNativeWindow(),
-        Profile::FromBrowserContext(web_contents_->GetBrowserContext()),
+        web_contents()->GetTopLevelNativeWindow(),
+        Profile::FromBrowserContext(web_contents()->GetBrowserContext()),
         password_manager::metrics_util::PasswordMigrationWarningTriggers::
             kKeyboardAcessoryBar);
   }
@@ -427,7 +443,7 @@
 }
 
 content::WebContents* AutofillPopupControllerImpl::GetWebContents() const {
-  return web_contents_;
+  return web_contents();
 }
 
 const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const {
@@ -582,7 +598,7 @@
   // Mark the popup-like filling sources as unavailable.
   // Note: We don't invoke ManualFillingController::Hide() here, as we might
   // switch between text input fields.
-  ManualFillingController::GetOrCreate(web_contents_)
+  ManualFillingController::GetOrCreate(web_contents())
       ->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                  /*has_suggestions=*/false);
 #endif
@@ -612,7 +628,7 @@
 bool AutofillPopupControllerImpl::IsMouseLocked() const {
   content::RenderFrameHost* rfh;
   content::RenderWidgetHostView* rwhv;
-  return web_contents_ && (rfh = web_contents_->GetFocusedFrame()) &&
+  return web_contents() && (rfh = web_contents()->GetFocusedFrame()) &&
          (rwhv = rfh->GetView()) && rwhv->IsMouseLocked();
 }
 
@@ -628,7 +644,7 @@
 
   // Retrieve the ax tree id associated with the current web contents.
   ui::AXTreeID tree_id;
-  if (content::RenderFrameHost* rfh = web_contents_->GetFocusedFrame()) {
+  if (content::RenderFrameHost* rfh = web_contents()->GetFocusedFrame()) {
     tree_id = rfh->GetAXTreeID();
   }
 
@@ -668,10 +684,11 @@
 
 ui::AXPlatformNode*
 AutofillPopupControllerImpl::GetRootAXPlatformNodeForWebContents() {
-  if (!web_contents_)
+  if (!web_contents()) {
     return nullptr;
+  }
 
-  auto* rwhv = web_contents_->GetRenderWidgetHostView();
+  auto* rwhv = web_contents()->GetRenderWidgetHostView();
   if (!rwhv)
     return nullptr;
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
index 76c36f3..ad4a683 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -23,6 +23,7 @@
 #include "components/autofill/core/common/aliases.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
@@ -56,6 +57,7 @@
 // other, public functions are available to its instantiator.
 class AutofillPopupControllerImpl
     : public AutofillPopupController,
+      public content::WebContentsObserver,
       public PictureInPictureWindowManager::Observer {
  public:
   AutofillPopupControllerImpl(const AutofillPopupControllerImpl&) = delete;
@@ -169,7 +171,7 @@
   // show or hide action.
   void FireControlsChangedEvent(bool is_show);
 
-  // Gets the root AXPlatformNode for our web_contents_, which can be used
+  // Gets the root AXPlatformNode for our WebContents, which can be used
   // to find the AXPlatformNode specifically for the autofill text field.
   virtual ui::AXPlatformNode* GetRootAXPlatformNodeForWebContents();
 
@@ -216,6 +218,10 @@
     base::WeakPtr<AutofillPopupView> ptr_;
   };
 
+  // content::WebContentsObserver:
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void OnVisibilityChanged(content::Visibility visibility) override;
+
   // Clear the internal state of the controller. This is needed to ensure that
   // when the popup is reused it doesn't leak values between uses.
   void ClearState();
@@ -236,14 +242,12 @@
   void SetViewForTesting(base::WeakPtr<AutofillPopupView> view);
 
   PopupControllerCommon controller_common_;
-  raw_ptr<content::WebContents, AcrossTasksDanglingUntriaged> web_contents_;
   AutofillPopupViewPtr view_;
   base::WeakPtr<AutofillPopupDelegate> delegate_;
 
   struct {
+    content::GlobalRenderFrameHostId rfh;
     content::RenderWidgetHost::KeyPressEventCallback handler;
-    int rwh_process_id = -1;
-    int rwh_routing_id = -1;
   } key_press_observer_;
 
   // The time the view was shown the last time. It is used to safeguard against
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
index a2e08ee..e74af43 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -254,8 +254,6 @@
 
   virtual std::unique_ptr<NiceMock<MockAutofillExternalDelegate>>
   CreateExternalDelegate() {
-    // Fake that |driver| has queried a form.
-    test_api(autofill_router()).set_last_queried_source(autofill_driver());
     return std::make_unique<NiceMock<MockAutofillExternalDelegate>>(
         autofill_manager());
   }
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
index 632c85d..46ba5ff 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h
@@ -76,6 +76,10 @@
   bool DidShowBottomSheetForTesting() const {
     return !!autofill_vcn_enroll_bottom_sheet_bridge_;
   }
+
+  void SetFieldsForTesting(const VirtualCardEnrollmentFields& fields) {
+    virtual_card_enrollment_fields_ = fields;
+  }
 #endif  // IS_ANDROID
 #endif  // UNIT_TEST
 
diff --git a/chrome/browser/ui/safety_hub/notification_permission_review_service.cc b/chrome/browser/ui/safety_hub/notification_permission_review_service.cc
index ac83b752e..39dd8981 100644
--- a/chrome/browser/ui/safety_hub/notification_permission_review_service.cc
+++ b/chrome/browser/ui/safety_hub/notification_permission_review_service.cc
@@ -261,6 +261,7 @@
     std::string notification_info_string = l10n_util::GetPluralStringFUTF8(
         IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_COUNT_LABEL,
         notification_permission.notification_count);
+    permission.Set(kSafetyHubNotificationInfoString, notification_info_string);
     result.Append(std::move(permission));
   }
 
diff --git a/chrome/browser/ui/safety_hub/notification_permission_review_service.h b/chrome/browser/ui/safety_hub/notification_permission_review_service.h
index d2cb92f..c1b99f19 100644
--- a/chrome/browser/ui/safety_hub/notification_permission_review_service.h
+++ b/chrome/browser/ui/safety_hub/notification_permission_review_service.h
@@ -14,6 +14,8 @@
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/keyed_service/core/keyed_service.h"
 
+constexpr char kSafetyHubNotificationInfoString[] = "notificationInfoString";
+
 struct NotificationPermissions {
   ContentSettingsPattern primary_pattern;
   ContentSettingsPattern secondary_pattern;
diff --git a/chrome/browser/ui/safety_hub/notification_permission_review_service_unittest.cc b/chrome/browser/ui/safety_hub/notification_permission_review_service_unittest.cc
index 92b20ced..9387a557 100644
--- a/chrome/browser/ui/safety_hub/notification_permission_review_service_unittest.cc
+++ b/chrome/browser/ui/safety_hub/notification_permission_review_service_unittest.cc
@@ -228,9 +228,15 @@
   EXPECT_EQ("https://www.youtube.com:443",
             *notification_permissions[0].GetDict().FindString(
                 site_settings::kOrigin));
+  EXPECT_EQ("About 5 notifications a day",
+            *notification_permissions[0].GetDict().FindString(
+                kSafetyHubNotificationInfoString));
   EXPECT_EQ("https://google.com:443",
             *notification_permissions[1].GetDict().FindString(
                 site_settings::kOrigin));
+  EXPECT_EQ("About 1 notification a day",
+            *notification_permissions[1].GetDict().FindString(
+                kSafetyHubNotificationInfoString));
 
   // Increasing notification count also promotes host in the list.
   RecordNotification(notification_engagement_service,
@@ -241,7 +247,13 @@
   EXPECT_EQ("https://google.com:443",
             *updated_notification_permissions[0].GetDict().FindString(
                 site_settings::kOrigin));
+  EXPECT_EQ("About 11 notifications a day",
+            *updated_notification_permissions[0].GetDict().FindString(
+                kSafetyHubNotificationInfoString));
   EXPECT_EQ("https://www.youtube.com:443",
             *updated_notification_permissions[1].GetDict().FindString(
                 site_settings::kOrigin));
+  EXPECT_EQ("About 5 notifications a day",
+            *updated_notification_permissions[1].GetDict().FindString(
+                kSafetyHubNotificationInfoString));
 }
diff --git a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
index 9e5e40c..609f37f 100644
--- a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
@@ -14,6 +14,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -325,7 +326,10 @@
           VideoOverlayWindowViews::kControlHideDelayAfterMove,
           base::BindRepeating(
               &VideoOverlayWindowViews::ReEnableControlsAfterMove,
-              base::Unretained(this))) {
+              base::Unretained(this))),
+      get_overlay_view_cb_(base::BindRepeating(
+          &PictureInPictureWindowManager::GetOverlayView,
+          base::Unretained(PictureInPictureWindowManager::GetInstance()))) {
   display::Screen::GetScreen()->AddObserver(this);
 }
 
@@ -597,8 +601,9 @@
     return;
   }
 
+  // If the overlay view is shown, then the other controls are always hidden.
   GetControlsContainerView()->SetVisible(
-      force_controls_visible_.value_or(is_visible));
+      !IsOverlayViewShown() && force_controls_visible_.value_or(is_visible));
 }
 
 void VideoOverlayWindowViews::UpdateControlsBounds() {
@@ -684,6 +689,13 @@
 
 bool VideoOverlayWindowViews::ControlsHitTestContainsPoint(
     const gfx::Point& point) {
+  if (IsOverlayViewShown()) {
+    // Let the overlay view consume this event if it wants to.  If not, then
+    // ignore any of our controls as well.  This will still permit dragging the
+    // window by any parts that aren't consumed by the overlay view.
+    return overlay_view_->GetEventHandlerForPoint(point);
+  }
+
   if (!AreControlsVisible())
     return false;
   if (GetBackToTabControlsBounds().Contains(point) ||
@@ -1005,6 +1017,10 @@
   if (video_view_->layer()->has_external_content())
     video_view_->layer()->SetSurfaceSize(video_bounds.size());
 
+  if (IsOverlayViewShown()) {
+    overlay_view_->SetBoundsRect(gfx::Rect(GetBounds().size()));
+  }
+
   // Notify the controller that the bounds have changed.
   controller_->UpdateLayerBounds();
 }
@@ -1210,6 +1226,20 @@
                        chromeos::kPipRoundedCornerRadius);
 #endif
 
+  // If there is an existing overlay view, remove it now.
+  if (overlay_view_) {
+    GetContentsView()->RemoveChildView(overlay_view_);
+    overlay_view_ = nullptr;
+  }
+
+  // Re-add it if needed.
+  if (auto overlay_view = get_overlay_view_cb_.Run()) {
+    overlay_view_ = GetContentsView()->AddChildView(std::move(overlay_view));
+    // Also update the bounds, since that's already happened for everything
+    // else, potentially, during widget resize.
+    overlay_view_->SetBoundsRect(gfx::Rect(GetBounds().size()));
+  }
+
   // If this is not the first time the window is shown, this will be a no-op.
   has_been_shown_ = true;
 }
@@ -1556,3 +1586,7 @@
     has_registered_frame_sink_hierarchy_ = false;
   }
 }
+
+bool VideoOverlayWindowViews::IsOverlayViewShown() const {
+  return overlay_view_ && overlay_view_->GetVisible();
+}
diff --git a/chrome/browser/ui/views/overlay/video_overlay_window_views.h b/chrome/browser/ui/views/overlay/video_overlay_window_views.h
index 1e283ff..541bc182 100644
--- a/chrome/browser/ui/views/overlay/video_overlay_window_views.h
+++ b/chrome/browser/ui/views/overlay/video_overlay_window_views.h
@@ -37,6 +37,9 @@
                                 public views::Widget,
                                 public display::DisplayObserver {
  public:
+  using GetOverlayViewCb =
+      base::RepeatingCallback<std::unique_ptr<views::View>()>;
+
   static std::unique_ptr<VideoOverlayWindowViews> Create(
       content::VideoPictureInPictureWindowController* controller);
 
@@ -157,6 +160,10 @@
 
   void ForceControlsVisibleForTesting(bool visible);
 
+  void set_overlay_view_cb_for_testing(GetOverlayViewCb get_overlay_view_cb) {
+    get_overlay_view_cb_ = std::move(get_overlay_view_cb);
+  }
+
   // Determines whether a layout of the window controls has been scheduled but
   // is not done yet.
   bool IsLayoutPendingForTesting() const;
@@ -234,6 +241,10 @@
   // visibility to the last requested state.
   void ReEnableControlsAfterMove();
 
+  // Returns true if and only if `overlay_view_` is currently shown.  In
+  // practice, the is the allow / block UI for auto-pip.
+  bool IsOverlayViewShown() const;
+
   // Not owned; |controller_| owns |this|.
   raw_ptr<content::VideoPictureInPictureWindowController> controller_;
 
@@ -300,6 +311,7 @@
   raw_ptr<SimpleOverlayWindowImageButton> previous_slide_controls_view_ =
       nullptr;
   raw_ptr<SimpleOverlayWindowImageButton> next_slide_controls_view_ = nullptr;
+  raw_ptr<views::View> overlay_view_ = nullptr;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Generates a nine patch layer painted with a highlight border for ChromeOS
@@ -347,6 +359,10 @@
   // Whether or not the current frame sink for the surface displayed in the
   // |video_view_| is registered as the child of the overlay window frame sink.
   bool has_registered_frame_sink_hierarchy_ = false;
+
+  // Callback to get / create an overlay view.  This is a callback to let tests
+  // provide alternate implementations.
+  GetOverlayViewCb get_overlay_view_cb_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_OVERLAY_VIDEO_OVERLAY_WINDOW_VIEWS_H_
diff --git a/chrome/browser/ui/views/overlay/video_overlay_window_views_unittest.cc b/chrome/browser/ui/views/overlay/video_overlay_window_views_unittest.cc
index e79de26b..64af94d 100644
--- a/chrome/browser/ui/views/overlay/video_overlay_window_views_unittest.cc
+++ b/chrome/browser/ui/views/overlay/video_overlay_window_views_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/memory/raw_ptr.h"
+#include "base/test/mock_callback.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/views/overlay/close_image_button.h"
@@ -23,9 +24,13 @@
 #include "ui/display/test/test_screen.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/vector2d.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/test/button_test_api.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget_utils.h"
 
 namespace {
 
@@ -33,6 +38,8 @@
 
 }  // namespace
 
+using testing::_;
+
 class TestVideoPictureInPictureWindowController
     : public content::VideoPictureInPictureWindowController {
  public:
@@ -97,9 +104,16 @@
     SetDisplayWorkArea({0, 0, 1000, 1000});
 
     overlay_window_ = VideoOverlayWindowViews::Create(&pip_window_controller_);
+    overlay_window_->set_overlay_view_cb_for_testing(
+        base::BindRepeating(&VideoOverlayWindowViewsTest::GetOverlayViewImpl,
+                            base::Unretained(this)));
+
     // On some platforms, OnNativeWidgetMove is invoked on creation.
     WaitForMove();
     overlay_window_->set_minimum_size_for_testing(kMinWindowSize);
+
+    event_generator_ = std::make_unique<ui::test::EventGenerator>(
+        views::GetRootWindow(overlay_window_.get()));
   }
 
   void TearDown() override {
@@ -122,6 +136,13 @@
     return pip_window_controller_;
   }
 
+  views::View* SetOverlayView(std::unique_ptr<views::View> overlay_view) {
+    overlay_view_ = std::move(overlay_view);
+    return overlay_view_.get();
+  }
+
+  ui::test::EventGenerator* event_generator() { return event_generator_.get(); }
+
  protected:
   void WaitForMove() {
     task_environment()->FastForwardBy(
@@ -130,6 +151,10 @@
   }
 
  private:
+  std::unique_ptr<views::View> GetOverlayViewImpl() {
+    return std::move(overlay_view_);
+  }
+
   TestingProfile profile_;
   content::TestWebContentsFactory web_contents_factory_;
   raw_ptr<content::WebContents> web_contents_;
@@ -137,6 +162,11 @@
 
   display::test::TestScreen test_screen_;
 
+  // Overlay view that we'll send to the window.  May be null.
+  std::unique_ptr<views::View> overlay_view_;
+
+  std::unique_ptr<ui::test::EventGenerator> event_generator_;
+
   std::unique_ptr<VideoOverlayWindowViews> overlay_window_;
 };
 
@@ -506,3 +536,53 @@
   // Only the last one should have any effect.
   EXPECT_FALSE(overlay_window().AreControlsVisible());
 }
+
+TEST_F(VideoOverlayWindowViewsTest, OverlayViewIsSizedCorrectly) {
+  // Set the bound of the window before showing it, to make sure the size
+  // propagates to the overlay view.
+  const gfx::Rect bounds(0, 0, 200, 200);
+  overlay_window().UpdateNaturalSize(bounds.size());
+  overlay_window().SetBounds(bounds);
+  // Setting the overlay view before show should be sufficient for it to take
+  // effect when shown.
+  auto* overlay_view = SetOverlayView(std::make_unique<views::View>());
+  overlay_window().ShowInactive();
+  EXPECT_TRUE(overlay_view->GetVisible());
+  EXPECT_EQ(overlay_view->bounds(), bounds);
+}
+
+TEST_F(VideoOverlayWindowViewsTest, OverlayViewCanBeClicked) {
+  // Make sure that the overlay view is z-ordered to get input events.
+  auto* overlay_view = SetOverlayView(std::make_unique<views::View>());
+
+  // Add a button!
+  base::MockRepeatingCallback<void(const ui::Event&)> cb;
+  auto* button = overlay_view->AddChildView(
+      std::make_unique<views::LabelButton>(cb.Get()));
+  button->SetBounds(0, 0, 50, 50);
+
+  // Show the window and click the button.
+  overlay_window().ShowInactive();
+  EXPECT_CALL(cb, Run(_));
+  event_generator()->MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
+  event_generator()->ClickLeftButton();
+
+  // Clear the callback since `cb` is going away.  Note that `DoNothing()`
+  // doesn't work here because type inference fails.
+  button->SetCallback(base::BindRepeating([](const ui::Event&) {}));
+}
+
+TEST_F(VideoOverlayWindowViewsTest, OverlayWindowBlocksInput) {
+  // Make sure that the playback controls don't receive input events while the
+  // overlay view is visible.
+  SetOverlayView(std::make_unique<views::View>());
+  overlay_window().ShowInactive();
+
+  // When the play/pause controls are visible, closing via the close button
+  // should pause the video.
+  overlay_window().SetPlayPauseButtonVisibility(true);
+  EXPECT_CALL(pip_window_controller(), Close(true)).Times(0);
+  event_generator()->MoveMouseTo(
+      overlay_window().GetCloseControlsBounds().CenterPoint());
+  event_generator()->ClickLeftButton();
+}
diff --git a/chrome/browser/ui/views/profiles/profile_menu_coordinator.cc b/chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
index 9aefd8bf..521991e 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
@@ -45,12 +45,19 @@
       feature_engagement::kIPHProfileSwitchFeature);
 
   std::unique_ptr<ProfileMenuViewBase> bubble;
-  if (browser.profile()->IsIncognitoProfile()) {
+  bool is_incognito = browser.profile()->IsIncognitoProfile();
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // On Lacros, the guest session returns true for `IsIncognitoProfile()`, see
+  // https://crbug.com/1348572
+  is_incognito &= !browser.profile()->IsGuestSession();
+#endif
+
+  if (is_incognito) {
     bubble =
         std::make_unique<IncognitoMenuView>(avatar_toolbar_button, &browser);
   } else {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-    // Note: on Ash, Guest Sessions have incognito profiles.
+    // Note: on Ash, only incognito windows have a profile menu.
     NOTREACHED_NORETURN() << "The profile menu is not implemented on Ash.";
 #else
     bubble = std::make_unique<ProfileMenuView>(avatar_toolbar_button, &browser);
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index d7802f3..11f8a4b 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -67,7 +67,6 @@
 #include "components/vector_icons/vector_icons.h"
 #include "net/base/url_util.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/color/color_id.h"
@@ -769,7 +768,3 @@
   }
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-BEGIN_METADATA(ProfileMenuView, ProfileMenuViewBase)
-ADD_READONLY_PROPERTY_METADATA(gfx::ImageSkia, SyncIcon)
-END_METADATA
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h
index b4a54bb..b595939f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -34,8 +34,6 @@
 // It displays a list of profiles and allows users to switch between profiles.
 class ProfileMenuView : public ProfileMenuViewBase {
  public:
-  METADATA_HEADER(ProfileMenuView);
-
   ProfileMenuView(views::Button* anchor_button, Browser* browser);
   ~ProfileMenuView() override;
 
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index f8726cc..4c6746f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -1202,3 +1202,7 @@
   base::ScopedObservation<views::Widget, views::WidgetObserver> observation_{
       this};
 };
+
+BEGIN_METADATA(ProfileMenuViewBase, views::BubbleDialogDelegateView)
+ADD_READONLY_PROPERTY_METADATA(gfx::ImageSkia, SyncIcon)
+END_METADATA
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index c2a9758..52a702c 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/views/close_bubble_on_tab_activation_helper.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
@@ -43,6 +44,8 @@
 class ProfileMenuViewBase : public content::WebContentsDelegate,
                             public views::BubbleDialogDelegateView {
  public:
+  METADATA_HEADER(ProfileMenuViewBase);
+
   // Enumeration of all actionable items in the profile menu.
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
index d6320f6..d44323d 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
@@ -98,6 +98,8 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/lacros/account_manager/fake_account_manager_ui_dialog_waiter.h"
 #include "chrome/browser/signin/signin_ui_delegate_impl_lacros.h"
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/startup/browser_init_params.h"
 #include "components/account_manager_core/chromeos/account_manager_facade_factory.h"
 #include "components/account_manager_core/chromeos/account_manager_mojo_service.h"
 #endif
@@ -887,8 +889,9 @@
   raw_ptr<Profile, DanglingUntriaged> profile_ = nullptr;
 };
 
-#define PROFILE_MENU_CLICK_TEST(actionable_item_list, test_case_name)     \
-  class test_case_name : public ProfileMenuClickTest {                    \
+#define PROFILE_MENU_CLICK_TEST_F(FixtureClass, actionable_item_list,     \
+                                  test_case_name)                         \
+  class test_case_name : public FixtureClass {                            \
    public:                                                                \
     test_case_name() = default;                                           \
     test_case_name(const test_case_name&) = delete;                       \
@@ -906,6 +909,12 @@
                                                                           \
   IN_PROC_BROWSER_TEST_P(test_case_name, test_case_name)
 
+// Specialized variant of `PROFILE_MENU_CLICK_TEST_F` using
+// `ProfileMenuClickTest` as `FixtureClass`.
+#define PROFILE_MENU_CLICK_TEST(actionable_item_list, test_case_name)   \
+  PROFILE_MENU_CLICK_TEST_F(ProfileMenuClickTest, actionable_item_list, \
+                            test_case_name)
+
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
 constexpr ProfileMenuViewBase::ActionableItem
@@ -1261,6 +1270,33 @@
   RunTest();
 }
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+
+class ProfileMenuClickTestGuestSession : public ProfileMenuClickTest {
+ public:
+  // Enable the guest session.
+  void CreatedBrowserMainParts(
+      content::BrowserMainParts* browser_main_parts) override {
+    crosapi::mojom::BrowserInitParamsPtr init_params =
+        chromeos::BrowserInitParams::GetForTests()->Clone();
+    init_params->session_type = crosapi::mojom::SessionType::kGuestSession;
+    chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+    ProfileMenuClickTest::CreatedBrowserMainParts(browser_main_parts);
+  }
+};
+
+// This tests the device guest session, which is not the same as the browser
+// guest mode.
+PROFILE_MENU_CLICK_TEST_F(ProfileMenuClickTestGuestSession,
+                          kActionableItems_GuestProfile,
+                          ProfileMenuClickTest_GuestSession) {
+  SetTargetBrowser(browser());
+
+  RunTest();
+}
+
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 #if !BUILDFLAG(IS_CHROMEOS)
 // List of actionable items in the correct order as they appear in the menu.
 // If a new button is added to the menu, it should also be added to this list.
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
index be37f1d..f432617 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/profiles/profile_menu_view.h"
 
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/browser/ui/test/test_browser_ui.h"
@@ -14,6 +15,7 @@
 #include "chrome/browser/ui/views/profiles/profile_menu_coordinator.h"
 #include "chrome/browser/ui/views/profiles/profiles_pixel_test_utils.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "ui/events/event_utils.h"
@@ -21,45 +23,162 @@
 #include "ui/views/test/widget_test.h"
 #include "ui/views/widget/any_widget_observer.h"
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/startup/browser_init_params.h"
+#endif
+
 namespace {
+
+enum class ProfileTypePixelTestParam {
+  kRegular,
+  kIncognito,
+  kGuest,
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  kDeviceGuestSession,
+#endif
+};
+
+struct ProfileMenuViewPixelTestParam {
+  PixelTestParam pixel_test_param;
+  ProfileTypePixelTestParam profile_type_param;
+};
+
 // To be passed as 4th argument to `INSTANTIATE_TEST_SUITE_P()`, allows the test
 // to be named like `<TestClassName>.InvokeUi_default/<TestSuffix>` instead
 // of using the index of the param in `TestParam` as suffix.
 std::string ParamToTestSuffix(
-    const ::testing::TestParamInfo<PixelTestParam>& info) {
-  return info.param.test_suffix;
+    const ::testing::TestParamInfo<ProfileMenuViewPixelTestParam>& info) {
+  return info.param.pixel_test_param.test_suffix;
 }
 
 // Permutations of supported parameters.
-const PixelTestParam kPixelTestParams[] = {
-    {.test_suffix = "Regular"},
-    {.test_suffix = "DarkTheme", .use_dark_theme = true},
-    {.test_suffix = "RTL", .use_right_to_left_language = true},
-    {.test_suffix = "CR2023", .use_chrome_refresh_2023_style = true},
-    {.test_suffix = "CR2023_DarkTheme",
-     .use_dark_theme = true,
-     .use_chrome_refresh_2023_style = true},
-    {.test_suffix = "CR2023_RTL",
-     .use_right_to_left_language = true,
-     .use_chrome_refresh_2023_style = true},
+const ProfileMenuViewPixelTestParam kPixelTestParams[] = {
+    // Legacy design (to be removed)
+    {.pixel_test_param = {.test_suffix = "Regular"},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
+    {.pixel_test_param = {.test_suffix = "Guest"},
+     .profile_type_param = ProfileTypePixelTestParam::kGuest},
+    {.pixel_test_param = {.test_suffix = "Incognito"},
+     .profile_type_param = ProfileTypePixelTestParam::kIncognito},
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+    {.pixel_test_param = {.test_suffix = "LacrosDeviceGuestSession"},
+     .profile_type_param = ProfileTypePixelTestParam::kDeviceGuestSession},
+#endif
+    {.pixel_test_param = {.test_suffix = "DarkTheme", .use_dark_theme = true},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
+    {.pixel_test_param = {.test_suffix = "RTL",
+                          .use_right_to_left_language = true},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
+
+    // CR2023 design
+    {.pixel_test_param = {.test_suffix = "CR2023",
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
+    {.pixel_test_param = {.test_suffix = "CR2023_Guest",
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kGuest},
+    {.pixel_test_param = {.test_suffix = "CR2023_DarkTheme_Guest",
+                          .use_dark_theme = true,
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kGuest},
+    {.pixel_test_param = {.test_suffix = "CR2023_Incognito",
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kIncognito},
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+    {.pixel_test_param = {.test_suffix = "CR2023_LacrosDeviceGuestSession",
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kDeviceGuestSession},
+#endif
+    {.pixel_test_param = {.test_suffix = "CR2023_DarkTheme",
+                          .use_dark_theme = true,
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
+    {.pixel_test_param = {.test_suffix = "CR2023_RTL",
+                          .use_right_to_left_language = true,
+                          .use_chrome_refresh_2023_style = true},
+     .profile_type_param = ProfileTypePixelTestParam::kRegular},
 };
+
 }  // namespace
 
 class ProfileMenuViewPixelTest
     : public ProfilesPixelTestBaseT<DialogBrowserTest>,
-      public testing::WithParamInterface<PixelTestParam> {
+      public testing::WithParamInterface<ProfileMenuViewPixelTestParam> {
  public:
   ProfileMenuViewPixelTest()
-      : ProfilesPixelTestBaseT<DialogBrowserTest>(GetParam()) {}
+      : ProfilesPixelTestBaseT<DialogBrowserTest>(GetParam().pixel_test_param) {
+  }
 
   ~ProfileMenuViewPixelTest() override = default;
 
+  ProfileTypePixelTestParam GetProfileType() const {
+    return GetParam().profile_type_param;
+  }
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // Enable the guest session.
+  void CreatedBrowserMainParts(
+      content::BrowserMainParts* browser_main_parts) override {
+    if (GetProfileType() != ProfileTypePixelTestParam::kDeviceGuestSession) {
+      return;
+    }
+    crosapi::mojom::BrowserInitParamsPtr init_params =
+        chromeos::BrowserInitParams::GetForTests()->Clone();
+
+    init_params->session_type = crosapi::mojom::SessionType::kGuestSession;
+    chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+    ProfilesPixelTestBaseT<DialogBrowserTest>::CreatedBrowserMainParts(
+        browser_main_parts);
+  }
+#endif
+
+  void SetUpOnMainThread() override {
+    ProfilesPixelTestBaseT<DialogBrowserTest>::SetUpOnMainThread();
+
+    // Configures the browser according to the profile type.
+    ui_test_utils::BrowserChangeObserver browser_added_observer(
+        nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
+    Browser* new_browser = nullptr;
+
+    switch (GetProfileType()) {
+      case ProfileTypePixelTestParam::kRegular:
+        // Nothing to do.
+        break;
+      case ProfileTypePixelTestParam::kIncognito:
+        CreateIncognitoBrowser();
+        new_browser = browser_added_observer.Wait();
+        ASSERT_TRUE(new_browser);
+        ASSERT_TRUE(new_browser->profile()->IsIncognitoProfile());
+        break;
+      case ProfileTypePixelTestParam::kGuest:
+        CreateGuestBrowser();
+        new_browser = browser_added_observer.Wait();
+        ASSERT_TRUE(new_browser);
+        ASSERT_TRUE(new_browser->profile()->IsGuestSession());
+        break;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+      case ProfileTypePixelTestParam::kDeviceGuestSession:
+        // Nothing to do, the current browser should already be guest.
+        ASSERT_TRUE(browser()->profile()->IsGuestSession());
+#endif
+    }
+
+    // Close the initial browser and set the new one as default.
+    if (new_browser) {
+      ASSERT_NE(new_browser, browser());
+      CloseBrowserSynchronously(browser());
+      SelectFirstBrowser();
+      ASSERT_EQ(new_browser, browser());
+    }
+  }
+
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
     CHECK(browser());
 
     views::NamedWidgetShownWaiter widget_waiter(
-        views::test::AnyWidgetTestPasskey{}, "ProfileMenuView");
+        views::test::AnyWidgetTestPasskey{}, "ProfileMenuViewBase");
 
     ASSERT_NO_FATAL_FAILURE(OpenProfileMenu());
 
diff --git a/chrome/browser/ui/webui/ash/login/testapi/oobe_test_api_handler.cc b/chrome/browser/ui/webui/ash/login/testapi/oobe_test_api_handler.cc
index f128885..6d2c478e 100644
--- a/chrome/browser/ui/webui/ash/login/testapi/oobe_test_api_handler.cc
+++ b/chrome/browser/ui/webui/ash/login/testapi/oobe_test_api_handler.cc
@@ -66,7 +66,6 @@
 void OobeTestAPIHandler::GetAdditionalParameters(base::Value::Dict* dict) {
   login::NetworkStateHelper helper_;
   dict->Set("testapi_shouldSkipNetworkFirstShow",
-            features::IsOobeNetworkScreenSkipEnabled() &&
                 !switches::IsOOBENetworkScreenSkippingDisabledForTesting() &&
                 helper_.IsConnectedToEthernet());
 
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
index 9d14def..4c7d453b 100644
--- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
+++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
@@ -73,7 +73,7 @@
 // static
 bool OfficeFallbackDialog::Show(
     const std::vector<storage::FileSystemURL>& file_urls,
-    const FallbackReason fallback_reason,
+    FallbackReason fallback_reason,
     const std::string& action_id,
     DialogChoiceCallback callback) {
   // Allow no more than one office fallback dialog at a time. In the case of
@@ -119,9 +119,9 @@
 
   // The pointer is managed by an instance of `views::WebDialogView` and removed
   // in `SystemWebDialogDelegate::OnDialogClosed`.
-  OfficeFallbackDialog* dialog =
-      new OfficeFallbackDialog(file_urls, title_text, reason_message,
-                               instructions_message, std::move(callback));
+  OfficeFallbackDialog* dialog = new OfficeFallbackDialog(
+      file_urls, fallback_reason, title_text, reason_message,
+      instructions_message, std::move(callback));
 
   dialog->ShowSystemDialog();
   return true;
@@ -131,15 +131,17 @@
   // Save callback as local variable before member variables are deleted during
   // dialog close.
   DialogChoiceCallback callback = std::move(callback_);
+  FallbackReason fallback_reason = fallback_reason_;
   // Delete class.
   SystemWebDialogDelegate::OnDialogClosed(choice);
   // Run callback after dialog closed.
   if (callback)
-    std::move(callback).Run(choice);
+    std::move(callback).Run(choice, fallback_reason);
 }
 
 OfficeFallbackDialog::OfficeFallbackDialog(
     const std::vector<storage::FileSystemURL>& file_urls,
+    FallbackReason fallback_reason,
     const std::string& title_text,
     const std::string& reason_message,
     const std::string& instructions_message,
@@ -147,6 +149,7 @@
     : SystemWebDialogDelegate(GURL(chrome::kChromeUIOfficeFallbackURL),
                               std::u16string() /* title */),
       file_urls_(file_urls),
+      fallback_reason_(fallback_reason),
       title_text_(title_text),
       reason_message_(reason_message),
       instructions_message_(instructions_message),
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
index 6192d92f..5f13e7ae 100644
--- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
+++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
@@ -12,15 +12,16 @@
 
 namespace ash::office_fallback {
 
-using DialogChoiceCallback =
-    base::OnceCallback<void(const std::string& choice)>;
-
 // The reason why the user's file can't open.
 enum class FallbackReason {
   kOffline,
   kDriveUnavailable,
 };
 
+using DialogChoiceCallback =
+    base::OnceCallback<void(const std::string& choice,
+                            FallbackReason fallback_reason)>;
+
 // Defines the web dialog used to allow users to choose what to do when failing
 // to open office files.
 class OfficeFallbackDialog : public SystemWebDialogDelegate {
@@ -31,7 +32,7 @@
   // Creates and shows the dialog. Returns true if a new dialog has been
   // effectively created.
   static bool Show(const std::vector<storage::FileSystemURL>& file_urls,
-                   const FallbackReason fallback_reason,
+                   FallbackReason fallback_reason,
                    const std::string& action_id,
                    DialogChoiceCallback callback);
 
@@ -42,6 +43,7 @@
 
  protected:
   OfficeFallbackDialog(const std::vector<storage::FileSystemURL>& file_urls,
+                       FallbackReason fallback_reason,
                        const std::string& title_text,
                        const std::string& reason_message,
                        const std::string& instructions_message,
@@ -52,6 +54,7 @@
 
  private:
   const std::vector<storage::FileSystemURL> file_urls_;
+  const FallbackReason fallback_reason_;
   const std::string title_text_;
   const std::string reason_message_;
   const std::string instructions_message_;
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.h b/chrome/browser/ui/webui/settings/site_settings_helper.h
index 9d883c74..591e039 100644
--- a/chrome/browser/ui/webui/settings/site_settings_helper.h
+++ b/chrome/browser/ui/webui/settings/site_settings_helper.h
@@ -89,7 +89,6 @@
 constexpr char kIsDirectory[] = "isDirectory";
 constexpr char kIsEmbargoed[] = "isEmbargoed";
 constexpr char kIsWritable[] = "isWritable";
-constexpr char kNotificationInfoString[] = "notificationInfoString";
 constexpr char kObject[] = "object";
 constexpr char kOpenDescription[] = "openDescription";
 constexpr char kOrigin[] = "origin";
diff --git a/chrome/browser/vr/win/graphics_delegate_win.cc b/chrome/browser/vr/win/graphics_delegate_win.cc
index 75df871..a905713 100644
--- a/chrome/browser/vr/win/graphics_delegate_win.cc
+++ b/chrome/browser/vr/win/graphics_delegate_win.cc
@@ -34,10 +34,10 @@
   attributes.bind_generates_resource = false;
 
   context_provider_ = base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-      host, factory->GetGpuMemoryBufferManager(), content::kGpuStreamIdDefault,
-      content::kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
-      GURL(std::string("chrome://gpu/VrUiWin")), false /* automatic flushes */,
-      false /* support locking */, false /* support grcontext */,
+      host, content::kGpuStreamIdDefault, content::kGpuStreamPriorityUI,
+      gpu::kNullSurfaceHandle, GURL(std::string("chrome://gpu/VrUiWin")),
+      false /* automatic flushes */, false /* support locking */,
+      false /* support grcontext */,
       gpu::SharedMemoryLimits::ForMailboxContext(), attributes,
       viz::command_buffer_metrics::ContextType::XR_COMPOSITING);
   gpu_memory_buffer_manager_ = factory->GetGpuMemoryBufferManager();
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 2a7ebf9..3160e7f1 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1692748490-c06965b816013a4530a30c49c3ef6541b61e2179.profdata
+chrome-android32-main-1693396730-19ca23531d7b5d225d8c7a649c169da2572a17ca.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 953d934..68dbf96 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1692748490-b387ab6f3f76466e74b286346b2717c68fd7add7.profdata
+chrome-android64-main-1693396730-a82e20c206cfb9ed6241dd1ae830a7d3f33ab016.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt
index ba902b8..dd22c6f 100644
--- a/chrome/build/lacros-arm64.pgo.txt
+++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-arm64-generic-main-1693353206-71c88a1e59cc64d963a00ba1fdc4797fa4216425.profdata
+chrome-chromeos-arm64-generic-main-1693396730-b785a92e8c568cb861b9acdf8b7aa894fead410a.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index bccbe42..99612b3 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1693354009-3ad814015f3a3c9e1777fa9ceb039343865e1864.profdata
+chrome-chromeos-amd64-generic-main-1693396730-287a6057b14809f74eae8055e9048e290acabcad.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 8fe3000..99eae4f 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1693375120-adeb8a12fc26528d5343b4199504ddf72998674d.profdata
+chrome-linux-main-1693396730-5fbf12cffc8cafd1217b6f5d4b9823ad00a8a7f1.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 9c6c8e4..46063354 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1693382295-54a3188dfca20de855f2f8df2b7e9d8982884f28.profdata
+chrome-mac-arm-main-1693403685-0d5b66a8137cb8e4db929db7dfc5a0ce53560237.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index accfa777..7856b182 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1693375120-fa7bc28f25cb6f9ba138dba532925e58fd8cdfea.profdata
+chrome-mac-main-1693396730-8037c6563cce3d2fa1c66e54bac1b9e2da698895.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 041b52f..1d6fe3d 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1693364180-bf28f3769ebcd4705ccd1c76c298c0cc84c0792a.profdata
+chrome-win32-main-1693385947-af3c05c2a466cef8ec7fb47cae6174e88c66ce50.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 1e7cee3f..6ce1da8 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1693364180-fa016dc0008e776ec45409b316b13f173e23ca86.profdata
+chrome-win64-main-1693396730-40a2f81c7608d933a778823a6e15acafed39fb31.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c24b68de7..7737eca 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4459,6 +4459,7 @@
         "../browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc",
         "../browser/ui/ash/shelf/app_service/app_service_promise_app_shelf_context_menu_browsertest.cc",
         "../browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc",
+        "../browser/ui/ash/shelf/app_service/app_service_shortcut_shelf_item_controller_browsertest.cc",
         "../browser/ui/ash/shelf/app_service/web_app_shelf_browsertest.cc",
         "../browser/ui/ash/shelf/app_shortcut_shelf_item_controller_browsertest.cc",
         "../browser/ui/ash/shelf/arc_app_shelf_browsertest.cc",
diff --git a/chrome/test/data/webui/settings/autofill_section_test.ts b/chrome/test/data/webui/settings/autofill_section_test.ts
index e0edded13..d692b80 100644
--- a/chrome/test/data/webui/settings/autofill_section_test.ts
+++ b/chrome/test/data/webui/settings/autofill_section_test.ts
@@ -192,7 +192,8 @@
 });
 
 suite('AutofillSectionFocusTest', function() {
-  test('verifyFocusLocationAfterRemoving', async () => {
+  // TODO(crbug.com/1473847): Fix the flakiness.
+  test.skip('verifyFocusLocationAfterRemoving', async () => {
     const section = await createAutofillSection(
         [
           createAddressEntry(),
@@ -547,7 +548,8 @@
         getAddressFieldValue(address, ServerFieldType.NAME_HONORIFIC_PREFIX));
   });
 
-  test('verifyPhoneAndEmailAreRemoved', function() {
+  // TODO(crbug.com/1473847): Fix the flakiness.
+  test.skip('verifyPhoneAndEmailAreRemoved', function() {
     const address = createEmptyAddressEntry();
 
     const phoneNumber = '(555) 555-5555';
@@ -695,7 +697,8 @@
     });
   });
 
-  test('verifySyncSourceNoticeForNewAddress', async () => {
+  // TODO(crbug.com/1473847): Fix the flakiness.
+  test.skip('verifySyncSourceNoticeForNewAddress', async () => {
     const section = await createAutofillSection([], {}, {
       email: 'stub-user@example.com',
       isSyncEnabledForAutofillProfiles: true,
diff --git a/chrome/test/data/webui/settings/safety_hub_page_test.ts b/chrome/test/data/webui/settings/safety_hub_page_test.ts
index fc6d92f6..e30beab 100644
--- a/chrome/test/data/webui/settings/safety_hub_page_test.ts
+++ b/chrome/test/data/webui/settings/safety_hub_page_test.ts
@@ -6,7 +6,7 @@
 import 'chrome://settings/lazy_load.js';
 
 import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
-import {ContentSettingsTypes, SafetyHubEvent, SettingsSafetyHubPageElement} from 'chrome://settings/lazy_load.js';
+import {CardInfo, CardState, ContentSettingsTypes, SafetyHubBrowserProxyImpl, SafetyHubEvent, SettingsSafetyHubPageElement} from 'chrome://settings/lazy_load.js';
 import {PasswordManagerImpl, PasswordManagerPage, Router, routes} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {isChildVisible} from 'chrome://webui-test/test_util.js';
@@ -27,10 +27,34 @@
     expiration: '13317004800000000',  // Represents 2023-01-01T00:00:00.
   }];
 
+  const passwordCardMockData: CardInfo = {
+    header: '2 compromised passwords',
+    subheader: 'You should change these now',
+    state: CardState.WARNING,
+  };
+
+  const versionCardMockData: CardInfo = {
+    header: 'Chrome is up to date',
+    subheader: 'Checked just now',
+    state: CardState.SAFE,
+  };
+
+  const safeBrowsingCardMockData: CardInfo = {
+    header: 'Safe Browsing is off',
+    subheader: 'An Extension turned off Safe Browsing',
+    state: CardState.INFO,
+  };
+
   setup(function() {
     safetyHubBrowserProxy = new TestSafetyHubBrowserProxy();
+    safetyHubBrowserProxy.setPasswordCardData(passwordCardMockData);
+    safetyHubBrowserProxy.setVersionCardData(versionCardMockData);
+    safetyHubBrowserProxy.setSafeBrowsingCardData(safeBrowsingCardMockData);
+    SafetyHubBrowserProxyImpl.setInstance(safetyHubBrowserProxy);
+
     passwordManagerProxy = new TestPasswordManagerProxy();
     PasswordManagerImpl.setInstance(passwordManagerProxy);
+
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
     testElement = document.createElement('settings-safety-hub-page');
     document.body.appendChild(testElement);
@@ -86,6 +110,20 @@
         testElement, 'settings-safety-hub-unused-site-permissions'));
   });
 
+  test('Password Card', async function() {
+    assertTrue(isChildVisible(testElement, '#passwords'));
+
+    // Card header and subheader should be what the browser proxy provides.
+    assertEquals(
+        testElement.$.passwords!.shadowRoot!.querySelector(
+                                                '#header')!.textContent!.trim(),
+        passwordCardMockData.header);
+    assertEquals(
+        testElement.$.passwords!.shadowRoot!.querySelector('#subheader')!
+            .textContent!.trim(),
+        passwordCardMockData.subheader);
+  });
+
   test('Password Card Clicked', async function() {
     testElement.$.passwords.click();
 
@@ -94,6 +132,20 @@
     assertEquals(PasswordManagerPage.CHECKUP, param);
   });
 
+  test('Version Card', async function() {
+    assertTrue(isChildVisible(testElement, '#version'));
+
+    // Card header and subheader should be what the browser proxy provides.
+    assertEquals(
+        testElement.$.version!.shadowRoot!.querySelector(
+                                              '#header')!.textContent!.trim(),
+        versionCardMockData.header);
+    assertEquals(
+        testElement.$.version!.shadowRoot!.querySelector('#subheader')!
+            .textContent!.trim(),
+        versionCardMockData.subheader);
+  });
+
   test('Version Card Clicked', function() {
     testElement.$.version.click();
 
@@ -101,6 +153,20 @@
     assertEquals(routes.ABOUT, Router.getInstance().getCurrentRoute());
   });
 
+  test('Safe Browsing Card', async function() {
+    assertTrue(isChildVisible(testElement, '#safeBrowsing'));
+
+    // Card header and subheader should be what the browser proxy provides.
+    assertEquals(
+        testElement.$.safeBrowsing!.shadowRoot!.querySelector('#header')!
+            .textContent!.trim(),
+        safeBrowsingCardMockData.header);
+    assertEquals(
+        testElement.$.safeBrowsing!.shadowRoot!.querySelector('#subheader')!
+            .textContent!.trim(),
+        safeBrowsingCardMockData.subheader);
+  });
+
   test('Safe Browsing Card Clicked', function() {
     testElement.$.safeBrowsing.click();
 
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index 74ba261..3d95638 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -64,8 +64,7 @@
   RunTest("settings/autofill_page_test.js", "mocha.run()");
 }
 
-// TODO(crbug.com/1473847): Flaky on many bots.
-IN_PROC_BROWSER_TEST_F(SettingsTest, DISABLED_AutofillSection) {
+IN_PROC_BROWSER_TEST_F(SettingsTest, AutofillSection) {
   RunTest("settings/autofill_section_test.js", "mocha.run()");
 }
 
diff --git a/chrome/test/data/webui/settings/test_safety_hub_browser_proxy.ts b/chrome/test/data/webui/settings/test_safety_hub_browser_proxy.ts
index e153a28..dc5fc8b 100644
--- a/chrome/test/data/webui/settings/test_safety_hub_browser_proxy.ts
+++ b/chrome/test/data/webui/settings/test_safety_hub_browser_proxy.ts
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 
 // clang-format off
-import {NotificationPermission, UnusedSitePermissions, SafetyHubBrowserProxy} from 'chrome://settings/lazy_load.js';
+import {CardInfo, CardState, NotificationPermission, SafetyHubBrowserProxy, UnusedSitePermissions} from 'chrome://settings/lazy_load.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 // clang-format on
 
@@ -15,8 +15,17 @@
  */
 export class TestSafetyHubBrowserProxy extends TestBrowserProxy implements
     SafetyHubBrowserProxy {
+  private dummyCardInfo: CardInfo = {
+    header: 'Dummy Header',
+    subheader: 'Dummy Subheader',
+    state: CardState.INFO,
+  };
+
   private unusedSitePermissions_: UnusedSitePermissions[] = [];
   private reviewNotificationList_: NotificationPermission[] = [];
+  private passwordCardData_: CardInfo = this.dummyCardInfo;
+  private safeBrowsingCardData_: CardInfo = this.dummyCardInfo;
+  private versionCardData_: CardInfo = this.dummyCardInfo;
 
   constructor() {
     super([
@@ -31,6 +40,9 @@
       'ignoreNotificationPermissionForOrigins',
       'undoIgnoreNotificationPermissionForOrigins',
       'resetNotificationPermissionForOrigins',
+      'getPasswordCardData',
+      'getSafeBrowsingCardData',
+      'getVersionCardData',
     ]);
   }
 
@@ -93,4 +105,31 @@
   resetNotificationPermissionForOrigins(origins: string[]): void {
     this.methodCalled('resetNotificationPermissionForOrigins', origins);
   }
+
+  getPasswordCardData(): Promise<CardInfo> {
+    this.methodCalled('getPasswordCardData');
+    return Promise.resolve(this.passwordCardData_);
+  }
+
+  setPasswordCardData(data: CardInfo): void {
+    this.passwordCardData_ = data;
+  }
+
+  getSafeBrowsingCardData(): Promise<CardInfo> {
+    this.methodCalled('getSafeBrowsingCardData');
+    return Promise.resolve(this.safeBrowsingCardData_);
+  }
+
+  setSafeBrowsingCardData(data: CardInfo): void {
+    this.safeBrowsingCardData_ = data;
+  }
+
+  getVersionCardData(): Promise<CardInfo> {
+    this.methodCalled('getVersionCardData');
+    return Promise.resolve(this.versionCardData_);
+  }
+
+  setVersionCardData(data: CardInfo): void {
+    this.versionCardData_ = data;
+  }
 }
diff --git a/chromeos/profiles/arm-exp.afdo.newest.txt b/chromeos/profiles/arm-exp.afdo.newest.txt
index 9f36892..b534c8c 100644
--- a/chromeos/profiles/arm-exp.afdo.newest.txt
+++ b/chromeos/profiles/arm-exp.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-exp-118-5938.22-1693215733-benchmark-118.0.5976.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-exp-118-5938.22-1693215733-benchmark-118.0.5978.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index 34abf35..a713085b 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-118-5938.13-1693222952-benchmark-118.0.5977.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-118-5938.13-1693222952-benchmark-118.0.5978.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index c8e8c6a33..12c0debc 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-118-5938.22-1693215733-benchmark-118.0.5976.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-118-5938.22-1693215733-benchmark-118.0.5978.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index ff0f22f..93fb6da 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-118-5938.13-1693220144-benchmark-118.0.5976.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-118-5938.13-1693220144-benchmark-118.0.5978.0-r1-redacted.afdo.xz
diff --git a/clank b/clank
index 5d6852a..a750aaa 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 5d6852ae1087957cdf63633e42a5ee9e0164cbfd
+Subproject commit a750aaa5d035918cb1e2c927521827a15c82c9c8
diff --git a/components/BUILD.gn b/components/BUILD.gn
index ea3ec6f..f3d560c 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -408,6 +408,8 @@
       "//components/value_store:unit_tests",
       "//components/visitedlink/test:unit_tests",
       "//components/web_cache/browser:unit_tests",
+      "//components/web_package:unit_tests",
+      "//components/web_package/test_support:unit_tests",
       "//components/webapps/services/web_app_origin_association:unit_tests",
       "//components/webauthn/json:unit_tests",
       "//components/webcrypto:unit_tests",
@@ -488,8 +490,6 @@
       "//components/spellcheck/browser:unit_tests",
       "//components/spellcheck/renderer:unit_tests",
       "//components/subresource_filter/content/browser:unit_tests",
-      "//components/web_package:unit_tests",
-      "//components/web_package/test_support:unit_tests",
       "//components/webapps/browser:unit_tests",
     ]
 
diff --git a/components/android_autofill/browser/autofill_provider.h b/components/android_autofill/browser/autofill_provider.h
index 9d287dac..e86a03a 100644
--- a/components/android_autofill/browser/autofill_provider.h
+++ b/components/android_autofill/browser/autofill_provider.h
@@ -103,8 +103,6 @@
   explicit AutofillProvider(content::WebContents* web_contents);
   friend class content::WebContentsUserData<AutofillProvider>;
 
-  content::WebContents* web_contents() { return &GetWebContents(); }
-
  private:
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 };
diff --git a/components/android_autofill/browser/autofill_provider_android.cc b/components/android_autofill/browser/autofill_provider_android.cc
index 8ba5330..c6fa1fb0 100644
--- a/components/android_autofill/browser/autofill_provider_android.cc
+++ b/components/android_autofill/browser/autofill_provider_android.cc
@@ -74,6 +74,7 @@
     const JavaRef<jobject>& jcaller,
     content::WebContents* web_contents)
     : AutofillProvider(web_contents),
+      content::WebContentsObserver(web_contents),
       java_ref_(JavaObjectWeakGlobalRef(env, jcaller)),
       check_submission_(false) {}
 
@@ -99,6 +100,26 @@
   java_ref_.reset();
 }
 
+void AutofillProviderAndroid::RenderFrameDeleted(
+    content::RenderFrameHost* rfh) {
+  // If the popup menu has been triggered from within an iframe and that frame
+  // is deleted, hide the popup. This is necessary because the popup may
+  // actually be shown by the AutofillExternalDelegate of an ancestor frame,
+  // which is not notified about `rfh`'s destruction and therefore won't close
+  // the popup.
+  if (manager_ &&
+      field_id_.frame_token == LocalFrameToken(rfh->GetFrameToken().value())) {
+    OnHidePopup(manager_.get());
+  }
+}
+
+void AutofillProviderAndroid::OnVisibilityChanged(
+    content::Visibility visibility) {
+  if (visibility == content::Visibility::HIDDEN && manager_) {
+    OnHidePopup(manager_.get());
+  }
+}
+
 void AutofillProviderAndroid::OnAskForValuesToFill(
     AndroidAutofillManager* manager,
     const FormData& form,
diff --git a/components/android_autofill/browser/autofill_provider_android.h b/components/android_autofill/browser/autofill_provider_android.h
index ba160f9..1eef119d 100644
--- a/components/android_autofill/browser/autofill_provider_android.h
+++ b/components/android_autofill/browser/autofill_provider_android.h
@@ -9,6 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/android_autofill/browser/autofill_provider.h"
 #include "components/autofill/core/common/unique_ids.h"
+#include "content/public/browser/web_contents_observer.h"
 
 namespace content {
 class WebContents;
@@ -21,7 +22,8 @@
 // Android implementation of AutofillProvider, it has one instance per
 // WebContents, this class is native peer of AutofillProvider.java.
 // This class is always instantialized by AutofillProvider Java object.
-class AutofillProviderAndroid : public AutofillProvider {
+class AutofillProviderAndroid : public AutofillProvider,
+                                content::WebContentsObserver {
  public:
   static AutofillProviderAndroid* Create(
       JNIEnv* env,
@@ -105,6 +107,10 @@
                           const base::android::JavaRef<jobject>& jcaller,
                           content::WebContents* web_contents);
 
+  // content::WebContentsObserver:
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void OnVisibilityChanged(content::Visibility visibility) override;
+
   void FireSuccessfulSubmission(mojom::SubmissionSource source);
   void OnFocusChanged(bool focus_on_form,
                       size_t index,
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc
index c13a237..b22c8ea 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -164,18 +164,6 @@
         render_frame_host->DocumentUsedWebOTP());
   }
 
-  // If the popup menu has been triggered from within an iframe and that
-  // frame is deleted, hide the popup. This is necessary because the popup
-  // may actually be shown by the AutofillExternalDelegate of an ancestor
-  // frame, which is not notified about |render_frame_host|'s destruction
-  // and therefore won't close the popup.
-  bool is_iframe = !driver->IsInAnyMainFrame();
-  if (is_iframe && router_.last_queried_source() == driver) {
-    DCHECK(!render_frame_host->IsInLifecycleState(
-        content::RenderFrameHost::LifecycleState::kPrerendering));
-    driver->renderer_events().HidePopup();
-  }
-
   for (Observer& observer : observers_) {
     observer.OnContentAutofillDriverWillBeDeleted(*this, *driver);
   }
@@ -245,13 +233,6 @@
   driver->Reset();
 }
 
-void ContentAutofillDriverFactory::OnVisibilityChanged(
-    content::Visibility visibility) {
-  if (visibility == content::Visibility::HIDDEN) {
-    client_->HideAutofillPopup(PopupHidingReason::kTabGone);
-  }
-}
-
 std::vector<ContentAutofillDriver*>
 ContentAutofillDriverFactory::GetExistingDrivers(
     base::PassKey<ScopedAutofillManagersObservation>) {
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h
index 2534f77..b74fca38 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -102,7 +102,6 @@
       content::NavigationHandle* navigation_handle) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
-  void OnVisibilityChanged(content::Visibility visibility) override;
 
   AutofillClient* client() { return client_; }
 
diff --git a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
index 725fdf7..8ad12eab 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
@@ -281,13 +281,6 @@
     EXPECT_EQ(test_api(*factory_).GetDriver(main_rfh()), main_driver);
 }
 
-// Tests that OnVisibilityChanged() hides the popup.
-TEST_F(ContentAutofillDriverFactoryTest, TabHidden) {
-  NavigateMainFrame("https://a.com/");
-  EXPECT_CALL(*client_, HideAutofillPopup(PopupHidingReason::kTabGone));
-  factory_->OnVisibilityChanged(content::Visibility::HIDDEN);
-}
-
 // Test case with one frame, with BFcache enabled or disabled depending on the
 // parameter.
 class ContentAutofillDriverFactoryTest_WithOrWithoutBfCacheAndIframes
diff --git a/components/autofill/content/browser/content_autofill_router.cc b/components/autofill/content/browser/content_autofill_router.cc
index 4d46e1b2..46c5bc2 100644
--- a/components/autofill/content/browser/content_autofill_router.cc
+++ b/components/autofill/content/browser/content_autofill_router.cc
@@ -59,21 +59,6 @@
       break;
     }
   }
-
-  if (last_queried_source_ == driver)
-    SetLastQueriedSource(nullptr);
-  if (last_queried_target_ == driver)
-    SetLastQueriedTarget(nullptr);
-}
-
-void ContentAutofillRouter::SetLastQueriedSource(
-    ContentAutofillDriver* source) {
-  last_queried_source_ = source;
-}
-
-void ContentAutofillRouter::SetLastQueriedTarget(
-    ContentAutofillDriver* target) {
-  last_queried_target_ = target;
 }
 
 // Routing of events called by the renderer:
@@ -287,8 +272,6 @@
   const FormData& browser_form = form_forest_.GetBrowserForm(form_id);
   auto* target = DriverOfFrame(browser_form.host_frame);
   CHECK(target);
-  SetLastQueriedSource(source);
-  SetLastQueriedTarget(target);
   callback(target, browser_form, field, bounding_box, trigger_source);
 }
 
@@ -364,9 +347,6 @@
 
   const FormData& browser_form = form_forest_.GetBrowserForm(form_id);
   auto* target = DriverOfFrame(browser_form.host_frame);
-  // Usually, `target == last_queried_target_`, but this is not guaranteed
-  // because ContentAutofillRouter may have learned about `form`'s parent form
-  // in between AskForValuesToFill() and DidFillAutofillFormData().
   CHECK(target);
   callback(target, browser_form, timestamp);
 }
diff --git a/components/autofill/content/browser/content_autofill_router.h b/components/autofill/content/browser/content_autofill_router.h
index e8319444..42c1b1a 100644
--- a/components/autofill/content/browser/content_autofill_router.h
+++ b/components/autofill/content/browser/content_autofill_router.h
@@ -150,15 +150,6 @@
   // the parent frame).
   void UnregisterDriver(ContentAutofillDriver* driver, bool driver_is_dying);
 
-  // Returns the ContentAutofillDriver* for which AskForValuesToFill() was
-  // called last.
-  // TODO(crbug.com/1224846) QueryFormFieldAutofill() was renamed to
-  // AskForValuesToFill(), so we should rename last_queried_source() and
-  // last_queried_source_ as well.
-  ContentAutofillDriver* last_queried_source() const {
-    return last_queried_source_;
-  }
-
   // Routing of events called by the renderer:
   void SetFormToBeProbablySubmitted(
       ContentAutofillDriver* source,
@@ -354,20 +345,9 @@
   // |form_forest_| except for |exception|.
   void TriggerFormExtractionExcept(ContentAutofillDriver* exception);
 
-  // Update the last queried and source and do cleanup work.
-  void SetLastQueriedSource(ContentAutofillDriver* source);
-  void SetLastQueriedTarget(ContentAutofillDriver* target);
-
   // The forest of forms. See its documentation for the usage protocol.
   internal::FormForest form_forest_;
 
-  // The driver that triggered the last AskForValuesToFill() call.
-  // Update with SetLastQueriedSource().
-  raw_ptr<ContentAutofillDriver> last_queried_source_ = nullptr;
-  // The driver to which the last AskForValuesToFill() call was routed.
-  // Update with SetLastQueriedTarget().
-  raw_ptr<ContentAutofillDriver> last_queried_target_ = nullptr;
-
   // When the focus moves to a different frame, the order of the events
   // FocusNoLongerOnForm() and FocusOnFormField() may be reversed due to race
   // conditions. We use these members to correct the order of the events.
diff --git a/components/autofill/content/browser/content_autofill_router_test_api.h b/components/autofill/content/browser/content_autofill_router_test_api.h
index 6c11acf..c137e1a 100644
--- a/components/autofill/content/browser/content_autofill_router_test_api.h
+++ b/components/autofill/content/browser/content_autofill_router_test_api.h
@@ -16,14 +16,6 @@
   explicit ContentAutofillRouterTestApi(ContentAutofillRouter* router)
       : router_(*router) {}
 
-  void set_last_queried_source(ContentAutofillDriver* driver) {
-    router_->last_queried_source_ = driver;
-  }
-
-  void set_last_queried_target(ContentAutofillDriver* driver) {
-    router_->last_queried_target_ = driver;
-  }
-
  private:
   const raw_ref<ContentAutofillRouter> router_;
 };
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc
index 0735b34d..de0e2f3 100644
--- a/components/autofill/core/browser/autofill_data_util.cc
+++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -280,13 +280,13 @@
     case autofill::FieldTypeGroup::kName:
       *group_bitmask |= kName;
       break;
-    case autofill::FieldTypeGroup::kAddressHome:
+    case autofill::FieldTypeGroup::kAddress:
       *group_bitmask |= kAddress;
       break;
     case autofill::FieldTypeGroup::kEmail:
       *group_bitmask |= kEmail;
       break;
-    case autofill::FieldTypeGroup::kPhoneHome:
+    case autofill::FieldTypeGroup::kPhone:
       *group_bitmask |= kPhone;
       break;
     default:
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc
index 6e51ad80..d564585 100644
--- a/components/autofill/core/browser/autofill_experiments.cc
+++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -148,6 +148,8 @@
     return false;
   }
 
+  // TODO(crbug.com/1462552): Simplify once IsSyncFeatureActive() is deleted
+  // from the codebase.
   if (sync_service->IsSyncFeatureActive()) {
     if (!sync_service->GetActiveDataTypes().Has(syncer::AUTOFILL_PROFILE)) {
       // In full sync mode, we only allow card upload when addresses are also
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
index 779e006..3ab0d1b6 100644
--- a/components/autofill/core/browser/autofill_field.cc
+++ b/components/autofill/core/browser/autofill_field.cc
@@ -384,14 +384,9 @@
 AutofillType AutofillField::ComputedType() const {
   // If autocomplete=tel/tel-* and server confirms it really is a phone field,
   // we always use the server prediction as html types are not very reliable.
-  if ((GroupTypeOfHtmlFieldType(html_type_, html_mode_) ==
-           FieldTypeGroup::kPhoneBilling ||
-       GroupTypeOfHtmlFieldType(html_type_, html_mode_) ==
-           FieldTypeGroup::kPhoneHome) &&
-      (GroupTypeOfServerFieldType(server_type()) ==
-           FieldTypeGroup::kPhoneBilling ||
-       GroupTypeOfServerFieldType(server_type()) ==
-           FieldTypeGroup::kPhoneHome)) {
+  if (GroupTypeOfHtmlFieldType(html_type_, html_mode_) ==
+          FieldTypeGroup::kPhone &&
+      GroupTypeOfServerFieldType(server_type()) == FieldTypeGroup::kPhone) {
     return AutofillType(server_type());
   }
 
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc
index f4fee44..de5e4f8 100644
--- a/components/autofill/core/browser/autofill_suggestion_generator.cc
+++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -127,7 +127,7 @@
       field_type, field.value, field.is_autofilled, field_types);
 
   // Adjust phone number to display in prefix/suffix case.
-  if (field_type.group() == FieldTypeGroup::kPhoneHome) {
+  if (field_type.group() == FieldTypeGroup::kPhone) {
     for (auto& suggestion : suggestions) {
       const AutofillProfile* profile = personal_data_->GetProfileByGUID(
           suggestion.GetPayload<Suggestion::BackendId>().value());
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index a61614f..11dd7a0 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -45,7 +45,7 @@
     case PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX:
     case PHONE_HOME_WHOLE_NUMBER:
     case PHONE_HOME_EXTENSION:
-      return FieldTypeGroup::kPhoneHome;
+      return FieldTypeGroup::kPhone;
 
     case ADDRESS_HOME_LINE1:
     case ADDRESS_HOME_LINE2:
@@ -78,7 +78,7 @@
     case ADDRESS_HOME_OVERFLOW_AND_LANDMARK:
     case ADDRESS_HOME_BETWEEN_STREETS_OR_LANDMARK:
     case DELIVERY_INSTRUCTIONS:
-      return FieldTypeGroup::kAddressHome;
+      return FieldTypeGroup::kAddress;
 
     case CREDIT_CARD_NAME_FULL:
     case CREDIT_CARD_NAME_FIRST:
@@ -154,9 +154,7 @@
     case HtmlFieldType::kAdditionalName:
     case HtmlFieldType::kAdditionalNameInitial:
     case HtmlFieldType::kFamilyName:
-      return field_mode == HtmlFieldMode::kBilling
-                 ? FieldTypeGroup::kNameBilling
-                 : FieldTypeGroup::kName;
+      return FieldTypeGroup::kName;
 
     case HtmlFieldType::kOrganization:
       return FieldTypeGroup::kCompany;
@@ -172,9 +170,7 @@
     case HtmlFieldType::kCountryName:
     case HtmlFieldType::kPostalCode:
     case HtmlFieldType::kFullAddress:
-      return field_mode == HtmlFieldMode::kBilling
-                 ? FieldTypeGroup::kAddressBilling
-                 : FieldTypeGroup::kAddressHome;
+      return FieldTypeGroup::kAddress;
 
     case HtmlFieldType::kCreditCardNameFull:
     case HtmlFieldType::kCreditCardNameFirst:
@@ -203,9 +199,7 @@
     case HtmlFieldType::kTelLocalPrefix:
     case HtmlFieldType::kTelLocalSuffix:
     case HtmlFieldType::kTelExtension:
-      return field_mode == HtmlFieldMode::kBilling
-                 ? FieldTypeGroup::kPhoneBilling
-                 : FieldTypeGroup::kPhoneHome;
+      return FieldTypeGroup::kPhone;
 
     case HtmlFieldType::kEmail:
       return FieldTypeGroup::kEmail;
diff --git a/components/autofill/core/browser/autofill_type_unittest.cc b/components/autofill/core/browser/autofill_type_unittest.cc
index dbe1eb8..ca68410 100644
--- a/components/autofill/core/browser/autofill_type_unittest.cc
+++ b/components/autofill/core/browser/autofill_type_unittest.cc
@@ -68,7 +68,7 @@
   // Type with group and subgroup.
   AutofillType phone(PHONE_HOME_NUMBER);
   EXPECT_EQ(PHONE_HOME_NUMBER, phone.GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kPhoneHome, phone.group());
+  EXPECT_EQ(FieldTypeGroup::kPhone, phone.group());
 
   // Boundary (error) condition.
   AutofillType boundary(MAX_VALID_FIELD_TYPE);
@@ -100,7 +100,7 @@
   // Type with group and subgroup.
   AutofillType phone(HtmlFieldType::kTel, HtmlFieldMode::kNone);
   EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER, phone.GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kPhoneHome, phone.group());
+  EXPECT_EQ(FieldTypeGroup::kPhone, phone.group());
 
   // Last value, to check any offset errors.
   AutofillType last(HtmlFieldType::kCreditCardExp4DigitYear,
@@ -118,7 +118,48 @@
   AutofillType billing_first(HtmlFieldType::kGivenName,
                              HtmlFieldMode::kBilling);
   EXPECT_EQ(NAME_FIRST, billing_first.GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kNameBilling, billing_first.group());
+  EXPECT_EQ(FieldTypeGroup::kName, billing_first.group());
+}
+
+class AutofillTypeTestForHtmlFieldTypes
+    : public ::testing::TestWithParam<
+          std::tuple<std::underlying_type_t<HtmlFieldType>,
+                     std::underlying_type_t<HtmlFieldMode>>> {
+ public:
+  HtmlFieldType html_field_type() const {
+    return static_cast<HtmlFieldType>(std::get<0>(GetParam()));
+  }
+
+  HtmlFieldMode html_field_mode() const {
+    return static_cast<HtmlFieldMode>(std::get<1>(GetParam()));
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    AutofillTypeTest,
+    AutofillTypeTestForHtmlFieldTypes,
+    testing::Combine(
+        testing::Range(base::to_underlying(HtmlFieldType::kMinValue),
+                       base::to_underlying(HtmlFieldType::kMaxValue)),
+        testing::Range(base::to_underlying(HtmlFieldMode::kMinValue),
+                       base::to_underlying(HtmlFieldMode::kMaxValue))));
+
+TEST_P(AutofillTypeTestForHtmlFieldTypes, GroupsOfHtmlFieldTypes) {
+  // Some HtmlFieldTypes have no ServerFieldType representation.
+  if (html_field_type() == HtmlFieldType::kFullAddress ||
+      html_field_type() == HtmlFieldType::kOneTimeCode ||
+      html_field_type() == HtmlFieldType::kTransactionAmount ||
+      html_field_type() == HtmlFieldType::kTransactionCurrency) {
+    return;
+  }
+  AutofillType t(html_field_type(), html_field_mode());
+  SCOPED_TRACE(testing::Message()
+               << "html_field_type="
+               << FieldTypeToStringPiece(html_field_type()) << " "
+               << "html_field_mode="
+               << HtmlFieldModeToStringPiece(html_field_mode()) << " "
+               << "field_type=" << FieldTypeToStringPiece(t.GetStorableType()));
+  EXPECT_EQ(t.group(), GroupTypeOfServerFieldType(t.GetStorableType()));
 }
 
 }  // namespace
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
index b4a066d2..4ce2f12 100644
--- a/components/autofill/core/browser/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -174,7 +174,6 @@
 // Returns whether the |field| is predicted as being any kind of name.
 bool IsNameType(const AutofillField& field) {
   return field.Type().group() == FieldTypeGroup::kName ||
-         field.Type().group() == FieldTypeGroup::kNameBilling ||
          field.Type().GetStorableType() == CREDIT_CARD_NAME_FULL ||
          field.Type().GetStorableType() == CREDIT_CARD_NAME_FIRST ||
          field.Type().GetStorableType() == CREDIT_CARD_NAME_LAST;
@@ -666,16 +665,13 @@
     case FieldTypeGroup::kIban:
       return PopupType::kIbans;
 
-    case FieldTypeGroup::kAddressHome:
-    case FieldTypeGroup::kAddressBilling:
+    case FieldTypeGroup::kAddress:
       return PopupType::kAddresses;
 
     case FieldTypeGroup::kName:
-    case FieldTypeGroup::kNameBilling:
     case FieldTypeGroup::kEmail:
     case FieldTypeGroup::kCompany:
-    case FieldTypeGroup::kPhoneHome:
-    case FieldTypeGroup::kPhoneBilling:
+    case FieldTypeGroup::kPhone:
     case FieldTypeGroup::kBirthdateField:
       return FormHasAddressField(form) ? PopupType::kAddresses
                                        : PopupType::kPersonalInformation;
@@ -2769,8 +2765,7 @@
   for (const FormFieldData& field : form.fields) {
     const AutofillField* autofill_field = GetAutofillField(form, field);
     if (autofill_field &&
-        (autofill_field->Type().group() == FieldTypeGroup::kAddressHome ||
-         autofill_field->Type().group() == FieldTypeGroup::kAddressBilling)) {
+        autofill_field->Type().group() == FieldTypeGroup::kAddress) {
       return true;
     }
   }
diff --git a/components/autofill/core/browser/data_model/address.cc b/components/autofill/core/browser/data_model/address.cc
index 81338bf..a08d266 100644
--- a/components/autofill/core/browser/data_model/address.cc
+++ b/components/autofill/core/browser/data_model/address.cc
@@ -90,7 +90,7 @@
 }
 
 std::u16string Address::GetRawInfo(ServerFieldType type) const {
-  DCHECK_EQ(FieldTypeGroup::kAddressHome, AutofillType(type).group());
+  DCHECK_EQ(FieldTypeGroup::kAddress, AutofillType(type).group());
 
   return structured_address_->GetValueForType(type);
 }
@@ -98,7 +98,7 @@
 void Address::SetRawInfoWithVerificationStatus(ServerFieldType type,
                                                const std::u16string& value,
                                                VerificationStatus status) {
-  DCHECK_EQ(FieldTypeGroup::kAddressHome, AutofillType(type).group());
+  DCHECK_EQ(FieldTypeGroup::kAddress, AutofillType(type).group());
   // The street address has a structure that may have already been set before
   // using the settings dialog. In case the settings dialog was used to change
   // the address to contain different tokens, the structure must be reset.
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc
index fea86c7..98a256f 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -88,8 +88,9 @@
   if (AutofillType(storable_type).group() == FieldTypeGroup::kName)
     return NAME_FULL;
 
-  if (AutofillType(storable_type).group() == FieldTypeGroup::kPhoneHome)
+  if (AutofillType(storable_type).group() == FieldTypeGroup::kPhone) {
     return PHONE_HOME_WHOLE_NUMBER;
+  }
 
   return storable_type;
 }
@@ -662,7 +663,7 @@
         // conditions that follow.
         return false;
       }
-    } else if (AutofillType(type).group() == FieldTypeGroup::kPhoneHome) {
+    } else if (AutofillType(type).group() == FieldTypeGroup::kPhone) {
       // Phone numbers should be canonicalized before comparing.
       if (type != PHONE_HOME_WHOLE_NUMBER &&
           type != PHONE_HOME_CITY_AND_NUMBER) {
@@ -1162,7 +1163,6 @@
 FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
   switch (type.group()) {
     case FieldTypeGroup::kName:
-    case FieldTypeGroup::kNameBilling:
       return &name_;
 
     case FieldTypeGroup::kEmail:
@@ -1171,12 +1171,10 @@
     case FieldTypeGroup::kCompany:
       return &company_;
 
-    case FieldTypeGroup::kPhoneHome:
-    case FieldTypeGroup::kPhoneBilling:
+    case FieldTypeGroup::kPhone:
       return &phone_number_;
 
-    case FieldTypeGroup::kAddressHome:
-    case FieldTypeGroup::kAddressBilling:
+    case FieldTypeGroup::kAddress:
       return &address_;
 
     case FieldTypeGroup::kBirthdateField:
diff --git a/components/autofill/core/browser/data_model/phone_number.cc b/components/autofill/core/browser/data_model/phone_number.cc
index c8ac133..97fed152 100644
--- a/components/autofill/core/browser/data_model/phone_number.cc
+++ b/components/autofill/core/browser/data_model/phone_number.cc
@@ -82,7 +82,7 @@
 }
 
 std::u16string PhoneNumber::GetRawInfo(ServerFieldType type) const {
-  DCHECK_EQ(FieldTypeGroup::kPhoneHome, AutofillType(type).group());
+  DCHECK_EQ(FieldTypeGroup::kPhone, AutofillType(type).group());
   if (type == PHONE_HOME_WHOLE_NUMBER)
     return number_;
 
@@ -95,7 +95,7 @@
 void PhoneNumber::SetRawInfoWithVerificationStatus(ServerFieldType type,
                                                    const std::u16string& value,
                                                    VerificationStatus status) {
-  DCHECK_EQ(FieldTypeGroup::kPhoneHome, AutofillType(type).group());
+  DCHECK_EQ(FieldTypeGroup::kPhone, AutofillType(type).group());
   if (type != PHONE_HOME_CITY_AND_NUMBER && type != PHONE_HOME_WHOLE_NUMBER) {
     // Only full phone numbers should be set directly. The remaining field types
     // are read-only. As PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX
diff --git a/components/autofill/core/browser/field_filler.cc b/components/autofill/core/browser/field_filler.cc
index 1bab803..6fee3c17 100644
--- a/components/autofill/core/browser/field_filler.cc
+++ b/components/autofill/core/browser/field_filler.cc
@@ -938,7 +938,7 @@
   const AutofillType type = field.Type();
   std::u16string value = profile.GetInfo(type, app_locale);
 
-  if (type.group() == FieldTypeGroup::kPhoneHome) {
+  if (type.group() == FieldTypeGroup::kPhone) {
     // If the `field_data` is a selection box and having the type
     // `PHONE_HOME_COUNTRY_CODE`, call
     // `GetPhoneCountryCodeSelectControlForInput`.
diff --git a/components/autofill/core/browser/field_filler_unittest.cc b/components/autofill/core/browser/field_filler_unittest.cc
index 0cbcbfd2..bb661c6 100644
--- a/components/autofill/core/browser/field_filler_unittest.cc
+++ b/components/autofill/core/browser/field_filler_unittest.cc
@@ -176,18 +176,18 @@
   field.set_server_predictions(
       {::autofill::test::CreateFieldPrediction(ADDRESS_HOME_LINE1)});
   EXPECT_EQ(ADDRESS_HOME_LINE1, field.Type().GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kAddressHome, field.Type().group());
+  EXPECT_EQ(FieldTypeGroup::kAddress, field.Type().group());
 
   // Checks that overall_type trumps everything.
   field.SetTypeTo(AutofillType(ADDRESS_HOME_ZIP));
   EXPECT_EQ(ADDRESS_HOME_ZIP, field.Type().GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kAddressHome, field.Type().group());
+  EXPECT_EQ(FieldTypeGroup::kAddress, field.Type().group());
 
   // Checks that setting server type resets overall type.
   field.set_server_predictions(
       {::autofill::test::CreateFieldPrediction(ADDRESS_HOME_LINE1)});
   EXPECT_EQ(ADDRESS_HOME_LINE1, field.Type().GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kAddressHome, field.Type().group());
+  EXPECT_EQ(FieldTypeGroup::kAddress, field.Type().group());
 
   // Remove the server type to make sure the heuristic type is preserved.
   field.set_server_predictions(
@@ -198,7 +198,7 @@
   // Checks that overall_type trumps everything.
   field.SetTypeTo(AutofillType(ADDRESS_HOME_ZIP));
   EXPECT_EQ(ADDRESS_HOME_ZIP, field.Type().GetStorableType());
-  EXPECT_EQ(FieldTypeGroup::kAddressHome, field.Type().group());
+  EXPECT_EQ(FieldTypeGroup::kAddress, field.Type().group());
 
   // Set the heuristic type and check it and reset overall Type.
   field.set_heuristic_type(GetActivePatternSource(), NAME_FIRST);
diff --git a/components/autofill/core/browser/field_type_utils.cc b/components/autofill/core/browser/field_type_utils.cc
index 5177894b..0b7512b 100644
--- a/components/autofill/core/browser/field_type_utils.cc
+++ b/components/autofill/core/browser/field_type_utils.cc
@@ -46,13 +46,10 @@
 bool IsAddressType(const AutofillType& type) {
   switch (type.group()) {
     case FieldTypeGroup::kName:
-    case FieldTypeGroup::kNameBilling:
     case FieldTypeGroup::kEmail:
     case FieldTypeGroup::kCompany:
-    case FieldTypeGroup::kAddressHome:
-    case FieldTypeGroup::kAddressBilling:
-    case FieldTypeGroup::kPhoneHome:
-    case FieldTypeGroup::kPhoneBilling:
+    case FieldTypeGroup::kAddress:
+    case FieldTypeGroup::kPhone:
     case FieldTypeGroup::kBirthdateField:
       return true;
     case FieldTypeGroup::kNoGroup:
diff --git a/components/autofill/core/browser/field_type_utils_unittest.cc b/components/autofill/core/browser/field_type_utils_unittest.cc
index bd7d5ee5..e01da17 100644
--- a/components/autofill/core/browser/field_type_utils_unittest.cc
+++ b/components/autofill/core/browser/field_type_utils_unittest.cc
@@ -23,12 +23,11 @@
       NumberOfPossibleFieldTypesInGroup(field, FieldTypeGroup::kCreditCard),
       1U);
 
-  EXPECT_EQ(
-      NumberOfPossibleFieldTypesInGroup(field, FieldTypeGroup::kAddressHome),
-      0U);
+  EXPECT_EQ(NumberOfPossibleFieldTypesInGroup(field, FieldTypeGroup::kAddress),
+            0U);
 
-  EXPECT_EQ(
-      NumberOfPossibleFieldTypesInGroup(field, FieldTypeGroup::kPhoneHome), 0U);
+  EXPECT_EQ(NumberOfPossibleFieldTypesInGroup(field, FieldTypeGroup::kPhone),
+            0U);
 }
 
 TEST(AutofillFieldTypeUtils, FieldHasMeaningfulFieldTypes) {
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h
index be7b8e8..d117056 100644
--- a/components/autofill/core/browser/field_types.h
+++ b/components/autofill/core/browser/field_types.h
@@ -426,13 +426,10 @@
 enum class FieldTypeGroup {
   kNoGroup,
   kName,
-  kNameBilling,
   kEmail,
   kCompany,
-  kAddressHome,
-  kAddressBilling,
-  kPhoneHome,
-  kPhoneBilling,
+  kAddress,
+  kPhone,
   kCreditCard,
   kPasswordField,
   kTransaction,
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index 940a71a..c4eb302 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -75,8 +75,7 @@
   if (types_seen.count(field_type) && field_type != EMAIL_ADDRESS &&
       (!base::FeatureList::IsEnabled(
            features::kAutofillEnableImportWhenMultiplePhoneNumbers) ||
-       (field_type_group != FieldTypeGroup::kPhoneBilling &&
-        field_type_group != FieldTypeGroup::kPhoneHome))) {
+       field_type_group != FieldTypeGroup::kPhone)) {
     LOG_AF(import_log_buffer)
         << LogMessage::kImportAddressProfileFromFormFailed
         << "Multiple fields of type "
@@ -523,8 +522,7 @@
 
     // Found phone number component field.
     // TODO(crbug.com/1156315) Remove feature check when launched.
-    if ((field_type.group() == FieldTypeGroup::kPhoneBilling ||
-         field_type.group() == FieldTypeGroup::kPhoneHome) &&
+    if (field_type.group() == FieldTypeGroup::kPhone &&
         base::FeatureList::IsEnabled(
             features::kAutofillEnableImportWhenMultiplePhoneNumbers)) {
       if (ignore_phone_number_fields)
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 6ad0be9..a6aa147 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -1466,8 +1466,9 @@
     // Forms often ask for multiple phone numbers -- e.g. both a daytime and
     // evening phone number.  Our phone number detection is also generally a
     // little off.  Hence, ignore this field type as a signal here.
-    if (AutofillType(current_type).group() == FieldTypeGroup::kPhoneHome)
+    if (AutofillType(current_type).group() == FieldTypeGroup::kPhone) {
       already_saw_current_type = false;
+    }
 
     bool ignored_field = !field->IsFocusable();
 
@@ -1625,8 +1626,9 @@
       // Forms often ask for multiple phone numbers -- e.g. both a daytime and
       // evening phone number.  Our phone number detection is also generally a
       // little off.  Hence, ignore this field type as a signal here.
-      if (AutofillType(current_type).group() == FieldTypeGroup::kPhoneHome)
+      if (AutofillType(current_type).group() == FieldTypeGroup::kPhone) {
         already_saw_current_type = false;
+      }
 
       bool ignored_field = !field->IsFocusable();
 
diff --git a/components/autofill/core/browser/form_structure_rationalizer.cc b/components/autofill/core/browser/form_structure_rationalizer.cc
index 95f6814f..f63baed 100644
--- a/components/autofill/core/browser/form_structure_rationalizer.cc
+++ b/components/autofill/core/browser/form_structure_rationalizer.cc
@@ -770,7 +770,7 @@
   for (int field_index = upper_index - 1; field_index >= 0; --field_index) {
     if ((*fields_)[field_index]->IsFocusable() &&
         AutofillType((*fields_)[field_index]->Type().GetStorableType())
-                .group() == FieldTypeGroup::kAddressHome &&
+                .group() == FieldTypeGroup::kAddress &&
         (*fields_)[field_index]->section == (*fields_)[upper_index]->section) {
       return false;
     }
diff --git a/components/autofill/core/browser/form_structure_sectioning_util.cc b/components/autofill/core/browser/form_structure_sectioning_util.cc
index 5163df9f..63ee92bb 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util.cc
+++ b/components/autofill/core/browser/form_structure_sectioning_util.cc
@@ -145,8 +145,9 @@
   // There are many phone number field types and their classification is
   // generally a little bit off. Furthermore, forms often ask for multiple phone
   // numbers, e.g. both a daytime and evening phone number.
-  if (AutofillType(current_type).group() == FieldTypeGroup::kPhoneHome)
+  if (AutofillType(current_type).group() == FieldTypeGroup::kPhone) {
     return true;
+  }
 
   return !HaveSeenSimilarType(current_type, seen_types);
 }
diff --git a/components/autofill/core/browser/form_types.cc b/components/autofill/core/browser/form_types.cc
index f1a401f..f4cd733 100644
--- a/components/autofill/core/browser/form_types.cc
+++ b/components/autofill/core/browser/form_types.cc
@@ -13,13 +13,10 @@
 FormType FieldTypeGroupToFormType(FieldTypeGroup field_type_group) {
   switch (field_type_group) {
     case FieldTypeGroup::kName:
-    case FieldTypeGroup::kNameBilling:
     case FieldTypeGroup::kEmail:
     case FieldTypeGroup::kCompany:
-    case FieldTypeGroup::kAddressHome:
-    case FieldTypeGroup::kAddressBilling:
-    case FieldTypeGroup::kPhoneHome:
-    case FieldTypeGroup::kPhoneBilling:
+    case FieldTypeGroup::kAddress:
+    case FieldTypeGroup::kPhone:
     case FieldTypeGroup::kBirthdateField:
       return FormType::kAddressForm;
     case FieldTypeGroup::kCreditCard:
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index 06b4df3..b963ce5 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -170,7 +170,6 @@
       break;
 
     case FieldTypeGroup::kName:
-    case FieldTypeGroup::kNameBilling:
       group = GROUP_NAME;
       break;
 
@@ -182,8 +181,7 @@
       group = GROUP_IBAN;
       break;
 
-    case FieldTypeGroup::kAddressHome:
-    case FieldTypeGroup::kAddressBilling:
+    case FieldTypeGroup::kAddress:
       switch (AutofillType(field_type).GetStorableType()) {
         case ADDRESS_HOME_LINE1:
           group = GROUP_ADDRESS_LINE_1;
@@ -351,8 +349,7 @@
       group = GROUP_EMAIL;
       break;
 
-    case FieldTypeGroup::kPhoneHome:
-    case FieldTypeGroup::kPhoneBilling:
+    case FieldTypeGroup::kPhone:
       group = GROUP_PHONE;
       break;
 
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
index a2e3722..1f524900 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -672,7 +672,7 @@
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldSignatureName,
          field_signature[0].value()},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::
              kFieldOverallTypeName,
          ADDRESS_HOME_LINE1},
@@ -691,7 +691,7 @@
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldSignatureName,
          field_signature[1].value()},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::
              kFieldOverallTypeName,
          ADDRESS_HOME_CITY},
@@ -710,7 +710,7 @@
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldSignatureName,
          field_signature[2].value()},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::
              kFieldOverallTypeName,
          ADDRESS_HOME_STATE},
@@ -729,7 +729,7 @@
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldSignatureName,
          field_signature[3].value()},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogHiddenRepresentationalFieldSkipDecisionType::
              kFieldOverallTypeName,
          ADDRESS_HOME_COUNTRY},
@@ -806,7 +806,7 @@
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldSignatureName,
          field_signature[0].value()},
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogRepeatedServerTypePredictionRationalized::
              kFieldOldOverallTypeName,
          ADDRESS_HOME_STREET_ADDRESS},
@@ -826,7 +826,7 @@
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldSignatureName,
          field_signature[1].value()},
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogRepeatedServerTypePredictionRationalized::
              kFieldOldOverallTypeName,
          ADDRESS_HOME_STREET_ADDRESS},
@@ -915,7 +915,7 @@
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldSignatureName,
          field_signature[0].value()},
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogRepeatedServerTypePredictionRationalized::
              kFieldOldOverallTypeName,
          ADDRESS_HOME_COUNTRY},
@@ -935,7 +935,7 @@
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldSignatureName,
          field_signature[1].value()},
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogRepeatedServerTypePredictionRationalized::
              kFieldOldOverallTypeName,
          ADDRESS_HOME_COUNTRY},
@@ -955,7 +955,7 @@
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldSignatureName,
          field_signature[2].value()},
         {UkmLogRepeatedServerTypePredictionRationalized::kFieldTypeGroupName,
-         static_cast<int64_t>(FieldTypeGroup::kAddressHome)},
+         static_cast<int64_t>(FieldTypeGroup::kAddress)},
         {UkmLogRepeatedServerTypePredictionRationalized::
              kFieldOldOverallTypeName,
          ADDRESS_HOME_COUNTRY},
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 40e4b53d..3959bd7 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -1247,12 +1247,6 @@
   database_helper_->GetLocalDatabase()->ClearAllLocalData();
   local_credit_cards_.clear();
   synced_local_profiles_.clear();
-  // Even though `account_profiles_` are not "local", the local/server
-  // distinction in the PersonalDataManager only exists for historical reasons
-  // and all AutofillProfiles fall in the local category.
-  // TODO(crbug.com/1475277): This call needs to be removed since account
-  // profiles are not cleared in the database.
-  account_profiles_.clear();
 }
 
 void PersonalDataManager::AddServerCreditCardForTest(
@@ -1666,9 +1660,8 @@
   auto is_field_type_profile_related = [](ServerFieldType type) {
     FieldTypeGroup group = AutofillType(type).group();
     return group == FieldTypeGroup::kName ||
-           group == FieldTypeGroup::kAddressHome ||
-           group == FieldTypeGroup::kPhoneHome ||
-           group == FieldTypeGroup::kEmail;
+           group == FieldTypeGroup::kAddress ||
+           group == FieldTypeGroup::kPhone || group == FieldTypeGroup::kEmail;
   };
   if (base::ranges::count_if(field_types, is_field_type_profile_related) > 1) {
     for (auto& suggestion : unique_suggestions) {
diff --git a/components/autofill/core/browser/test_autofill_manager_waiter.cc b/components/autofill/core/browser/test_autofill_manager_waiter.cc
index f6613db..6c94b383 100644
--- a/components/autofill/core/browser/test_autofill_manager_waiter.cc
+++ b/components/autofill/core/browser/test_autofill_manager_waiter.cc
@@ -4,8 +4,9 @@
 
 #include "components/autofill/core/browser/test_autofill_manager_waiter.h"
 
+#include <vector>
+
 #include "base/check_op.h"
-#include "base/containers/contains.h"
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
 #include "base/strings/string_util.h"
diff --git a/components/autofill/core/browser/test_autofill_manager_waiter.h b/components/autofill/core/browser/test_autofill_manager_waiter.h
index d86d032e..8e37aa2 100644
--- a/components/autofill/core/browser/test_autofill_manager_waiter.h
+++ b/components/autofill/core/browser/test_autofill_manager_waiter.h
@@ -7,18 +7,18 @@
 
 #include <map>
 #include <memory>
-#include <vector>
 
 #include "base/containers/span.h"
 #include "base/location.h"
 #include "base/run_loop.h"
 #include "base/scoped_observation.h"
 #include "base/synchronization/lock.h"
+#include "base/test/scoped_run_loop_timeout.h"
 #include "base/time/time.h"
-#include "base/types/cxx23_to_underlying.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/common/dense_set.h"
 #include "components/autofill/core/common/unique_ids.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
@@ -217,6 +217,218 @@
     base::RepeatingCallback<bool(const FormStructure&)> pred,
     base::TimeDelta timeout = base::Seconds(30));
 
+namespace internal {
+
+// Observes a single event and quits a base::RunLoop on the first event that
+// matches a given predicate.
+//
+// Helper class for WaitForEvent().
+//
+// For every AutofillManager::Observer::OnFoo(Args... args) event, this class
+// should have an override of the form
+//
+//   void OnFoo(Args... args) {
+//     MaybeQuit(&Observer::OnFoo, args...);
+//   }
+template <typename... Args>
+class AutofillManagerSingleEventWaiter : public AutofillManager::Observer {
+ public:
+  using Event = void (Observer::*)(Args...);
+
+  explicit AutofillManagerSingleEventWaiter(
+      AutofillManager& manager,
+      Event event,
+      testing::Matcher<std::tuple<Args...>> matcher)
+      : event_(std::forward<Event>(event)), matcher_(matcher) {
+    observation_.Observe(&manager);
+  }
+
+  ~AutofillManagerSingleEventWaiter() override = default;
+
+  testing::AssertionResult Wait(base::TimeDelta timeout,
+                                const base::Location& location) && {
+    bool timed_out = false;
+    base::test::ScopedRunLoopTimeout run_loop_timeout(
+        FROM_HERE, timeout,
+        base::BindRepeating(
+            [](bool* timed_out, const base::Location& location) {
+              *timed_out = true;
+              return std::string("Timeout callback from WaitForEvent() in ") +
+                     location.ToString();
+            },
+            base::Unretained(&timed_out), location));
+    run_loop_.Run(location);
+    return !timed_out ? testing::AssertionSuccess()
+                      : testing::AssertionFailure()
+                            << "Timeout of callback from WaitForEvent() in "
+                            << location.ToString();
+  }
+
+ private:
+  // AutofillManager::Observer:
+  void OnAutofillManagerDestroyed(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnAutofillManagerDestroyed, manager);
+  }
+  void OnAutofillManagerReset(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnAutofillManagerReset, manager);
+  }
+  void OnBeforeLanguageDetermined(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnBeforeLanguageDetermined, manager);
+  }
+  void OnAfterLanguageDetermined(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnAfterLanguageDetermined, manager);
+  }
+  void OnBeforeFormsSeen(AutofillManager& manager,
+                         base::span<const FormGlobalId> forms) override {
+    MaybeQuit(&Observer::OnBeforeFormsSeen, manager, forms);
+  }
+  void OnAfterFormsSeen(AutofillManager& manager,
+                        base::span<const FormGlobalId> forms) override {
+    MaybeQuit(&Observer::OnAfterFormsSeen, manager, forms);
+  }
+  void OnBeforeTextFieldDidChange(AutofillManager& manager,
+                                  FormGlobalId form,
+                                  FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnBeforeTextFieldDidChange, manager, form, field);
+  }
+  void OnAfterTextFieldDidChange(AutofillManager& manager,
+                                 FormGlobalId form,
+                                 FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnAfterTextFieldDidChange, manager, form, field);
+  }
+  void OnBeforeTextFieldDidScroll(AutofillManager& manager,
+                                  FormGlobalId form,
+                                  FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnBeforeTextFieldDidScroll, manager, form, field);
+  }
+  void OnAfterTextFieldDidScroll(AutofillManager& manager,
+                                 FormGlobalId form,
+                                 FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnAfterTextFieldDidScroll, manager, form, field);
+  }
+  void OnBeforeSelectControlDidChange(AutofillManager& manager,
+                                      FormGlobalId form,
+                                      FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnBeforeSelectControlDidChange, manager, form, field);
+  }
+  void OnAfterSelectControlDidChange(AutofillManager& manager,
+                                     FormGlobalId form,
+                                     FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnAfterSelectControlDidChange, manager, form, field);
+  }
+  void OnBeforeAskForValuesToFill(AutofillManager& manager,
+                                  FormGlobalId form,
+                                  FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnBeforeAskForValuesToFill, manager, form, field);
+  }
+  void OnAfterAskForValuesToFill(AutofillManager& manager,
+                                 FormGlobalId form,
+                                 FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnAfterAskForValuesToFill, manager, form, field);
+  }
+  void OnBeforeDidFillAutofillFormData(AutofillManager& manager,
+                                       FormGlobalId form) override {
+    MaybeQuit(&Observer::OnBeforeDidFillAutofillFormData, manager, form);
+  }
+  void OnAfterDidFillAutofillFormData(AutofillManager& manager,
+                                      FormGlobalId form) override {
+    MaybeQuit(&Observer::OnAfterDidFillAutofillFormData, manager, form);
+  }
+  void OnBeforeJavaScriptChangedAutofilledValue(AutofillManager& manager,
+                                                FormGlobalId form,
+                                                FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnBeforeDidFillAutofillFormData, manager, form, field);
+  }
+  void OnAfterJavaScriptChangedAutofilledValue(AutofillManager& manager,
+                                               FormGlobalId form,
+                                               FieldGlobalId field) override {
+    MaybeQuit(&Observer::OnAfterDidFillAutofillFormData, manager, form, field);
+  }
+  void OnBeforeLoadedServerPredictions(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnBeforeLoadedServerPredictions, manager);
+  }
+  void OnAfterLoadedServerPredictions(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnAfterLoadedServerPredictions, manager);
+  }
+  void OnFieldTypesDetermined(AutofillManager& manager,
+                              FormGlobalId form,
+                              FieldTypeSource source) override {
+    MaybeQuit(&Observer::OnFieldTypesDetermined, manager, form, source);
+  }
+  void OnSuggestionsShown(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnSuggestionsShown, manager);
+  }
+  void OnSuggestionsHidden(AutofillManager& manager) override {
+    MaybeQuit(&Observer::OnSuggestionsHidden, manager);
+  }
+  void OnFillOrPreviewDataModelForm(
+      AutofillManager& manager,
+      autofill::FormGlobalId form,
+      mojom::AutofillActionPersistence action_persistence,
+      base::span<const std::pair<const FormFieldData*, const AutofillField*>>
+          filled_fields,
+      absl::variant<const AutofillProfile*, const CreditCard*>
+          profile_or_credit_card) override {
+    MaybeQuit(&Observer::OnFillOrPreviewDataModelForm, manager, form,
+              action_persistence, filled_fields, profile_or_credit_card);
+  }
+  void OnFormSubmitted(AutofillManager& manager, FormGlobalId form) override {
+    MaybeQuit(&Observer::OnFormSubmitted, manager, form);
+  }
+
+  // Quits the `run_loop_` if `event` matches `event_`.
+  //
+  // `event` must be a pointer to an AutofillManager::Observer member function.
+  template <typename CandidateEvent, typename... CandidateArgs>
+  void MaybeQuit(const CandidateEvent& event, CandidateArgs&&... args) {
+    if constexpr (std::is_same_v<Event, CandidateEvent>) {
+      if (event_ == event && matcher_.Matches(std::forward_as_tuple(
+                                 std::forward<CandidateArgs>(args)...))) {
+        run_loop_.Quit();
+      }
+    }
+  }
+
+  base::ScopedObservation<AutofillManager, AutofillManager::Observer>
+      observation_{this};
+  Event event_ = nullptr;
+  testing::Matcher<std::tuple<Args...>> matcher_;
+  base::RunLoop run_loop_;
+};
+
+}  // namespace internal
+
+// Returns a callback that waits for a given `event` whose arguments are matched
+// by `matcher`.
+//
+// The `event` must be a pointer to an AutofillManager::Observer member
+// function. When adding a new event to AutofillManager::Observer, a
+// corresponding override must be added to AutofillManagerSingleEventWaiter.
+//
+// Typical usage is as follows:
+//
+//   base::OnceCallback<bool()> preview_waiter = WaitForEvent(
+//      *autofill_manager,
+//      &AutofillManager::Observer::OnFillOrPreviewDataModelForm,
+//      testing::Args<2>(mojom::AutofillActionPersistence::kPreview));
+//   ...
+//   EXPECT_TRUE(std::move(preview_waiter).Run());
+template <typename Matcher, typename R, typename... Args>
+base::OnceCallback<testing::AssertionResult()> WaitForEvent(
+    AutofillManager& manager,
+    R (AutofillManager::Observer::*event)(Args...),
+    Matcher matcher,
+    base::TimeDelta timeout = base::Seconds(1),
+    const base::Location& location = FROM_HERE) {
+  using T = internal::AutofillManagerSingleEventWaiter<Args...>;
+  return base::BindOnce(
+      [](std::unique_ptr<T> observer, base::TimeDelta timeout,
+         const base::Location& location) {
+        return std::move(*observer).Wait(timeout, std::move(location));
+      },
+      std::make_unique<T>(manager, event, matcher), timeout, location);
+}
+
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_WAITER_H_
diff --git a/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc b/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc
index 7439901e..421510c 100644
--- a/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc
+++ b/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc
@@ -34,11 +34,10 @@
     FieldTypeGroup focused_group) const {
   std::vector<std::u16string> label_parts;
 
-  bool street_address_is_focused =
-      focused_group == FieldTypeGroup::kAddressHome &&
-      IsStreetAddressPart(focused_field_type());
+  bool street_address_is_focused = focused_group == FieldTypeGroup::kAddress &&
+                                   IsStreetAddressPart(focused_field_type());
   bool non_street_address_is_focused =
-      focused_group == FieldTypeGroup::kAddressHome &&
+      focused_group == FieldTypeGroup::kAddress &&
       !IsStreetAddressPart(focused_field_type());
 
   if (focused_group != FieldTypeGroup::kName &&
@@ -55,7 +54,7 @@
         &label_parts);
   }
 
-  if (focused_group != FieldTypeGroup::kPhoneHome && phone_disambiguates_) {
+  if (focused_group != FieldTypeGroup::kPhone && phone_disambiguates_) {
     AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts);
   }
 
diff --git a/components/autofill/core/browser/ui/address_email_form_label_formatter.cc b/components/autofill/core/browser/ui/address_email_form_label_formatter.cc
index 05262e4..bb363ee 100644
--- a/components/autofill/core/browser/ui/address_email_form_label_formatter.cc
+++ b/components/autofill/core/browser/ui/address_email_form_label_formatter.cc
@@ -27,7 +27,7 @@
 std::u16string AddressEmailFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
     FieldTypeGroup focused_group) const {
-  return focused_group == FieldTypeGroup::kAddressHome &&
+  return focused_group == FieldTypeGroup::kAddress &&
                  !IsStreetAddressPart(focused_field_type())
              ? GetLabelForProfileOnFocusedNonStreetAddress(
                    form_has_street_address_, profile, app_locale(),
@@ -53,7 +53,7 @@
         &label_parts);
   }
 
-  if (focused_group != FieldTypeGroup::kAddressHome) {
+  if (focused_group != FieldTypeGroup::kAddress) {
     AddLabelPartIfNotEmpty(
         GetLabelAddress(form_has_street_address_, profile, app_locale(),
                         field_types_for_labels()),
diff --git a/components/autofill/core/browser/ui/address_form_label_formatter.cc b/components/autofill/core/browser/ui/address_form_label_formatter.cc
index 4f837ff..775e1b03 100644
--- a/components/autofill/core/browser/ui/address_form_label_formatter.cc
+++ b/components/autofill/core/browser/ui/address_form_label_formatter.cc
@@ -27,7 +27,7 @@
 std::u16string AddressFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
     FieldTypeGroup focused_group) const {
-  if (focused_group != FieldTypeGroup::kAddressHome) {
+  if (focused_group != FieldTypeGroup::kAddress) {
     return GetLabelNationalAddress(field_types_for_labels(), profile,
                                    app_locale());
   } else {
diff --git a/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc b/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc
index 59cce8d..948c183 100644
--- a/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc
+++ b/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc
@@ -28,7 +28,7 @@
 std::u16string AddressPhoneFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
     FieldTypeGroup focused_group) const {
-  return focused_group == FieldTypeGroup::kAddressHome &&
+  return focused_group == FieldTypeGroup::kAddress &&
                  !IsStreetAddressPart(focused_field_type())
              ? GetLabelForProfileOnFocusedNonStreetAddress(
                    form_has_street_address_, profile, app_locale(),
@@ -53,11 +53,11 @@
         &label_parts);
   }
 
-  if (focused_group != FieldTypeGroup::kPhoneHome) {
+  if (focused_group != FieldTypeGroup::kPhone) {
     AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts);
   }
 
-  if (focused_group != FieldTypeGroup::kAddressHome) {
+  if (focused_group != FieldTypeGroup::kAddress) {
     AddLabelPartIfNotEmpty(
         GetLabelAddress(form_has_street_address_, profile, app_locale(),
                         field_types_for_labels()),
diff --git a/components/autofill/core/browser/ui/contact_form_label_formatter.cc b/components/autofill/core/browser/ui/contact_form_label_formatter.cc
index 9cb1083..fa82cb4 100644
--- a/components/autofill/core/browser/ui/contact_form_label_formatter.cc
+++ b/components/autofill/core/browser/ui/contact_form_label_formatter.cc
@@ -37,7 +37,7 @@
         &label_parts);
   }
 
-  if (focused_group != FieldTypeGroup::kPhoneHome) {
+  if (focused_group != FieldTypeGroup::kPhone) {
     AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts);
   }
 
diff --git a/components/autofill/core/browser/ui/label_formatter.cc b/components/autofill/core/browser/ui/label_formatter.cc
index 5af8002..1042ca1 100644
--- a/components/autofill/core/browser/ui/label_formatter.cc
+++ b/components/autofill/core/browser/ui/label_formatter.cc
@@ -43,14 +43,14 @@
       groups_(groups) {
   const FieldTypeGroup focused_group = AutofillType(focused_field_type).group();
   DenseSet<FieldTypeGroup> groups_for_labels{
-      FieldTypeGroup::kName, FieldTypeGroup::kAddressHome,
-      FieldTypeGroup::kEmail, FieldTypeGroup::kPhoneHome};
+      FieldTypeGroup::kName, FieldTypeGroup::kAddress, FieldTypeGroup::kEmail,
+      FieldTypeGroup::kPhone};
 
   // If a user is focused on an address field, then parts of the address may be
   // shown in the label. For example, if the user is focusing on a street
   // address field, then it may be helpful to show the city in the label.
   // Otherwise, the focused field should not appear in the label.
-  if (focused_group != FieldTypeGroup::kAddressHome) {
+  if (focused_group != FieldTypeGroup::kAddress) {
     groups_for_labels.erase(focused_group);
   }
 
diff --git a/components/autofill/core/browser/ui/label_formatter_utils.cc b/components/autofill/core/browser/ui/label_formatter_utils.cc
index 1a24a77..299195b 100644
--- a/components/autofill/core/browser/ui/label_formatter_utils.cc
+++ b/components/autofill/core/browser/ui/label_formatter_utils.cc
@@ -123,7 +123,7 @@
   auto should_be_extracted =
       [&extract_street_address_types](ServerFieldType type) -> bool {
     return AutofillType(AutofillType(type).GetStorableType()).group() ==
-               FieldTypeGroup::kAddressHome &&
+               FieldTypeGroup::kAddress &&
            (extract_street_address_types ? IsStreetAddressPart(type)
                                          : !IsStreetAddressPart(type));
   };
@@ -375,21 +375,20 @@
     FieldTypeGroup focused_group,
     const std::vector<ServerFieldType>& types) {
   return HasNonStreetAddress(types) &&
-         (focused_group != FieldTypeGroup::kAddressHome ||
+         (focused_group != FieldTypeGroup::kAddress ||
           !IsNonStreetAddressPart(focused_field));
 }
 
 bool HasUnfocusedPhoneField(FieldTypeGroup focused_group,
                             uint32_t form_groups) {
-  return ContainsPhone(form_groups) &&
-         focused_group != FieldTypeGroup::kPhoneHome;
+  return ContainsPhone(form_groups) && focused_group != FieldTypeGroup::kPhone;
 }
 
 bool HasUnfocusedStreetAddressField(ServerFieldType focused_field,
                                     FieldTypeGroup focused_group,
                                     const std::vector<ServerFieldType>& types) {
   return HasStreetAddress(types) &&
-         (focused_group != FieldTypeGroup::kAddressHome ||
+         (focused_group != FieldTypeGroup::kAddress ||
           !IsStreetAddressPart(focused_field));
 }
 
diff --git a/components/autofill/core/browser/ui/suggestion_selection.cc b/components/autofill/core/browser/ui/suggestion_selection.cc
index 445f753..53f951d 100644
--- a/components/autofill/core/browser/ui/suggestion_selection.cc
+++ b/components/autofill/core/browser/ui/suggestion_selection.cc
@@ -161,8 +161,7 @@
                              const std::string& app_locale,
                              Suggestion& suggestion) {
   const FieldTypeGroup field_type_group = type.group();
-  if (field_type_group == FieldTypeGroup::kName ||
-      field_type_group == FieldTypeGroup::kNameBilling) {
+  if (field_type_group == FieldTypeGroup::kName) {
     // Note that this suggestion can only be added if name infos exist in the
     // profile.
     suggestion.children.push_back(
@@ -231,8 +230,7 @@
                                 const std::string& app_locale,
                                 Suggestion& suggestion) {
   const FieldTypeGroup field_type_group = type.group();
-  if (field_type_group == FieldTypeGroup::kAddressHome ||
-      field_type_group == FieldTypeGroup::kAddressBilling) {
+  if (field_type_group == FieldTypeGroup::kAddress) {
     // Note that this suggestion can only be added if address infos exist in the
     // profile.
     suggestion.children.push_back(
@@ -265,8 +263,7 @@
   if (profile.HasInfo(PHONE_HOME_WHOLE_NUMBER)) {
     Suggestion phone_number_suggestion(
         profile.GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale));
-    const bool is_phone_field = type.group() == FieldTypeGroup::kPhoneHome ||
-                                type.group() == FieldTypeGroup::kPhoneBilling;
+    const bool is_phone_field = type.group() == FieldTypeGroup::kPhone;
     phone_number_suggestion.popup_item_id =
         is_phone_field ? PopupItemId::kFillFullPhoneNumber
                        : PopupItemId::kFieldByFieldFilling;
@@ -369,7 +366,7 @@
             &prefix_matched_suggestion)) {
       matched_profiles->push_back(profile);
 
-      if (type.group() == FieldTypeGroup::kPhoneHome) {
+      if (type.group() == FieldTypeGroup::kPhone) {
         bool format_phone;
 
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
@@ -482,8 +479,7 @@
   // Phones should do a substring match because they can be trimmed to remove
   // the first parts (e.g. country code or prefix). It is still considered a
   // prefix match in order to put it at the top of the suggestions.
-  if ((type.group() == FieldTypeGroup::kPhoneHome ||
-       type.group() == FieldTypeGroup::kPhoneBilling) &&
+  if (type.group() == FieldTypeGroup::kPhone &&
       suggestion_canon.find(field_contents_canon) != std::u16string::npos) {
     return true;
   }
diff --git a/components/autofill/ios/form_util/BUILD.gn b/components/autofill/ios/form_util/BUILD.gn
index cc1215db..a3cbc8a0 100644
--- a/components/autofill/ios/form_util/BUILD.gn
+++ b/components/autofill/ios/form_util/BUILD.gn
@@ -63,6 +63,8 @@
   sources = [
     "resources/create_fill_namespace.js",
     "resources/fill_constants.js",
+    "resources/fill_element_inference.js",
+    "resources/fill_element_inference_util.js",
   ]
 }
 
diff --git a/components/autofill/ios/form_util/resources/fill.js b/components/autofill/ios/form_util/resources/fill.js
index 59e8524..cf666d9 100644
--- a/components/autofill/ios/form_util/resources/fill.js
+++ b/components/autofill/ios/form_util/resources/fill.js
@@ -4,6 +4,7 @@
 
 import '//components/autofill/ios/form_util/resources/create_fill_namespace.js';
 import '//components/autofill/ios/form_util/resources/fill_constants.js';
+import '//components/autofill/ios/form_util/resources/fill_element_inference.js';
 
 // This file provides methods used to fill forms in JavaScript.
 
@@ -840,889 +841,6 @@
 };
 
 /**
- * Returns is the tag of an |element| is tag.
- *
- * It is based on the logic in
- *     bool HasTagName(const WebNode& node, const blink::WebString& tag)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {Node} node Node to examine.
- * @param {string} tag Tag name.
- * @return {boolean} Whether the tag of node is tag.
- */
-__gCrWeb.fill.hasTagName = function(node, tag) {
-  return node.nodeType === Node.ELEMENT_NODE &&
-      /** @type {Element} */ (node).tagName === tag.toUpperCase();
-};
-
-/**
- * Checks if an element is autofillable.
- *
- * It is based on the logic in
- *     bool IsAutofillableElement(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {boolean} Whether element is one of the element types that can be
- *     autofilled.
- */
-__gCrWeb.fill.isAutofillableElement = function(element) {
-  return __gCrWeb.fill.isAutofillableInputElement(element) ||
-      __gCrWeb.fill.isSelectElement(element) ||
-      __gCrWeb.fill.isTextAreaElement(element);
-};
-
-/**
- * Trims whitespace from the start of the input string.
- * Simplified version of string_util::TrimWhitespace.
- * @param {string} input String to trim.
- * @return {string} The |input| string without leading whitespace.
- */
-__gCrWeb.fill.trimWhitespaceLeading = function(input) {
-  return input.replace(/^\s+/gm, '');
-};
-
-/**
- * Trims whitespace from the end of the input string.
- * Simplified version of string_util::TrimWhitespace.
- * @param {string} input String to trim.
- * @return {string} The |input| string without trailing whitespace.
- */
-__gCrWeb.fill.trimWhitespaceTrailing = function(input) {
-  return input.replace(/\s+$/gm, '');
-};
-
-/**
- * Appends |suffix| to |prefix| so that any intermediary whitespace is collapsed
- * to a single space.  If |force_whitespace| is true, then the resulting string
- * is guaranteed to have a space between |prefix| and |suffix|.  Otherwise, the
- * result includes a space only if |prefix| has trailing whitespace or |suffix|
- * has leading whitespace.
- *
- * A few examples:
- *     CombineAndCollapseWhitespace('foo', 'bar', false)       -> 'foobar'
- *     CombineAndCollapseWhitespace('foo', 'bar', true)        -> 'foo bar'
- *     CombineAndCollapseWhitespace('foo ', 'bar', false)      -> 'foo bar'
- *     CombineAndCollapseWhitespace('foo', ' bar', false)      -> 'foo bar'
- *     CombineAndCollapseWhitespace('foo', ' bar', true)       -> 'foo bar'
- *     CombineAndCollapseWhitespace('foo   ', '   bar', false) -> 'foo bar'
- *     CombineAndCollapseWhitespace(' foo', 'bar ', false)     -> ' foobar '
- *     CombineAndCollapseWhitespace(' foo', 'bar ', true)      -> ' foo bar '
- *
- * It is based on the logic in
- * const string16 CombineAndCollapseWhitespace(const string16& prefix,
- *                                             const string16& suffix,
- *                                             bool force_whitespace)
- * @param {string} prefix The prefix string in the string combination.
- * @param {string} suffix The suffix string in the string combination.
- * @param {boolean} forceWhitespace A boolean indicating if whitespace should
- *     be added as separator in the combination.
- * @return {string} The combined string.
- */
-__gCrWeb.fill.combineAndCollapseWhitespace = function(
-    prefix, suffix, forceWhitespace) {
-  const prefixTrimmed = __gCrWeb.fill.trimWhitespaceTrailing(prefix);
-  const prefixTrailingWhitespace = prefixTrimmed !== prefix;
-  const suffixTrimmed = __gCrWeb.fill.trimWhitespaceLeading(suffix);
-  const suffixLeadingWhitespace = suffixTrimmed !== suffix;
-  if (prefixTrailingWhitespace || suffixLeadingWhitespace || forceWhitespace) {
-    return prefixTrimmed + ' ' + suffixTrimmed;
-  } else {
-    return prefixTrimmed + suffixTrimmed;
-  }
-};
-
-/**
- * This is a helper function for the findChildText() function (see below).
- * Search depth is limited with the |depth| parameter.
- *
- * Based on form_autofill_util::FindChildTextInner().
- *
- * @param {Node} node The node to fetch the text content from.
- * @param {number} depth The maximum depth to descend on the DOM.
- * @param {Array<Node>} divsToSkip List of <div> tags to ignore if encountered.
- * @return {string} The discovered and adapted string.
- */
-__gCrWeb.fill.findChildTextInner = function(node, depth, divsToSkip) {
-  if (depth <= 0 || !node) {
-    return '';
-  }
-
-  // Skip over comments.
-  if (node.nodeType === Node.COMMENT_NODE) {
-    return __gCrWeb.fill.findChildTextInner(
-        node.nextSibling, depth - 1, divsToSkip);
-  }
-
-  if (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {
-    return '';
-  }
-
-  // Ignore elements known not to contain inferable labels.
-  let skipNode = false;
-  if (node.nodeType === Node.ELEMENT_NODE) {
-    if (node.tagName === 'OPTION') {
-      return '';
-    }
-    if (__gCrWeb.form.isFormControlElement(/** @type {Element} */ (node))) {
-      const input = /** @type {FormControlElement} */ (node);
-      if (__gCrWeb.fill.isAutofillableElement(input)) {
-        return '';
-      }
-    }
-    skipNode = node.tagName === 'SCRIPT' || node.tagName === 'NOSCRIPT';
-  }
-
-  if (node.tagName === 'DIV') {
-    for (let i = 0; i < divsToSkip.length; ++i) {
-      if (node === divsToSkip[i]) {
-        return '';
-      }
-    }
-  }
-
-  // Extract the text exactly at this node.
-  let nodeText = '';
-  if (!skipNode) {
-    nodeText = __gCrWeb.fill.nodeValue(node);
-    if (node.nodeType === Node.TEXT_NODE && !nodeText) {
-      // In the C++ version, this text node would have been stripped completely.
-      // Just pass the buck.
-      return __gCrWeb.fill.findChildTextInner(
-          node.nextSibling, depth, divsToSkip);
-    }
-
-    // Recursively compute the children's text.
-    // Preserve inter-element whitespace separation.
-    const childText = __gCrWeb.fill.findChildTextInner(
-        node.firstChild, depth - 1, divsToSkip);
-    let addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
-    // Emulate apparently incorrect Chromium behavior tracked in
-    // https://crbug.com/239819.
-    addSpace = false;
-    nodeText = __gCrWeb.fill.combineAndCollapseWhitespace(
-        nodeText, childText, addSpace);
-  }
-
-  // Recursively compute the siblings' text.
-  // Again, preserve inter-element whitespace separation.
-  const siblingText =
-      __gCrWeb.fill.findChildTextInner(node.nextSibling, depth - 1, divsToSkip);
-  let addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
-  // Emulate apparently incorrect Chromium behavior tracked in
-  // https://crbug.com/239819.
-  addSpace = false;
-  nodeText = __gCrWeb.fill.combineAndCollapseWhitespace(
-      nodeText, siblingText, addSpace);
-
-  return nodeText;
-};
-
-/**
- * Same as findChildText() below, but with a list of div nodes to skip.
- *
- * It is based on the logic in
- *    string16 FindChildTextWithIgnoreList(
- *        const WebNode& node,
- *        const std::set<WebNode>& divs_to_skip)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {Node} node A node of which the child text will be return.
- * @param {Array<Node>} divsToSkip List of <div> tags to ignore if encountered.
- * @return {string} The child text.
- */
-__gCrWeb.fill.findChildTextWithIgnoreList = function(node, divsToSkip) {
-  if (node.nodeType === Node.TEXT_NODE) return __gCrWeb.fill.nodeValue(node);
-
-  const child = node.firstChild;
-  const kChildSearchDepth = 10;
-  let nodeText =
-      __gCrWeb.fill.findChildTextInner(child, kChildSearchDepth, divsToSkip);
-  nodeText = nodeText.trim();
-  return nodeText;
-};
-
-/**
- * Returns the aggregated values of the descendants of |element| that are
- * non-empty text nodes.
- *
- * It is based on the logic in
- *    string16 FindChildText(const WebNode& node)
- * chromium/src/components/autofill/content/renderer/form_autofill_util.cc,
- * which is a faster alternative to |innerText()| for performance critical
- * operations.
- *
- * @param {Node} node A node of which the child text will be return.
- * @return {string} The child text.
- */
-__gCrWeb.fill.findChildText = function(node) {
-  return __gCrWeb.fill.findChildTextWithIgnoreList(node, []);
-};
-
-/**
- * Shared function for InferLabelFromPrevious() and InferLabelFromNext().
- *
- * It is based on the logic in
- *     string16 InferLabelFromSibling(const WebFormControlElement& element,
- *                                    bool forward)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @param {boolean} forward whether to search for the next or previous element.
- * @return {string} The label of element or an empty string if there is no
- *                  sibling or no label.
- */
-__gCrWeb.fill.inferLabelFromSibling = function(element, forward) {
-  let inferredLabel = '';
-  let sibling = element;
-  if (!sibling) {
-    return '';
-  }
-
-  while (true) {
-    if (forward) {
-      sibling = sibling.nextSibling;
-    } else {
-      sibling = sibling.previousSibling;
-    }
-
-    if (!sibling) {
-      break;
-    }
-
-    // Skip over comments.
-    const nodeType = sibling.nodeType;
-    if (nodeType === Node.COMMENT_NODE) {
-      continue;
-    }
-
-    // Otherwise, only consider normal HTML elements and their contents.
-    if (nodeType !== Node.TEXT_NODE && nodeType !== Node.ELEMENT_NODE) {
-      break;
-    }
-
-    // A label might be split across multiple "lightweight" nodes.
-    // Coalesce any text contained in multiple consecutive
-    //  (a) plain text nodes or
-    //  (b) inline HTML elements that are essentially equivalent to text nodes.
-    if (nodeType === Node.TEXT_NODE || __gCrWeb.fill.hasTagName(sibling, 'b') ||
-        __gCrWeb.fill.hasTagName(sibling, 'strong') ||
-        __gCrWeb.fill.hasTagName(sibling, 'span') ||
-        __gCrWeb.fill.hasTagName(sibling, 'font')) {
-      const value = __gCrWeb.fill.findChildText(sibling);
-      // A text node's value will be empty if it is for a line break.
-      const addSpace = nodeType === Node.TEXT_NODE && value.length === 0;
-      if (forward) {
-        inferredLabel = __gCrWeb.fill.combineAndCollapseWhitespace(
-            inferredLabel, value, addSpace);
-      } else {
-        inferredLabel = __gCrWeb.fill.combineAndCollapseWhitespace(
-            value, inferredLabel, addSpace);
-      }
-      continue;
-    }
-
-    // If we have identified a partial label and have reached a non-lightweight
-    // element, consider the label to be complete.
-    const trimmedLabel = inferredLabel.trim();
-    if (trimmedLabel.length > 0) {
-      break;
-    }
-
-    // <img> and <br> tags often appear between the input element and its
-    // label text, so skip over them.
-    if (__gCrWeb.fill.hasTagName(sibling, 'img') ||
-        __gCrWeb.fill.hasTagName(sibling, 'br')) {
-      continue;
-    }
-
-    // We only expect <p> and <label> tags to contain the full label text.
-    if (__gCrWeb.fill.hasTagName(sibling, 'p') ||
-        __gCrWeb.fill.hasTagName(sibling, 'label')) {
-      inferredLabel = __gCrWeb.fill.findChildText(sibling);
-    }
-    break;
-  }
-  return inferredLabel.trim();
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * a previous sibling of |element|,
- * e.g. Some Text <input ...>
- * or   Some <span>Text</span> <input ...>
- * or   <p>Some Text</p><input ...>
- * or   <label>Some Text</label> <input ...>
- * or   Some Text <img><input ...>
- * or   <b>Some Text</b><br/> <input ...>.
- *
- * It is based on the logic in
- *     string16 InferLabelFromPrevious(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromPrevious = function(element) {
-  return __gCrWeb.fill.inferLabelFromSibling(element, false);
-};
-
-/**
- * Same as InferLabelFromPrevious(), but in the other direction.
- * Useful for cases like: <span><input type="checkbox">Label For Checkbox</span>
- *
- * It is based on the logic in
- *     string16 InferLabelFromNext(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromNext = function(element) {
-  return __gCrWeb.fill.inferLabelFromSibling(element, true);
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * the placeholder attribute.
- *
- * It is based on the logic in
- *     string16 InferLabelFromPlaceholder(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromPlaceholder = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  return element.placeholder || element.getAttribute('placeholder') || '';
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * the value attribute when it is present and user has not typed in (if
- * element's value attribute is same as the element's value).
- *
- * It is based on the logic in
- *     string16 InferLabelFromValueAttr(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.InferLabelFromValueAttr = function(element) {
-  if (!element || !element.value || !element.hasAttribute('value') ||
-      element.value !== element.getAttribute('value')) {
-    return '';
-  }
-
-  return element.value;
-};
-
-/**
- * Helper for |InferLabelForElement()| that tests if an inferred label is valid
- * or not. A valid label is a label that does not only contains special
- * characters.
- *
- * It is based on the logic in
- *     bool IsLabelValid(base::StringPiece16 inferred_label,
- *         const std::vector<char16_t>& stop_words)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- * The list of characters that are considered special is hard-coded in a regexp.
- *
- * @param {string} label An element to examine.
- * @return {boolean} Whether the label contains not special characters.
- */
-__gCrWeb.fill.IsLabelValid = function(label) {
-  return label.search(/[^ *:()\u2013-]/) >= 0;
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * enclosing list item, e.g.
- *     <li>Some Text<input ...><input ...><input ...></li>
- *
- * It is based on the logic in
- *     string16 InferLabelFromListItem(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromListItem = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  let parentNode = element.parentNode;
-  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !__gCrWeb.fill.hasTagName(parentNode, 'li')) {
-    parentNode = parentNode.parentNode;
-  }
-
-  if (parentNode && __gCrWeb.fill.hasTagName(parentNode, 'li')) {
-    return __gCrWeb.fill.findChildText(parentNode);
-  }
-
-  return '';
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * surrounding table structure,
- * e.g. <tr><td>Some Text</td><td><input ...></td></tr>
- * or   <tr><th>Some Text</th><td><input ...></td></tr>
- * or   <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
- * or   <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr>
- *
- * It is based on the logic in
- *    string16 InferLabelFromTableColumn(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromTableColumn = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  let parentNode = element.parentNode;
-  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !__gCrWeb.fill.hasTagName(parentNode, 'td')) {
-    parentNode = parentNode.parentNode;
-  }
-
-  if (!parentNode) {
-    return '';
-  }
-
-  // Check all previous siblings, skipping non-element nodes, until we find a
-  // non-empty text block.
-  let inferredLabel = '';
-  let previous = parentNode.previousSibling;
-  while (inferredLabel.length === 0 && previous) {
-    if (__gCrWeb.fill.hasTagName(previous, 'td') ||
-        __gCrWeb.fill.hasTagName(previous, 'th')) {
-      inferredLabel = __gCrWeb.fill.findChildText(previous);
-    }
-    previous = previous.previousSibling;
-  }
-
-  return inferredLabel;
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * surrounding table structure,
- * e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr>
- *
- * If there are multiple cells and the row with the input matches up with the
- * previous row, then look for a specific cell within the previous row.
- * e.g. <tr><td>Input 1 label</td><td>Input 2 label</td></tr>
- *  <tr><td><input name="input 1"></td><td><input name="input2"></td></tr>
- *
- * It is based on the logic in
- *     string16 InferLabelFromTableRow(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromTableRow = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  let cell = element.parentNode;
-  while (cell) {
-    if (cell.nodeType === Node.ELEMENT_NODE &&
-        __gCrWeb.fill.hasTagName(cell, 'td')) {
-      break;
-    }
-    cell = cell.parentNode;
-  }
-
-  // Not in a cell - bail out.
-  if (!cell) {
-    return '';
-  }
-
-  // Count the cell holding |element|.
-  let cellCount = cell.colSpan;
-  let cellPosition = 0;
-  let cellPositionEnd = cellCount - 1;
-
-  // Count cells to the left to figure out |element|'s cell's position.
-  let cellIterator = cell.previousSibling;
-  while (cellIterator) {
-    if (cellIterator.nodeType === Node.ELEMENT_NODE &&
-        __gCrWeb.fill.hasTagName(cellIterator, 'td')) {
-      cellPosition += cellIterator.colSpan;
-    }
-    cellIterator = cellIterator.previousSibling;
-  }
-
-  // Count cells to the right.
-  cellIterator = cell.nextSibling;
-  while (cellIterator) {
-    if (cellIterator.nodeType === Node.ELEMENT_NODE &&
-        __gCrWeb.fill.hasTagName(cellIterator, 'td')) {
-      cellCount += cellIterator.colSpan;
-    }
-    cellIterator = cellIterator.nextSibling;
-  }
-
-  // Combine left + right.
-  cellCount += cellPosition;
-  cellPositionEnd += cellPosition;
-
-  // Find the current row.
-  let parentNode = element.parentNode;
-  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !__gCrWeb.fill.hasTagName(parentNode, 'tr')) {
-    parentNode = parentNode.parentNode;
-  }
-
-  if (!parentNode) {
-    return '';
-  }
-
-  // Now find the previous row.
-  let rowIt = parentNode.previousSibling;
-  while (rowIt) {
-    if (rowIt.nodeType === Node.ELEMENT_NODE &&
-        __gCrWeb.fill.hasTagName(parentNode, 'tr')) {
-      break;
-    }
-    rowIt = rowIt.previousSibling;
-  }
-
-  // If there exists a previous row, check its cells and size. If they align
-  // with the current row, infer the label from the cell above.
-  if (rowIt) {
-    let matchingCell = null;
-    let prevRowCount = 0;
-    let prevRowIt = rowIt.firstChild;
-    while (prevRowIt) {
-      if (prevRowIt.nodeType === Node.ELEMENT_NODE) {
-        if (__gCrWeb.fill.hasTagName(prevRowIt, 'td') ||
-            __gCrWeb.fill.hasTagName(prevRowIt, 'th')) {
-          const span = prevRowIt.colSpan;
-          const prevRowCountEnd = prevRowCount + span - 1;
-          if (prevRowCount === cellPosition &&
-              prevRowCountEnd === cellPositionEnd) {
-            matchingCell = prevRowIt;
-          }
-          prevRowCount += span;
-        }
-      }
-      prevRowIt = prevRowIt.nextSibling;
-    }
-    if (cellCount === prevRowCount && matchingCell) {
-      const inferredLabel = __gCrWeb.fill.findChildText(matchingCell);
-      if (inferredLabel.length > 0) {
-        return inferredLabel;
-      }
-    }
-  }
-
-  // If there is no previous row, or if the previous row and current row do not
-  // align, check all previous siblings, skipping non-element nodes, until we
-  // find a non-empty text block.
-  let inferredLabel = '';
-  let previous = parentNode.previousSibling;
-  while (inferredLabel.length === 0 && previous) {
-    if (__gCrWeb.fill.hasTagName(previous, 'tr')) {
-      inferredLabel = __gCrWeb.fill.findChildText(previous);
-    }
-    previous = previous.previousSibling;
-  }
-  return inferredLabel;
-};
-
-/**
- * Returns true if |node| is an element and it is a container type that
- * inferLabelForElement() can traverse.
- *
- * It is based on the logic in
- *     bool IsTraversableContainerElement(const WebNode& node);
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {!Node} node The node to be examined.
- * @return {boolean} Whether it can be traversed.
- */
-__gCrWeb.fill.isTraversableContainerElement = function(node) {
-  if (node.nodeType !== Node.ELEMENT_NODE) {
-    return false;
-  }
-
-  const tagName = /** @type {Element} */ (node).tagName;
-  return (
-      tagName === 'DD' || tagName === 'DIV' || tagName === 'FIELDSET' ||
-      tagName === 'LI' || tagName === 'TD' || tagName === 'TABLE');
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * an enclosing label.
- * e.g. <label>Some Text<span><input ...></span></label>
- *
- * It is based on the logic in
- *    string16 InferLabelFromEnclosingLabel(
- *        const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromEnclosingLabel = function(element) {
-  if (!element) {
-    return '';
-  }
-  let node = element.parentNode;
-  while (node && !__gCrWeb.fill.hasTagName(node, 'label')) {
-    node = node.parentNode;
-  }
-  if (node) {
-    return __gCrWeb.fill.findChildText(node);
-  }
-  return '';
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * a surrounding div table,
- * e.g. <div>Some Text<span><input ...></span></div>
- * e.g. <div>Some Text</div><div><input ...></div>
- *
- * Contrary to the other InferLabelFrom* functions, this functions walks up
- * the DOM tree from the original input, instead of down from the surrounding
- * tag. While doing so, if a <label> or text node sibling are found along the
- * way, a label is inferred from them directly. For example, <div>First
- * name<div><input></div>Last name<div><input></div></div> infers "First name"
- * and "Last name" for the two inputs, respectively, by picking up the text
- * nodes on the way to the surrounding div. Without doing so, the label of both
- * inputs becomes "First nameLast name".
- *
- * It is based on the logic in
- *    string16 InferLabelFromDivTable(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromDivTable = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  let node = element.parentNode;
-  let lookingForParent = true;
-  const divsToSkip = [];
-
-  // Search the sibling and parent <div>s until we find a candidate label.
-  let inferredLabel = '';
-  while (inferredLabel.length === 0 && node) {
-    if (__gCrWeb.fill.hasTagName(node, 'div')) {
-      if (lookingForParent) {
-        inferredLabel =
-            __gCrWeb.fill.findChildTextWithIgnoreList(node, divsToSkip);
-      } else {
-        inferredLabel = __gCrWeb.fill.findChildText(node);
-      }
-      // Avoid sibling DIVs that contain autofillable fields.
-      if (!lookingForParent && inferredLabel.length > 0) {
-        const resultElement = node.querySelector('input, select, textarea');
-        if (resultElement) {
-          inferredLabel = '';
-          let addDiv = true;
-          for (let i = 0; i < divsToSkip.length; ++i) {
-            if (node === divsToSkip[i]) {
-              addDiv = false;
-              break;
-            }
-          }
-          if (addDiv) {
-            divsToSkip.push(node);
-          }
-        }
-      }
-
-      lookingForParent = false;
-    } else if (!lookingForParent) {
-      // Infer a label from text nodes and unassigned <label> siblings.
-      if (__gCrWeb.fill.hasTagName(node, 'label') && !node.control) {
-        inferredLabel = __gCrWeb.fill.findChildText(node);
-      } else if (node.nodeType === Node.TEXT_NODE) {
-        inferredLabel = __gCrWeb.fill.nodeValue(node).trim();
-      }
-    } else if (__gCrWeb.fill.isTraversableContainerElement(node)) {
-      // If the element is in a non-div container, its label most likely is too.
-      break;
-    }
-
-    if (!node.previousSibling) {
-      // If there are no more siblings, continue walking up the tree.
-      lookingForParent = true;
-    }
-
-    if (lookingForParent) {
-      node = node.parentNode;
-    } else {
-      node = node.previousSibling;
-    }
-  }
-
-  return inferredLabel;
-};
-
-/**
- * Helper for |InferLabelForElement()| that infers a label, if possible, from
- * a surrounding definition list,
- * e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl>
- * e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
- *
- * It is based on the logic in
- *    string16 InferLabelFromDefinitionList(
- *        const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The label of element.
- */
-__gCrWeb.fill.inferLabelFromDefinitionList = function(element) {
-  if (!element) {
-    return '';
-  }
-
-  let parentNode = element.parentNode;
-  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !__gCrWeb.fill.hasTagName(parentNode, 'dd')) {
-    parentNode = parentNode.parentNode;
-  }
-
-  if (!parentNode || !__gCrWeb.fill.hasTagName(parentNode, 'dd')) {
-    return '';
-  }
-
-  // Skip by any intervening text nodes.
-  let previous = parentNode.previousSibling;
-  while (previous && previous.nodeType === Node.TEXT_NODE) {
-    previous = previous.previousSibling;
-  }
-
-  if (!previous || !__gCrWeb.fill.hasTagName(previous, 'dt')) return '';
-
-  return __gCrWeb.fill.findChildText(previous);
-};
-
-/**
- * Returns the element type for all ancestor nodes in CAPS, starting with the
- * parent node.
- *
- * It is based on the logic in
- *    std::vector<std::string> AncestorTagNames(
- *        const WebFormControlElement& element);
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {Array} The element types for all ancestors.
- */
-__gCrWeb.fill.ancestorTagNames = function(element) {
-  const tagNames = [];
-  let parentNode = element.parentNode;
-  while (parentNode) {
-    if (parentNode.nodeType === Node.ELEMENT_NODE) {
-      tagNames.push(parentNode.tagName);
-    }
-    parentNode = parentNode.parentNode;
-  }
-  return tagNames;
-};
-
-/**
- * Infers corresponding label for |element| from surrounding context in the DOM,
- * e.g. the contents of the preceding <p> tag or text element.
- *
- * It is based on the logic in
- *    string16 InferLabelForElement(const WebFormControlElement& element)
- * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
- *
- * @param {FormControlElement} element An element to examine.
- * @return {string} The inferred label of element, or '' if none could be found.
- */
-__gCrWeb.fill.inferLabelForElement = function(element) {
-  let inferredLabel;
-  if (__gCrWeb.fill.isCheckableElement(element)) {
-    inferredLabel = __gCrWeb.fill.inferLabelFromNext(element);
-    if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-      return inferredLabel;
-    }
-  }
-
-  inferredLabel = __gCrWeb.fill.inferLabelFromPrevious(element);
-  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-    return inferredLabel;
-  }
-
-  // If we didn't find a label, check for the placeholder case.
-  inferredLabel = __gCrWeb.fill.inferLabelFromPlaceholder(element);
-  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-    return inferredLabel;
-  }
-
-  // If we didn't find a placeholder, check for the aria-label case.
-  inferredLabel = __gCrWeb.fill.getAriaLabel(element);
-  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-    return inferredLabel;
-  }
-
-  // For all other searches that involve traversing up the tree, the search
-  // order is based on which tag is the closest ancestor to |element|.
-  const tagNames = __gCrWeb.fill.ancestorTagNames(element);
-  const seenTagNames = {};
-  for (let index = 0; index < tagNames.length; ++index) {
-    const tagName = tagNames[index];
-    if (tagName in seenTagNames) {
-      continue;
-    }
-
-    seenTagNames[tagName] = true;
-    if (tagName === 'LABEL') {
-      inferredLabel = __gCrWeb.fill.inferLabelFromEnclosingLabel(element);
-    } else if (tagName === 'DIV') {
-      inferredLabel = __gCrWeb.fill.inferLabelFromDivTable(element);
-    } else if (tagName === 'TD') {
-      inferredLabel = __gCrWeb.fill.inferLabelFromTableColumn(element);
-      if (!__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-        inferredLabel = __gCrWeb.fill.inferLabelFromTableRow(element);
-      }
-    } else if (tagName === 'DD') {
-      inferredLabel = __gCrWeb.fill.inferLabelFromDefinitionList(element);
-    } else if (tagName === 'LI') {
-      inferredLabel = __gCrWeb.fill.inferLabelFromListItem(element);
-    } else if (tagName === 'FIELDSET') {
-      break;
-    }
-
-    if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-      return inferredLabel;
-    }
-  }
-  // If we didn't find a label, check for the value attribute case.
-  inferredLabel = __gCrWeb.fill.InferLabelFromValueAttr(element);
-  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
-    return inferredLabel;
-  }
-
-  return '';
-};
-
-/**
  * Fills |field| data with the values of the <option> elements present in
  * |selectElement|.
  *
diff --git a/components/autofill/ios/form_util/resources/fill_element_inference.js b/components/autofill/ios/form_util/resources/fill_element_inference.js
new file mode 100644
index 0000000..d87cc454
--- /dev/null
+++ b/components/autofill/ios/form_util/resources/fill_element_inference.js
@@ -0,0 +1,606 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
+
+/**
+ * Shared function for InferLabelFromPrevious() and InferLabelFromNext().
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromSibling(const WebFormControlElement& element,
+ *                                    bool forward)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @param {boolean} forward whether to search for the next or previous element.
+ * @return {string} The label of element or an empty string if there is no
+ *                  sibling or no label.
+ */
+__gCrWeb.fill.inferLabelFromSibling = function(element, forward) {
+  let inferredLabel = '';
+  let sibling = element;
+  if (!sibling) {
+    return '';
+  }
+
+  while (true) {
+    if (forward) {
+      sibling = sibling.nextSibling;
+    } else {
+      sibling = sibling.previousSibling;
+    }
+
+    if (!sibling) {
+      break;
+    }
+
+    // Skip over comments.
+    const nodeType = sibling.nodeType;
+    if (nodeType === Node.COMMENT_NODE) {
+      continue;
+    }
+
+    // Otherwise, only consider normal HTML elements and their contents.
+    if (nodeType !== Node.TEXT_NODE && nodeType !== Node.ELEMENT_NODE) {
+      break;
+    }
+
+    // A label might be split across multiple "lightweight" nodes.
+    // Coalesce any text contained in multiple consecutive
+    //  (a) plain text nodes or
+    //  (b) inline HTML elements that are essentially equivalent to text nodes.
+    if (nodeType === Node.TEXT_NODE || __gCrWeb.fill.hasTagName(sibling, 'b') ||
+        __gCrWeb.fill.hasTagName(sibling, 'strong') ||
+        __gCrWeb.fill.hasTagName(sibling, 'span') ||
+        __gCrWeb.fill.hasTagName(sibling, 'font')) {
+      const value = __gCrWeb.fill.findChildText(sibling);
+      // A text node's value will be empty if it is for a line break.
+      const addSpace = nodeType === Node.TEXT_NODE && value.length === 0;
+      if (forward) {
+        inferredLabel = __gCrWeb.fill.combineAndCollapseWhitespace(
+            inferredLabel, value, addSpace);
+      } else {
+        inferredLabel = __gCrWeb.fill.combineAndCollapseWhitespace(
+            value, inferredLabel, addSpace);
+      }
+      continue;
+    }
+
+    // If we have identified a partial label and have reached a non-lightweight
+    // element, consider the label to be complete.
+    const trimmedLabel = inferredLabel.trim();
+    if (trimmedLabel.length > 0) {
+      break;
+    }
+
+    // <img> and <br> tags often appear between the input element and its
+    // label text, so skip over them.
+    if (__gCrWeb.fill.hasTagName(sibling, 'img') ||
+        __gCrWeb.fill.hasTagName(sibling, 'br')) {
+      continue;
+    }
+
+    // We only expect <p> and <label> tags to contain the full label text.
+    if (__gCrWeb.fill.hasTagName(sibling, 'p') ||
+        __gCrWeb.fill.hasTagName(sibling, 'label')) {
+      inferredLabel = __gCrWeb.fill.findChildText(sibling);
+    }
+    break;
+  }
+  return inferredLabel.trim();
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * a previous sibling of |element|,
+ * e.g. Some Text <input ...>
+ * or   Some <span>Text</span> <input ...>
+ * or   <p>Some Text</p><input ...>
+ * or   <label>Some Text</label> <input ...>
+ * or   Some Text <img><input ...>
+ * or   <b>Some Text</b><br/> <input ...>.
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromPrevious(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromPrevious = function(element) {
+  return __gCrWeb.fill.inferLabelFromSibling(element, false);
+};
+
+/**
+ * Same as InferLabelFromPrevious(), but in the other direction.
+ * Useful for cases like: <span><input type="checkbox">Label For Checkbox</span>
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromNext(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromNext = function(element) {
+  return __gCrWeb.fill.inferLabelFromSibling(element, true);
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * the placeholder attribute.
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromPlaceholder(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromPlaceholder = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  return element.placeholder || element.getAttribute('placeholder') || '';
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * the value attribute when it is present and user has not typed in (if
+ * element's value attribute is same as the element's value).
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromValueAttr(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.InferLabelFromValueAttr = function(element) {
+  if (!element || !element.value || !element.hasAttribute('value') ||
+      element.value !== element.getAttribute('value')) {
+    return '';
+  }
+
+  return element.value;
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * enclosing list item, e.g.
+ *     <li>Some Text<input ...><input ...><input ...></li>
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromListItem(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromListItem = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  let parentNode = element.parentNode;
+  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
+         !__gCrWeb.fill.hasTagName(parentNode, 'li')) {
+    parentNode = parentNode.parentNode;
+  }
+
+  if (parentNode && __gCrWeb.fill.hasTagName(parentNode, 'li')) {
+    return __gCrWeb.fill.findChildText(parentNode);
+  }
+
+  return '';
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * surrounding table structure,
+ * e.g. <tr><td>Some Text</td><td><input ...></td></tr>
+ * or   <tr><th>Some Text</th><td><input ...></td></tr>
+ * or   <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
+ * or   <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr>
+ *
+ * It is based on the logic in
+ *    string16 InferLabelFromTableColumn(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromTableColumn = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  let parentNode = element.parentNode;
+  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
+         !__gCrWeb.fill.hasTagName(parentNode, 'td')) {
+    parentNode = parentNode.parentNode;
+  }
+
+  if (!parentNode) {
+    return '';
+  }
+
+  // Check all previous siblings, skipping non-element nodes, until we find a
+  // non-empty text block.
+  let inferredLabel = '';
+  let previous = parentNode.previousSibling;
+  while (inferredLabel.length === 0 && previous) {
+    if (__gCrWeb.fill.hasTagName(previous, 'td') ||
+        __gCrWeb.fill.hasTagName(previous, 'th')) {
+      inferredLabel = __gCrWeb.fill.findChildText(previous);
+    }
+    previous = previous.previousSibling;
+  }
+
+  return inferredLabel;
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * surrounding table structure,
+ * e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr>
+ *
+ * If there are multiple cells and the row with the input matches up with the
+ * previous row, then look for a specific cell within the previous row.
+ * e.g. <tr><td>Input 1 label</td><td>Input 2 label</td></tr>
+ *  <tr><td><input name="input 1"></td><td><input name="input2"></td></tr>
+ *
+ * It is based on the logic in
+ *     string16 InferLabelFromTableRow(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromTableRow = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  let cell = element.parentNode;
+  while (cell) {
+    if (cell.nodeType === Node.ELEMENT_NODE &&
+        __gCrWeb.fill.hasTagName(cell, 'td')) {
+      break;
+    }
+    cell = cell.parentNode;
+  }
+
+  // Not in a cell - bail out.
+  if (!cell) {
+    return '';
+  }
+
+  // Count the cell holding |element|.
+  let cellCount = cell.colSpan;
+  let cellPosition = 0;
+  let cellPositionEnd = cellCount - 1;
+
+  // Count cells to the left to figure out |element|'s cell's position.
+  let cellIterator = cell.previousSibling;
+  while (cellIterator) {
+    if (cellIterator.nodeType === Node.ELEMENT_NODE &&
+        __gCrWeb.fill.hasTagName(cellIterator, 'td')) {
+      cellPosition += cellIterator.colSpan;
+    }
+    cellIterator = cellIterator.previousSibling;
+  }
+
+  // Count cells to the right.
+  cellIterator = cell.nextSibling;
+  while (cellIterator) {
+    if (cellIterator.nodeType === Node.ELEMENT_NODE &&
+        __gCrWeb.fill.hasTagName(cellIterator, 'td')) {
+      cellCount += cellIterator.colSpan;
+    }
+    cellIterator = cellIterator.nextSibling;
+  }
+
+  // Combine left + right.
+  cellCount += cellPosition;
+  cellPositionEnd += cellPosition;
+
+  // Find the current row.
+  let parentNode = element.parentNode;
+  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
+         !__gCrWeb.fill.hasTagName(parentNode, 'tr')) {
+    parentNode = parentNode.parentNode;
+  }
+
+  if (!parentNode) {
+    return '';
+  }
+
+  // Now find the previous row.
+  let rowIt = parentNode.previousSibling;
+  while (rowIt) {
+    if (rowIt.nodeType === Node.ELEMENT_NODE &&
+        __gCrWeb.fill.hasTagName(parentNode, 'tr')) {
+      break;
+    }
+    rowIt = rowIt.previousSibling;
+  }
+
+  // If there exists a previous row, check its cells and size. If they align
+  // with the current row, infer the label from the cell above.
+  if (rowIt) {
+    let matchingCell = null;
+    let prevRowCount = 0;
+    let prevRowIt = rowIt.firstChild;
+    while (prevRowIt) {
+      if (prevRowIt.nodeType === Node.ELEMENT_NODE) {
+        if (__gCrWeb.fill.hasTagName(prevRowIt, 'td') ||
+            __gCrWeb.fill.hasTagName(prevRowIt, 'th')) {
+          const span = prevRowIt.colSpan;
+          const prevRowCountEnd = prevRowCount + span - 1;
+          if (prevRowCount === cellPosition &&
+              prevRowCountEnd === cellPositionEnd) {
+            matchingCell = prevRowIt;
+          }
+          prevRowCount += span;
+        }
+      }
+      prevRowIt = prevRowIt.nextSibling;
+    }
+    if (cellCount === prevRowCount && matchingCell) {
+      const inferredLabel = __gCrWeb.fill.findChildText(matchingCell);
+      if (inferredLabel.length > 0) {
+        return inferredLabel;
+      }
+    }
+  }
+
+  // If there is no previous row, or if the previous row and current row do not
+  // align, check all previous siblings, skipping non-element nodes, until we
+  // find a non-empty text block.
+  let inferredLabel = '';
+  let previous = parentNode.previousSibling;
+  while (inferredLabel.length === 0 && previous) {
+    if (__gCrWeb.fill.hasTagName(previous, 'tr')) {
+      inferredLabel = __gCrWeb.fill.findChildText(previous);
+    }
+    previous = previous.previousSibling;
+  }
+  return inferredLabel;
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * an enclosing label.
+ * e.g. <label>Some Text<span><input ...></span></label>
+ *
+ * It is based on the logic in
+ *    string16 InferLabelFromEnclosingLabel(
+ *        const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromEnclosingLabel = function(element) {
+  if (!element) {
+    return '';
+  }
+  let node = element.parentNode;
+  while (node && !__gCrWeb.fill.hasTagName(node, 'label')) {
+    node = node.parentNode;
+  }
+  if (node) {
+    return __gCrWeb.fill.findChildText(node);
+  }
+  return '';
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * a surrounding div table,
+ * e.g. <div>Some Text<span><input ...></span></div>
+ * e.g. <div>Some Text</div><div><input ...></div>
+ *
+ * Contrary to the other InferLabelFrom* functions, this functions walks up
+ * the DOM tree from the original input, instead of down from the surrounding
+ * tag. While doing so, if a <label> or text node sibling are found along the
+ * way, a label is inferred from them directly. For example, <div>First
+ * name<div><input></div>Last name<div><input></div></div> infers "First name"
+ * and "Last name" for the two inputs, respectively, by picking up the text
+ * nodes on the way to the surrounding div. Without doing so, the label of both
+ * inputs becomes "First nameLast name".
+ *
+ * It is based on the logic in
+ *    string16 InferLabelFromDivTable(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromDivTable = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  let node = element.parentNode;
+  let lookingForParent = true;
+  const divsToSkip = [];
+
+  // Search the sibling and parent <div>s until we find a candidate label.
+  let inferredLabel = '';
+  while (inferredLabel.length === 0 && node) {
+    if (__gCrWeb.fill.hasTagName(node, 'div')) {
+      if (lookingForParent) {
+        inferredLabel =
+            __gCrWeb.fill.findChildTextWithIgnoreList(node, divsToSkip);
+      } else {
+        inferredLabel = __gCrWeb.fill.findChildText(node);
+      }
+      // Avoid sibling DIVs that contain autofillable fields.
+      if (!lookingForParent && inferredLabel.length > 0) {
+        const resultElement = node.querySelector('input, select, textarea');
+        if (resultElement) {
+          inferredLabel = '';
+          let addDiv = true;
+          for (let i = 0; i < divsToSkip.length; ++i) {
+            if (node === divsToSkip[i]) {
+              addDiv = false;
+              break;
+            }
+          }
+          if (addDiv) {
+            divsToSkip.push(node);
+          }
+        }
+      }
+
+      lookingForParent = false;
+    } else if (!lookingForParent) {
+      // Infer a label from text nodes and unassigned <label> siblings.
+      if (__gCrWeb.fill.hasTagName(node, 'label') && !node.control) {
+        inferredLabel = __gCrWeb.fill.findChildText(node);
+      } else if (node.nodeType === Node.TEXT_NODE) {
+        inferredLabel = __gCrWeb.fill.nodeValue(node).trim();
+      }
+    } else if (__gCrWeb.fill.isTraversableContainerElement(node)) {
+      // If the element is in a non-div container, its label most likely is too.
+      break;
+    }
+
+    if (!node.previousSibling) {
+      // If there are no more siblings, continue walking up the tree.
+      lookingForParent = true;
+    }
+
+    if (lookingForParent) {
+      node = node.parentNode;
+    } else {
+      node = node.previousSibling;
+    }
+  }
+
+  return inferredLabel;
+};
+
+/**
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * a surrounding definition list,
+ * e.g. <dl><dt>Some Text</dt><dd><input ...></dd></dl>
+ * e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
+ *
+ * It is based on the logic in
+ *    string16 InferLabelFromDefinitionList(
+ *        const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
+__gCrWeb.fill.inferLabelFromDefinitionList = function(element) {
+  if (!element) {
+    return '';
+  }
+
+  let parentNode = element.parentNode;
+  while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
+         !__gCrWeb.fill.hasTagName(parentNode, 'dd')) {
+    parentNode = parentNode.parentNode;
+  }
+
+  if (!parentNode || !__gCrWeb.fill.hasTagName(parentNode, 'dd')) {
+    return '';
+  }
+
+  // Skip by any intervening text nodes.
+  let previous = parentNode.previousSibling;
+  while (previous && previous.nodeType === Node.TEXT_NODE) {
+    previous = previous.previousSibling;
+  }
+
+  if (!previous || !__gCrWeb.fill.hasTagName(previous, 'dt')) {
+    return '';
+  }
+
+  return __gCrWeb.fill.findChildText(previous);
+};
+
+/**
+ * Infers corresponding label for |element| from surrounding context in the DOM,
+ * e.g. the contents of the preceding <p> tag or text element.
+ *
+ * It is based on the logic in
+ *    string16 InferLabelForElement(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The inferred label of element, or '' if none could be found.
+ */
+__gCrWeb.fill.inferLabelForElement = function(element) {
+  let inferredLabel;
+  if (__gCrWeb.fill.isCheckableElement(element)) {
+    inferredLabel = __gCrWeb.fill.inferLabelFromNext(element);
+    if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+      return inferredLabel;
+    }
+  }
+
+  inferredLabel = __gCrWeb.fill.inferLabelFromPrevious(element);
+  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+    return inferredLabel;
+  }
+
+  // If we didn't find a label, check for the placeholder case.
+  inferredLabel = __gCrWeb.fill.inferLabelFromPlaceholder(element);
+  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+    return inferredLabel;
+  }
+
+  // If we didn't find a placeholder, check for the aria-label case.
+  inferredLabel = __gCrWeb.fill.getAriaLabel(element);
+  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+    return inferredLabel;
+  }
+
+  // For all other searches that involve traversing up the tree, the search
+  // order is based on which tag is the closest ancestor to |element|.
+  const tagNames = __gCrWeb.fill.ancestorTagNames(element);
+  const seenTagNames = {};
+  for (let index = 0; index < tagNames.length; ++index) {
+    const tagName = tagNames[index];
+    if (tagName in seenTagNames) {
+      continue;
+    }
+
+    seenTagNames[tagName] = true;
+    if (tagName === 'LABEL') {
+      inferredLabel = __gCrWeb.fill.inferLabelFromEnclosingLabel(element);
+    } else if (tagName === 'DIV') {
+      inferredLabel = __gCrWeb.fill.inferLabelFromDivTable(element);
+    } else if (tagName === 'TD') {
+      inferredLabel = __gCrWeb.fill.inferLabelFromTableColumn(element);
+      if (!__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+        inferredLabel = __gCrWeb.fill.inferLabelFromTableRow(element);
+      }
+    } else if (tagName === 'DD') {
+      inferredLabel = __gCrWeb.fill.inferLabelFromDefinitionList(element);
+    } else if (tagName === 'LI') {
+      inferredLabel = __gCrWeb.fill.inferLabelFromListItem(element);
+    } else if (tagName === 'FIELDSET') {
+      break;
+    }
+
+    if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+      return inferredLabel;
+    }
+  }
+  // If we didn't find a label, check for the value attribute case.
+  inferredLabel = __gCrWeb.fill.InferLabelFromValueAttr(element);
+  if (__gCrWeb.fill.IsLabelValid(inferredLabel)) {
+    return inferredLabel;
+  }
+
+  return '';
+};
diff --git a/components/autofill/ios/form_util/resources/fill_element_inference_util.js b/components/autofill/ios/form_util/resources/fill_element_inference_util.js
new file mode 100644
index 0000000..80d766ab
--- /dev/null
+++ b/components/autofill/ios/form_util/resources/fill_element_inference_util.js
@@ -0,0 +1,289 @@
+// 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.
+
+/**
+ * Returns is the tag of an |element| is tag.
+ *
+ * It is based on the logic in
+ *     bool HasTagName(const WebNode& node, const blink::WebString& tag)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {Node} node Node to examine.
+ * @param {string} tag Tag name.
+ * @return {boolean} Whether the tag of node is tag.
+ */
+__gCrWeb.fill.hasTagName = function(node, tag) {
+  return node.nodeType === Node.ELEMENT_NODE &&
+      /** @type {Element} */ (node).tagName === tag.toUpperCase();
+};
+
+/**
+ * Checks if an element is autofillable.
+ *
+ * It is based on the logic in
+ *     bool IsAutofillableElement(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {boolean} Whether element is one of the element types that can be
+ *     autofilled.
+ */
+__gCrWeb.fill.isAutofillableElement = function(element) {
+  return __gCrWeb.fill.isAutofillableInputElement(element) ||
+      __gCrWeb.fill.isSelectElement(element) ||
+      __gCrWeb.fill.isTextAreaElement(element);
+};
+
+/**
+ * Trims whitespace from the start of the input string.
+ * Simplified version of string_util::TrimWhitespace.
+ * @param {string} input String to trim.
+ * @return {string} The |input| string without leading whitespace.
+ */
+__gCrWeb.fill.trimWhitespaceLeading = function(input) {
+  return input.replace(/^\s+/gm, '');
+};
+
+/**
+ * Trims whitespace from the end of the input string.
+ * Simplified version of string_util::TrimWhitespace.
+ * @param {string} input String to trim.
+ * @return {string} The |input| string without trailing whitespace.
+ */
+__gCrWeb.fill.trimWhitespaceTrailing = function(input) {
+  return input.replace(/\s+$/gm, '');
+};
+
+/**
+ * Appends |suffix| to |prefix| so that any intermediary whitespace is collapsed
+ * to a single space.  If |force_whitespace| is true, then the resulting string
+ * is guaranteed to have a space between |prefix| and |suffix|.  Otherwise, the
+ * result includes a space only if |prefix| has trailing whitespace or |suffix|
+ * has leading whitespace.
+ *
+ * A few examples:
+ *     CombineAndCollapseWhitespace('foo', 'bar', false)       -> 'foobar'
+ *     CombineAndCollapseWhitespace('foo', 'bar', true)        -> 'foo bar'
+ *     CombineAndCollapseWhitespace('foo ', 'bar', false)      -> 'foo bar'
+ *     CombineAndCollapseWhitespace('foo', ' bar', false)      -> 'foo bar'
+ *     CombineAndCollapseWhitespace('foo', ' bar', true)       -> 'foo bar'
+ *     CombineAndCollapseWhitespace('foo   ', '   bar', false) -> 'foo bar'
+ *     CombineAndCollapseWhitespace(' foo', 'bar ', false)     -> ' foobar '
+ *     CombineAndCollapseWhitespace(' foo', 'bar ', true)      -> ' foo bar '
+ *
+ * It is based on the logic in
+ * const string16 CombineAndCollapseWhitespace(const string16& prefix,
+ *                                             const string16& suffix,
+ *                                             bool force_whitespace)
+ * @param {string} prefix The prefix string in the string combination.
+ * @param {string} suffix The suffix string in the string combination.
+ * @param {boolean} forceWhitespace A boolean indicating if whitespace should
+ *     be added as separator in the combination.
+ * @return {string} The combined string.
+ */
+__gCrWeb.fill.combineAndCollapseWhitespace = function(
+    prefix, suffix, forceWhitespace) {
+  const prefixTrimmed = __gCrWeb.fill.trimWhitespaceTrailing(prefix);
+  const prefixTrailingWhitespace = prefixTrimmed !== prefix;
+  const suffixTrimmed = __gCrWeb.fill.trimWhitespaceLeading(suffix);
+  const suffixLeadingWhitespace = suffixTrimmed !== suffix;
+  if (prefixTrailingWhitespace || suffixLeadingWhitespace || forceWhitespace) {
+    return prefixTrimmed + ' ' + suffixTrimmed;
+  } else {
+    return prefixTrimmed + suffixTrimmed;
+  }
+};
+
+/**
+ * This is a helper function for the findChildText() function (see below).
+ * Search depth is limited with the |depth| parameter.
+ *
+ * Based on form_autofill_util::FindChildTextInner().
+ *
+ * @param {Node} node The node to fetch the text content from.
+ * @param {number} depth The maximum depth to descend on the DOM.
+ * @param {Array<Node>} divsToSkip List of <div> tags to ignore if encountered.
+ * @return {string} The discovered and adapted string.
+ */
+__gCrWeb.fill.findChildTextInner = function(node, depth, divsToSkip) {
+  if (depth <= 0 || !node) {
+    return '';
+  }
+
+  // Skip over comments.
+  if (node.nodeType === Node.COMMENT_NODE) {
+    return __gCrWeb.fill.findChildTextInner(
+        node.nextSibling, depth - 1, divsToSkip);
+  }
+
+  if (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {
+    return '';
+  }
+
+  // Ignore elements known not to contain inferable labels.
+  let skipNode = false;
+  if (node.nodeType === Node.ELEMENT_NODE) {
+    if (node.tagName === 'OPTION') {
+      return '';
+    }
+    if (__gCrWeb.form.isFormControlElement(/** @type {Element} */ (node))) {
+      const input = /** @type {FormControlElement} */ (node);
+      if (__gCrWeb.fill.isAutofillableElement(input)) {
+        return '';
+      }
+    }
+    skipNode = node.tagName === 'SCRIPT' || node.tagName === 'NOSCRIPT';
+  }
+
+  if (node.tagName === 'DIV') {
+    for (let i = 0; i < divsToSkip.length; ++i) {
+      if (node === divsToSkip[i]) {
+        return '';
+      }
+    }
+  }
+
+  // Extract the text exactly at this node.
+  let nodeText = '';
+  if (!skipNode) {
+    nodeText = __gCrWeb.fill.nodeValue(node);
+    if (node.nodeType === Node.TEXT_NODE && !nodeText) {
+      // In the C++ version, this text node would have been stripped completely.
+      // Just pass the buck.
+      return __gCrWeb.fill.findChildTextInner(
+          node.nextSibling, depth, divsToSkip);
+    }
+
+    // Recursively compute the children's text.
+    // Preserve inter-element whitespace separation.
+    const childText = __gCrWeb.fill.findChildTextInner(
+        node.firstChild, depth - 1, divsToSkip);
+    let addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
+    // Emulate apparently incorrect Chromium behavior tracked in
+    // https://crbug.com/239819.
+    addSpace = false;
+    nodeText = __gCrWeb.fill.combineAndCollapseWhitespace(
+        nodeText, childText, addSpace);
+  }
+
+  // Recursively compute the siblings' text.
+  // Again, preserve inter-element whitespace separation.
+  const siblingText =
+      __gCrWeb.fill.findChildTextInner(node.nextSibling, depth - 1, divsToSkip);
+  let addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
+  // Emulate apparently incorrect Chromium behavior tracked in
+  // https://crbug.com/239819.
+  addSpace = false;
+  nodeText = __gCrWeb.fill.combineAndCollapseWhitespace(
+      nodeText, siblingText, addSpace);
+
+  return nodeText;
+};
+
+/**
+ * Same as findChildText() below, but with a list of div nodes to skip.
+ *
+ * It is based on the logic in
+ *    string16 FindChildTextWithIgnoreList(
+ *        const WebNode& node,
+ *        const std::set<WebNode>& divs_to_skip)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {Node} node A node of which the child text will be return.
+ * @param {Array<Node>} divsToSkip List of <div> tags to ignore if encountered.
+ * @return {string} The child text.
+ */
+__gCrWeb.fill.findChildTextWithIgnoreList = function(node, divsToSkip) {
+  if (node.nodeType === Node.TEXT_NODE) {
+    return __gCrWeb.fill.nodeValue(node);
+  }
+
+  const child = node.firstChild;
+  const kChildSearchDepth = 10;
+  let nodeText =
+      __gCrWeb.fill.findChildTextInner(child, kChildSearchDepth, divsToSkip);
+  nodeText = nodeText.trim();
+  return nodeText;
+};
+
+/**
+ * Returns the aggregated values of the descendants of |element| that are
+ * non-empty text nodes.
+ *
+ * It is based on the logic in
+ *    string16 FindChildText(const WebNode& node)
+ * chromium/src/components/autofill/content/renderer/form_autofill_util.cc,
+ * which is a faster alternative to |innerText()| for performance critical
+ * operations.
+ *
+ * @param {Node} node A node of which the child text will be return.
+ * @return {string} The child text.
+ */
+__gCrWeb.fill.findChildText = function(node) {
+  return __gCrWeb.fill.findChildTextWithIgnoreList(node, []);
+};
+
+/**
+ * Returns true if |node| is an element and it is a container type that
+ * inferLabelForElement() can traverse.
+ *
+ * It is based on the logic in
+ *     bool IsTraversableContainerElement(const WebNode& node);
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {!Node} node The node to be examined.
+ * @return {boolean} Whether it can be traversed.
+ */
+__gCrWeb.fill.isTraversableContainerElement = function(node) {
+  if (node.nodeType !== Node.ELEMENT_NODE) {
+    return false;
+  }
+
+  const tagName = /** @type {Element} */ (node).tagName;
+  return (
+      tagName === 'DD' || tagName === 'DIV' || tagName === 'FIELDSET' ||
+      tagName === 'LI' || tagName === 'TD' || tagName === 'TABLE');
+};
+
+/**
+ * Returns the element type for all ancestor nodes in CAPS, starting with the
+ * parent node.
+ *
+ * It is based on the logic in
+ *    std::vector<std::string> AncestorTagNames(
+ *        const WebFormControlElement& element);
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {Array} The element types for all ancestors.
+ */
+__gCrWeb.fill.ancestorTagNames = function(element) {
+  const tagNames = [];
+  let parentNode = element.parentNode;
+  while (parentNode) {
+    if (parentNode.nodeType === Node.ELEMENT_NODE) {
+      tagNames.push(parentNode.tagName);
+    }
+    parentNode = parentNode.parentNode;
+  }
+  return tagNames;
+};
+
+/**
+ * Helper for |InferLabelForElement()| that tests if an inferred label is valid
+ * or not. A valid label is a label that does not only contains special
+ * characters.
+ *
+ * It is based on the logic in
+ *     bool IsLabelValid(base::StringPiece16 inferred_label,
+ *         const std::vector<char16_t>& stop_words)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ * The list of characters that are considered special is hard-coded in a regexp.
+ *
+ * @param {string} label An element to examine.
+ * @return {boolean} Whether the label contains not special characters.
+ */
+__gCrWeb.fill.IsLabelValid = function(label) {
+  return label.search(/[^ *:()\u2013-]/) >= 0;
+};
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index dd0a481..043f732 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -743,6 +743,15 @@
     Virtual card
   </message>
   <if expr="is_android">
+    <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONTENT_DESCRIPTION" desc="The description of the virtual card enrollment dialog for the accessbility screen reader." formatter_data="android_java">
+      Virtual card enrollment
+    </message>
+    <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_FULL_HEIGHT_CONTENT_DESCRIPTION" desc="The description of the full height virtual card enrollment dialog for the accessbility screen reader." formatter_data="android_java">
+      Virtual card enrollment opened at full height
+    </message>
+    <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CLOSED_DESCRIPTION" desc="The description of the virtual card enrollment dialog closing for the accessbility screen reader." formatter_data="android_java">
+      Virtual card enrollment closed
+    </message>
     <message name="IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT" desc="Text to be displayed in the snackbar shown after a virtual card number id autofilled.">
       Virtual card number not filled in?
     </message>
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CLOSED_DESCRIPTION.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CLOSED_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..e19759c6
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CLOSED_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+919f9e717246e6fe17e7041afe06c21701b8f3f0
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONTENT_DESCRIPTION.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONTENT_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..e19759c6
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_CONTENT_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+919f9e717246e6fe17e7041afe06c21701b8f3f0
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_FULL_HEIGHT_CONTENT_DESCRIPTION.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_FULL_HEIGHT_CONTENT_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..e19759c6
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLL_FULL_HEIGHT_CONTENT_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+919f9e717246e6fe17e7041afe06c21701b8f3f0
\ No newline at end of file
diff --git a/components/consent_auditor/COMMON_METADATA b/components/consent_auditor/COMMON_METADATA
deleted file mode 100644
index db7a5c4a..0000000
--- a/components/consent_auditor/COMMON_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
-  component: "Privacy"
-}
diff --git a/components/consent_auditor/DIR_METADATA b/components/consent_auditor/DIR_METADATA
index c75f2f8..4a58e65 100644
--- a/components/consent_auditor/DIR_METADATA
+++ b/components/consent_auditor/DIR_METADATA
@@ -1 +1 @@
-mixins: "//components/consent_auditor/COMMON_METADATA"
+mixins: "//components/sync/COMMON_METADATA"
diff --git a/components/consent_auditor/OWNERS b/components/consent_auditor/OWNERS
index 745d3ad..261ab18 100644
--- a/components/consent_auditor/OWNERS
+++ b/components/consent_auditor/OWNERS
@@ -1,3 +1 @@
-dullweber@chromium.org
-markusheintz@chromium.org
-msramek@chromium.org
+file://components/sync/OWNERS
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index cbe77edd..700a2af 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -114,6 +114,11 @@
 
 _cronet_version_header_include_dir = "$target_gen_dir/cronet_version_header"
 
+proto_java_library("flags_java_proto") {
+  proto_path = "."
+  sources = [ "proto/flags.proto" ]
+}
+
 proto_library("request_context_config_proto") {
   sources = [ "proto/request_context_config.proto" ]
 }
@@ -380,6 +385,7 @@
 
 cronet_impl_native_java_deps_to_package = [
   ":cronet_urlconnection_impl_java",
+  ":flags_java_proto",
   ":request_context_config_java_proto",
   "//base:base_java",
   "//base:jni_java",
@@ -391,6 +397,7 @@
 # cronet_impl_native_base_java.jar - native implementation of the Cronet engine.
 android_library("cronet_impl_native_base_java") {
   sources = [
+    "java/src/org/chromium/net/httpflags/HttpFlagsLoader.java",
     "java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
     "java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
     "java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
@@ -968,12 +975,14 @@
     "test/javatests/src/org/chromium/net/TestRequestFinishedListener.java",
     "test/javatests/src/org/chromium/net/TestUploadDataProvider.java",
     "test/javatests/src/org/chromium/net/TestUrlRequestCallback.java",
+    "test/javatests/src/org/chromium/net/httpflags/HttpFlagsInterceptor.java",
     "test/javatests/src/org/chromium/net/impl/CronetManifestInterceptor.java",
   ]
   deps = [
            ":cronet_api_java",
            ":cronet_impl_all_java",
            ":cronet_test_apk_java",
+           ":flags_java_proto",
            "//base:base_java",
            "//base:base_java_test_support",
            "//base:jni_java",
@@ -1015,6 +1024,7 @@
   ":cronet_common_javatests",
   ":cronet_fake_javatests",
   ":cronet_test_apk_java",
+  ":flags_java_proto",
   "//base:base_java",
   "//base:jni_java",
   "//base:base_java_test_support",
@@ -1071,6 +1081,7 @@
     "test/javatests/src/org/chromium/net/UrlResponseInfoTest.java",
     "test/javatests/src/org/chromium/net/apihelpers/ContentTypeParametersParserTest.java",
     "test/javatests/src/org/chromium/net/apihelpers/UploadDataProvidersTest.java",
+    "test/javatests/src/org/chromium/net/httpflags/HttpFlagsLoaderTest.java",
     "test/javatests/src/org/chromium/net/impl/CronetLoggerTest.java",
     "test/javatests/src/org/chromium/net/impl/CronetManifestTest.java",
     "test/javatests/src/org/chromium/net/urlconnection/CronetBufferedOutputStreamTest.java",
@@ -1092,6 +1103,7 @@
     ":cronet_impl_all_java",
     ":cronet_urlconnection_impl_java",
     "//third_party/android_deps:guava_android_java",
+    "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/android_sdk:android_test_base_java",
     "//third_party/androidx:androidx_test_ext_junit_java",
     "//third_party/androidx:androidx_test_runner_java",
diff --git a/components/cronet/android/java/src/org/chromium/net/httpflags/HttpFlagsLoader.java b/components/cronet/android/java/src/org/chromium/net/httpflags/HttpFlagsLoader.java
new file mode 100644
index 0000000..a907f8a
--- /dev/null
+++ b/components/cronet/android/java/src/org/chromium/net/httpflags/HttpFlagsLoader.java
@@ -0,0 +1,130 @@
+// 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.
+
+package org.chromium.net.httpflags;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Utilities for loading HTTP flags.
+ *
+ * <p>HTTP flags are a generic mechanism by which the host system (i.e. the Android system image)
+ * can provide values for a variety of configuration knobs to alter the behavior of the HTTP client
+ * stack. The idea is that the host system can use some kind of centralized configuration mechanism
+ * to remotely push changes to these settings while collecting data on the results. This in turn
+ * enables A/B experiments, progressive configuration rollouts, etc.
+ *
+ * <p>Currently, the interface with the host system is defined as follows:
+ * <ol>
+ * <li>The Android system image must provide an Android app that exposes a service matching the
+ *     {@link #FLAGS_FILE_PROVIDER_INTENT_ACTION} action.
+ * <li>That Android app must expose a directory named after {@link #FLAGS_FILE_DIR_NAME} under the
+ *     app's {@link ApplicationInfo#deviceProtectedDataDir}.
+ * <li>That directory must contain a file named after {@link #FLAGS_FILE_NAME} that must be readable
+ *     by the process running {@link #load}.
+ * <li>The flag values are obtained from the contents of that file. The format is a binary proto
+ *     that can be read through {@link Flags#parseDelimitedFrom} - see `flags.proto` for details.
+ * </ol>
+ *
+ * @see HttpFlagsInterceptor
+ */
+final class HttpFlagsLoader {
+    private HttpFlagsLoader() {}
+
+    @VisibleForTesting
+    static final String FLAGS_FILE_PROVIDER_INTENT_ACTION = "android.net.http.FLAGS_FILE_PROVIDER";
+    @VisibleForTesting
+    static final String FLAGS_FILE_DIR_NAME = "app_httpflags";
+    @VisibleForTesting
+    static final String FLAGS_FILE_NAME = "flags.binarypb";
+
+    private static final String TAG = "HttpFlagsLoader";
+
+    /**
+     * Locates and loads the HTTP flags file from the host system.
+     *
+     * Note that this is an expensive call.
+     *
+     * @return The contents of the flags file, or null if the flags file could not be loaded for any
+     * reason. In the latter case, the callee will take care of logging the failure.
+     */
+    @Nullable
+    public static Flags load(Context context) {
+        try {
+            ApplicationInfo providerApplicationInfo = getProviderApplicationInfo(context);
+            if (providerApplicationInfo == null) return null;
+            Log.d(TAG, "Found application exporting HTTP flags: %s",
+                    providerApplicationInfo.packageName);
+
+            File flagsFile = getFlagsFileFromProvider(context, providerApplicationInfo);
+            Log.d(TAG, "HTTP flags file path: %s", flagsFile.getAbsolutePath());
+
+            Flags flags = loadFlagsFile(flagsFile);
+            if (flags == null) return null;
+            Log.d(TAG, "Successfully loaded HTTP flags: %s", flags);
+
+            return flags;
+        } catch (RuntimeException exception) {
+            Log.e(TAG, "Unable to load HTTP flags file", exception);
+            return null;
+        }
+    }
+
+    @Nullable
+    private static ApplicationInfo getProviderApplicationInfo(Context context) {
+        ResolveInfo resolveInfo = context.getPackageManager().resolveService(
+                new Intent(FLAGS_FILE_PROVIDER_INTENT_ACTION),
+                // Make sure we only read flags files that are written by a package from the system
+                // image. This prevents random third-party apps from being able to inject flags into
+                // other apps, which would be a security risk.
+                PackageManager.MATCH_SYSTEM_ONLY);
+        if (resolveInfo == null) {
+            Log.w(TAG,
+                    "Unable to resolve the HTTP flags file provider package. This is expected if "
+                            + "the host system is not set up to provide HTTP flags.");
+            return null;
+        }
+
+        return resolveInfo.serviceInfo.applicationInfo;
+    }
+
+    private static File getFlagsFileFromProvider(
+            Context context, ApplicationInfo providerApplicationInfo) {
+        return new File(new File(new File(Build.VERSION.SDK_INT >= 24
+                                                 ? providerApplicationInfo.deviceProtectedDataDir
+                                                 : providerApplicationInfo.dataDir),
+                                FLAGS_FILE_DIR_NAME),
+                FLAGS_FILE_NAME);
+    }
+
+    @Nullable
+    private static Flags loadFlagsFile(File file) {
+        try (FileInputStream fileInputStream = new FileInputStream(file)) {
+            return Flags.parseDelimitedFrom(fileInputStream);
+        } catch (FileNotFoundException exception) {
+            Log.w(TAG,
+                    "HTTP flags file `%s` is missing. This is expected if HTTP flags functionality "
+                            + "is currently disabled in the host system.",
+                    file.getPath());
+            return null;
+        } catch (IOException exception) {
+            throw new RuntimeException("Unable to read HTTP flags file", exception);
+        }
+    }
+}
diff --git a/components/cronet/android/proto/flags.proto b/components/cronet/android/proto/flags.proto
new file mode 100644
index 0000000..83f381096
--- /dev/null
+++ b/components/cronet/android/proto/flags.proto
@@ -0,0 +1,61 @@
+// Describes the proto schema for HTTP flags.
+//
+// IMPORTANT: a copy of the proto schema described here is used by the HTTP
+// flags producer, which is the responsibility of the host system. Be very
+// careful about backward compatibility implications of any changes made in this
+// file.
+
+syntax = "proto2";
+
+package org.chromium.net.httpflags;
+
+option java_package = "org.chromium.net.httpflags";
+option java_multiple_files = true;
+
+// Describes the value that an HTTP flag should have, based on various criteria
+// depending on the context in which the flag is used.
+message FlagValue {
+  // A possible value for this flag, along with a set of constraints that have
+  // to be met for that value to be used.
+  message ConstrainedValue {
+    // App selector: only apply this value to applications whose package ID
+    // matches the value of this field, e.g. "com.google.foo".
+    // If not set, matches all apps.
+    optional string app_id = 1;
+
+    // Only apply this value to client libraries running at least this version.
+    //
+    // Currently this refers to Cronet versions. The semantics of this field are
+    // the same as the Finch `variations.Study.Filter.min_version` field, that
+    // is:
+    //
+    // The minimum Cronet version, allowing a trailing '*' character for pattern
+    // matching. Inclusive. (To check for a match, iterate over each component
+    // checking >= until a * or end of string is reached.) Ex: "17.0.963.46",
+    // "17.0.963.*", "17.*"
+    //
+    // If not set, matches all versions.
+    optional string min_version = 2;
+
+    // If none of these fields are set, the flag is deemed to be unset.
+    oneof value {
+      bool bool_value = 3;
+      int64 int_value = 4;
+      float float_value = 5;
+      string string_value = 6;
+      bytes bytes_value = 7;
+    }
+  }
+
+  // Each entry in this list is tried in turn, and the first entry to match
+  // determines the flag value. If no entries match, the flag is deemed to be
+  // unset.
+  repeated ConstrainedValue constrained_values = 8;
+}
+
+// The format of the HTTP flags file is defined as the binary representation of
+// an instance of this proto.
+message Flags {
+  // The key is the name of the flag. For example, "Cronet_log_me".
+  map<string, FlagValue> flags = 1;
+}
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
index 9b615c4..ae320bdf38 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
@@ -15,6 +15,7 @@
 import android.os.Build;
 import android.os.StrictMode;
 
+import androidx.annotation.Nullable;
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.rules.TestRule;
@@ -24,6 +25,8 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.PathUtils;
+import org.chromium.net.httpflags.Flags;
+import org.chromium.net.httpflags.HttpFlagsInterceptor;
 import org.chromium.net.impl.JavaCronetProvider;
 import org.chromium.net.impl.NativeCronetProvider;
 import org.chromium.net.impl.UserAgent;
@@ -317,15 +320,18 @@
 
         private final CronetImplementation mImplementation;
         private final ExperimentalCronetEngine.Builder mBuilder;
+        private final MutableContextWrapper mContextWrapperWithoutFlags;
         private final MutableContextWrapper mContextWrapper;
         private final StrictMode.VmPolicy mOldVmPolicy;
 
+        private HttpFlagsInterceptor mHttpFlagsInterceptor;
         private ExperimentalCronetEngine mCronetEngine;
         private boolean mClosed;
 
         private CronetTestFramework(CronetImplementation implementation) {
-            this.mContextWrapper =
+            this.mContextWrapperWithoutFlags =
                     new MutableContextWrapper(ApplicationProvider.getApplicationContext());
+            this.mContextWrapper = new MutableContextWrapper(mContextWrapperWithoutFlags);
             assert sContextWrapper.getBaseContext() == null;
             sContextWrapper.setBaseContext(mContextWrapper);
             this.mBuilder = implementation.createBuilder(sContextWrapper)
@@ -346,6 +352,8 @@
                                                .penaltyDeath()
                                                .build());
             }
+
+            setHttpFlags(null);
         }
 
         /**
@@ -364,14 +372,48 @@
                         "Refusing to intercept context after the Cronet engine has been built");
             }
 
+            mContextWrapperWithoutFlags.setBaseContext(contextInterceptor.interceptContext(
+                    mContextWrapperWithoutFlags.getBaseContext()));
+        }
+
+        /**
+         * Sets the HTTP flags, if any, that the code under test should run with. This affects the
+         * behavior of the {@link Context} that the code under test sees.
+         *
+         * If this method is never called, the default behavior is to simulate the absence of a
+         * flags file. This ensures that the code under test does not end up accidentally using a
+         * flags file from the host system, which would lead to non-deterministic results.
+         *
+         * @param flagsFileContents the contents of the flags file, or null to simulate a missing
+         * file (default behavior).
+         *
+         * @throws IllegalStateException if called after the engine has already been built.
+         * Modifying flags while the code under test is running is always a mistake, because the
+         * code under test won't notice the changes.
+         *
+         * @see org.chromium.net.impl.HttpFlagsLoader
+         * @see HttpFlagsInterceptor
+         */
+        public void setHttpFlags(@Nullable Flags flagsFileContents) {
+            checkNotClosed();
+
+            if (mCronetEngine != null) {
+                throw new IllegalStateException(
+                        "Refusing to replace flags file provider after the Cronet engine has been "
+                        + "built");
+            }
+
+            if (mHttpFlagsInterceptor != null) mHttpFlagsInterceptor.close();
+            mHttpFlagsInterceptor = new HttpFlagsInterceptor(flagsFileContents);
             mContextWrapper.setBaseContext(
-                    contextInterceptor.interceptContext(mContextWrapper.getBaseContext()));
+                    mHttpFlagsInterceptor.interceptContext(mContextWrapperWithoutFlags));
         }
 
         /**
          * @return the context to be used by the Cronet engine
          *
          * @see #interceptContext
+         * @see #setFlagsFileContents
          */
         public Context getContext() {
             checkNotClosed();
@@ -454,6 +496,8 @@
             sContextWrapper.setBaseContext(null);
             mClosed = true;
 
+            if (mHttpFlagsInterceptor != null) mHttpFlagsInterceptor.close();
+
             try {
                 // Run GC and finalizers a few times to pick up leaked closeables
                 for (int i = 0; i < 10; i++) {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsInterceptor.java b/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsInterceptor.java
new file mode 100644
index 0000000..05b81494
--- /dev/null
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsInterceptor.java
@@ -0,0 +1,136 @@
+// 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.
+
+package org.chromium.net.httpflags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Build;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.base.test.util.PackageManagerWrapper;
+import org.chromium.net.ContextInterceptor;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * A {@link ContextInterceptor} that makes the intercepted Context advertise the presence (or
+ * absence) of an HTTP flags file.
+ *
+ * @see org.chromium.net.httpflags.HttpFlagsLoader
+ */
+public final class HttpFlagsInterceptor implements ContextInterceptor, AutoCloseable {
+    private static final String FLAGS_PROVIDER_PACKAGE_NAME =
+            "org.chromium.net.httpflags.HttpFlagsInterceptor.FAKE_PROVIDER_PACKAGE";
+
+    @Nullable
+    private final Flags mFlagsFileContents;
+    private File mDataDir;
+
+    /**
+     * @param flagsFileContents the contents of the flags file, or null to simulate a missing file.
+     */
+    public HttpFlagsInterceptor(@Nullable Flags flagsFileContents) {
+        mFlagsFileContents = flagsFileContents;
+    }
+
+    @Override
+    public Context interceptContext(Context context) {
+        return new HttpFlagsContextWrapper(context);
+    }
+
+    private final class HttpFlagsContextWrapper extends ContextWrapper {
+        HttpFlagsContextWrapper(Context context) {
+            super(context);
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return new PackageManagerWrapper(super.getPackageManager()) {
+                @Override
+                public ResolveInfo resolveService(Intent intent, int flags) {
+                    if (!intent.getAction().equals(
+                                HttpFlagsLoader.FLAGS_FILE_PROVIDER_INTENT_ACTION)) {
+                        return super.resolveService(intent, flags);
+                    }
+
+                    assertThat(flags).isEqualTo(MATCH_SYSTEM_ONLY);
+
+                    if (mFlagsFileContents == null) return null;
+                    createFlagsFile(getBaseContext());
+
+                    ApplicationInfo applicationInfo = new ApplicationInfo();
+                    applicationInfo.packageName = FLAGS_PROVIDER_PACKAGE_NAME;
+                    if (Build.VERSION.SDK_INT >= 24) {
+                        applicationInfo.deviceProtectedDataDir = mDataDir.getAbsolutePath();
+                    } else {
+                        applicationInfo.dataDir = mDataDir.getAbsolutePath();
+                    }
+
+                    ResolveInfo resolveInfo = new ResolveInfo();
+                    resolveInfo.serviceInfo = new ServiceInfo();
+                    resolveInfo.serviceInfo.applicationInfo = applicationInfo;
+                    return resolveInfo;
+                }
+            };
+        }
+    }
+
+    private void createFlagsFile(Context context) {
+        if (mDataDir != null) return;
+        mDataDir = context.getDir("org.chromium.net.httpflags.FakeFlagsFileDataDir."
+                        // Ensure different instances can't interfere with each other (e.g.
+                        // when running multiple tests).
+                        + UUID.randomUUID(),
+                Context.MODE_PRIVATE);
+
+        File flagsFile = getFlagsFile();
+        if (!flagsFile.getParentFile().mkdir()) {
+            throw new RuntimeException("Unable to create flags dir");
+        }
+        try {
+            if (!flagsFile.createNewFile()) throw new RuntimeException("File already exists");
+            try (final FileOutputStream fileOutputStream = new FileOutputStream(flagsFile)) {
+                mFlagsFileContents.writeDelimitedTo(fileOutputStream);
+            }
+        } catch (RuntimeException | IOException exception) {
+            throw new RuntimeException(
+                    "Failed to write fake HTTP flags file " + flagsFile, exception);
+        }
+    }
+
+    @Override
+    public void close() {
+        if (mDataDir == null) return;
+
+        File flagsFile = getFlagsFile();
+        if (!flagsFile.delete()) {
+            throw new RuntimeException("Failed to delete fake HTTP flags file " + flagsFile);
+        }
+        File flagsDir = flagsFile.getParentFile();
+        if (!flagsDir.delete()) {
+            throw new RuntimeException("Failed to delete fake HTTP flags dir " + flagsDir);
+        }
+        if (!mDataDir.delete()) {
+            throw new RuntimeException("Failed to delete fake HTTP flags data dir " + mDataDir);
+        }
+        mDataDir = null;
+    }
+
+    private File getFlagsFile() {
+        return new File(new File(mDataDir, HttpFlagsLoader.FLAGS_FILE_DIR_NAME),
+                HttpFlagsLoader.FLAGS_FILE_NAME);
+    }
+}
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsLoaderTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsLoaderTest.java
new file mode 100644
index 0000000..dd8a6ea1
--- /dev/null
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/httpflags/HttpFlagsLoaderTest.java
@@ -0,0 +1,62 @@
+
+// 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.
+
+package org.chromium.net.httpflags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.Batch;
+import org.chromium.net.CronetTestRule;
+import org.chromium.net.CronetTestRule.CronetTestFramework;
+import org.chromium.net.CronetTestRule.OnlyRunNativeCronet;
+
+/**
+ * Tests {@link HttpFlagsLoader}
+ */
+@Batch(Batch.UNIT_TESTS)
+@RunWith(AndroidJUnit4.class)
+public final class HttpFlagsLoaderTest {
+    @Rule
+    public final CronetTestRule mTestRule = CronetTestRule.withManualEngineStartup();
+
+    public CronetTestFramework mCronetTestFramework;
+    @Before
+    public void setUp() {
+        mCronetTestFramework = mTestRule.getTestFramework();
+    }
+
+    @Test
+    @SmallTest
+    @OnlyRunNativeCronet
+    public void testLoad_returnsNullIfNoFlags() {
+        mCronetTestFramework.setHttpFlags(null);
+        assertThat(HttpFlagsLoader.load(mCronetTestFramework.getContext())).isNull();
+    }
+
+    @Test
+    @SmallTest
+    @OnlyRunNativeCronet
+    public void testLoad_returnsFileFlagContents() {
+        Flags flags = Flags.newBuilder()
+                              .putFlags("test_flag_name",
+                                      FlagValue.newBuilder()
+                                              .addConstrainedValues(
+                                                      FlagValue.ConstrainedValue.newBuilder()
+                                                              .setStringValue("test_flag_value")
+                                                              .build())
+                                              .build())
+                              .build();
+        mCronetTestFramework.setHttpFlags(flags);
+        assertThat(HttpFlagsLoader.load(mCronetTestFramework.getContext())).isEqualTo(flags);
+    }
+}
diff --git a/components/embedder_support/content_settings_utils.cc b/components/embedder_support/content_settings_utils.cc
index fb452a1..751d7a7 100644
--- a/components/embedder_support/content_settings_utils.cc
+++ b/components/embedder_support/content_settings_utils.cc
@@ -67,6 +67,9 @@
 
   for (const auto& it : render_frames) {
     auto* rfh = content::RenderFrameHost::FromID(it);
+    if (!rfh) {
+      continue;
+    }
     content_settings::PageSpecificContentSettings::StorageAccessed(
         storage_type, it.child_id, it.frame_routing_id, rfh->GetStorageKey(),
         !allow);
diff --git a/components/exo/server/wayland_server_controller.cc b/components/exo/server/wayland_server_controller.cc
index 4b60713..145f5669 100644
--- a/components/exo/server/wayland_server_controller.cc
+++ b/components/exo/server/wayland_server_controller.cc
@@ -52,10 +52,26 @@
   // TODO(https://crbug.com/1124106): Investigate if we can eliminate Shutdown
   // methods.
   display_->Shutdown();
+  wayland::Server::SetServerGetter(base::NullCallback());
   DCHECK_EQ(g_instance, this);
   g_instance = nullptr;
 }
 
+wayland::Server* WaylandServerController::GetServerForDisplay(
+    wl_display* display) {
+  if (default_server_ && default_server_->GetWaylandDisplay() == display) {
+    return default_server_.get();
+  }
+
+  for (const auto& pair : on_demand_servers_) {
+    if (pair.second->GetWaylandDisplay() == display) {
+      return pair.second.get();
+    }
+  }
+
+  return nullptr;
+}
+
 WaylandServerController::WaylandServerController(
     std::unique_ptr<DataExchangeDelegate> data_exchange_delegate,
     std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
@@ -74,6 +90,8 @@
   default_server_->StartWithDefaultPath(base::BindOnce([](bool success) {
     DCHECK(success) << "Failed to start the default wayland server.";
   }));
+  wayland::Server::SetServerGetter(base::BindRepeating(
+      &WaylandServerController::GetServerForDisplay, base::Unretained(this)));
 }
 
 void WaylandServerController::ListenOnSocket(
diff --git a/components/exo/server/wayland_server_controller.h b/components/exo/server/wayland_server_controller.h
index af22ffe..8e5854c2 100644
--- a/components/exo/server/wayland_server_controller.h
+++ b/components/exo/server/wayland_server_controller.h
@@ -14,6 +14,8 @@
 #include "components/exo/security_delegate.h"
 #include "components/exo/wayland/server.h"
 
+struct wl_display;
+
 namespace exo {
 
 namespace wayland {
@@ -49,6 +51,9 @@
 
   ~WaylandServerController();
 
+  // Gets the Server instance for the `display` if it exists.
+  wayland::Server* GetServerForDisplay(wl_display* display);
+
   InputMethodSurfaceManager* input_method_surface_manager() {
     return display_->input_method_surface_manager();
   }
diff --git a/components/exo/wayland/clients/security_delegate_binding_test.cc b/components/exo/wayland/clients/security_delegate_binding_test.cc
index 0b11cc9..92d54c17 100644
--- a/components/exo/wayland/clients/security_delegate_binding_test.cc
+++ b/components/exo/wayland/clients/security_delegate_binding_test.cc
@@ -30,7 +30,7 @@
   void SetUp() override {
     WaylandServerTest::SetUp();
     server_security_delegate_ =
-        GetSecurityDelegate(server_->GetWaylandDisplayForTesting());
+        GetSecurityDelegate(server_->GetWaylandDisplay());
     ASSERT_NE(server_security_delegate_, nullptr);
   }
 
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 8105c275..2f91df6 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -59,6 +59,7 @@
 #include "build/build_config.h"
 #include "components/exo/display.h"
 #include "components/exo/security_delegate.h"
+#include "components/exo/wayland/client_tracker.h"
 #include "components/exo/wayland/content_type.h"
 #include "components/exo/wayland/overlay_prioritizer.h"
 #include "components/exo/wayland/serial_tracker.h"
@@ -135,6 +136,9 @@
 // (see `man 2 listen`).
 constexpr int kMaxPendingConnections = 128;
 
+// Callback used to find a Server instance for a given wl_display.
+Server::ServerGetter g_server_getter;
+
 bool IsDrmAtomicAvailable() {
 #if BUILDFLAG(IS_OZONE)
   auto& host_properties =
@@ -269,6 +273,8 @@
 
   wl_display_.reset(wl_display_create());
   SetSecurityDelegate(wl_display_.get(), security_delegate_.get());
+
+  client_tracker_ = std::make_unique<ClientTracker>(wl_display_.get());
 }
 
 void Server::Initialize() {
@@ -450,6 +456,17 @@
   return server;
 }
 
+// static.
+Server* Server::GetServerForDisplay(wl_display* display) {
+  return g_server_getter ? g_server_getter.Run(display) : nullptr;
+}
+
+// static.
+void Server::SetServerGetter(Server::ServerGetter server_getter) {
+  CHECK(!server_getter || !g_server_getter);
+  g_server_getter = std::move(server_getter);
+}
+
 void Server::StartWithDefaultPath(StartCallback callback) {
   if (!Open()) {
     std::move(callback).Run(/*success=*/false);
@@ -513,6 +530,10 @@
   return iter->second.get()->GetOutputResourceForClient(client);
 }
 
+bool Server::IsClientDestroyed(wl_client* client) const {
+  return client_tracker_->IsClientDestroyed(client);
+}
+
 void Server::AddWaylandOutput(int64_t id,
                               std::unique_ptr<WaylandDisplayOutput> output) {
   outputs_.insert(std::make_pair(id, std::move(output)));
diff --git a/components/exo/wayland/server.h b/components/exo/wayland/server.h
index 1fff81e..2ba3507 100644
--- a/components/exo/wayland/server.h
+++ b/components/exo/wayland/server.h
@@ -27,6 +27,7 @@
 
 namespace wayland {
 
+class ClientTracker;
 class SerialTracker;
 class UiControls;
 struct WaylandDataDeviceManager;
@@ -45,6 +46,7 @@
 // requests are dispatched into the given Exosphere display.
 class Server : public display::DisplayObserver {
  public:
+  using ServerGetter = base::RepeatingCallback<Server*(wl_display*)>;
   using StartCallback = base::OnceCallback<void(bool)>;
 
   Server(Display* display, std::unique_ptr<SecurityDelegate> security_delegate);
@@ -63,6 +65,12 @@
       Display* display,
       std::unique_ptr<SecurityDelegate> security_delegate);
 
+  // Gets the Server instance for a given wl_display.
+  static Server* GetServerForDisplay(wl_display* display);
+
+  // Sets the callback used to find the Server instance for a given wl_display.
+  static void SetServerGetter(ServerGetter server_getter);
+
   void StartWithDefaultPath(StartCallback callback);
   void StartWithFdAsync(base::ScopedFD fd, StartCallback callback);
 
@@ -93,18 +101,17 @@
   wl_resource* GetOutputResource(wl_client* client, int64_t display_id);
 
   Display* GetDisplay() { return display_; }
+  wl_display* GetWaylandDisplay() { return wl_display_.get(); }
 
-  // Public version of the protected accessor below, to be used in tests.
-  wl_display* GetWaylandDisplayForTesting() const {
-    return GetWaylandDisplay();
-  }
+  // Returns whether a client associated with this server has started
+  // destruction.
+  bool IsClientDestroyed(wl_client* client) const;
 
  protected:
   friend class UiControls;
   friend class WestonTest;
   void AddWaylandOutput(int64_t id,
                         std::unique_ptr<WaylandDisplayOutput> output);
-  wl_display* GetWaylandDisplay() const { return wl_display_.get(); }
 
  private:
   friend class ScopedEventDispatchDisabler;
@@ -132,6 +139,7 @@
   std::unique_ptr<WaylandXdgShell> xdg_shell_data_;
   std::unique_ptr<WaylandRemoteShellData> remote_shell_data_;
   std::unique_ptr<UiControls> ui_controls_holder_;
+  std::unique_ptr<ClientTracker> client_tracker_;
 };
 
 }  // namespace wayland
diff --git a/components/exo/wayland/server_unittest.cc b/components/exo/wayland/server_unittest.cc
index 384c90e..01488bc 100644
--- a/components/exo/wayland/server_unittest.cc
+++ b/components/exo/wayland/server_unittest.cc
@@ -68,7 +68,7 @@
 
   auto server = CreateServer(std::move(security_delegate));
 
-  EXPECT_EQ(GetSecurityDelegate(server->GetWaylandDisplayForTesting()),
+  EXPECT_EQ(GetSecurityDelegate(server->GetWaylandDisplay()),
             security_delegate_ptr);
 }
 
@@ -101,7 +101,7 @@
   EXPECT_NE(client_display, nullptr);
 
   wl_list* all_clients =
-      wl_display_get_client_list(server->GetWaylandDisplayForTesting());
+      wl_display_get_client_list(server->GetWaylandDisplay());
   ASSERT_FALSE(wl_list_empty(all_clients));
   wl_client* client = wl_client_from_link(all_clients->next);
 
@@ -126,7 +126,7 @@
   client_thread.Start();
 
   TestListener client_creation_listener;
-  wl_display_add_client_created_listener(server->GetWaylandDisplayForTesting(),
+  wl_display_add_client_created_listener(server->GetWaylandDisplay(),
                                          &client_creation_listener.listener);
 
   base::Lock lock;
@@ -148,13 +148,16 @@
     server->Dispatch(base::Milliseconds(10));
   }
 
+  // Remove the listener from the display's client creation signal.
+  wl_list_remove(&client_creation_listener.listener.link);
+
   {
     base::AutoLock locker(lock);
     EXPECT_TRUE(connected_to_server);
   }
 
   wl_list* all_clients =
-      wl_display_get_client_list(server->GetWaylandDisplayForTesting());
+      wl_display_get_client_list(server->GetWaylandDisplay());
   ASSERT_FALSE(wl_list_empty(all_clients));
   wl_client* client = wl_client_from_link(all_clients->next);
 
@@ -168,6 +171,9 @@
   while (!client_destruction_listener.notified) {
     server->Dispatch(base::Milliseconds(10));
   }
+
+  // Remove the listener from the client's destroy signal.
+  wl_list_remove(&client_destruction_listener.listener.link);
 }
 
 TEST_F(ServerTest, Flush) {
diff --git a/components/exo/wayland/server_util.cc b/components/exo/wayland/server_util.cc
index cadfbde6..96fab49 100644
--- a/components/exo/wayland/server_util.cc
+++ b/components/exo/wayland/server_util.cc
@@ -9,6 +9,7 @@
 #include "base/containers/flat_map.h"
 #include "base/time/time.h"
 #include "components/exo/data_offer.h"
+#include "components/exo/wayland/server.h"
 #include "ui/display/display.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
@@ -86,5 +87,17 @@
   return GetSecurityDelegate(wl_client_get_display(client));
 }
 
+bool IsClientDestroyed(wl_client* client) {
+  CHECK(client);
+
+  // There should always be a display associated with a client and display will
+  // always outlive the wl_client object.
+  wl_display* display = wl_client_get_display(client);
+  CHECK(display);
+
+  Server* server = Server::GetServerForDisplay(display);
+  return server ? server->IsClientDestroyed(client) : true;
+}
+
 }  // namespace wayland
 }  // namespace exo
diff --git a/components/exo/wayland/server_util.h b/components/exo/wayland/server_util.h
index ba329db5..d666e4b 100644
--- a/components/exo/wayland/server_util.h
+++ b/components/exo/wayland/server_util.h
@@ -77,6 +77,11 @@
 // connected to.
 SecurityDelegate* GetSecurityDelegate(wl_client* client);
 
+// Returns whether a client has initiated destruction. After destruction begins
+// resources associated with the client start to be freed and there is a risk of
+// UAFs in querying for client resources (see crbug.com/1433187).
+bool IsClientDestroyed(wl_client* client);
+
 }  // namespace wayland
 }  // namespace exo
 
diff --git a/components/exo/wayland/test/server_util.cc b/components/exo/wayland/test/server_util.cc
index c7382ba..77a1513 100644
--- a/components/exo/wayland/test/server_util.cc
+++ b/components/exo/wayland/test/server_util.cc
@@ -21,7 +21,7 @@
 
   wl_client* client = nullptr;
   wl_list* all_clients =
-      wl_display_get_client_list(server->GetWaylandDisplayForTesting());
+      wl_display_get_client_list(server->GetWaylandDisplay());
 
   auto find_closure = [](struct wl_resource* resource, void* data) {
     IteratorData* iterator_data = static_cast<IteratorData*>(data);
diff --git a/components/exo/wayland/test/wayland_server_test.cc b/components/exo/wayland/test/wayland_server_test.cc
index 8375eca..82b027e 100644
--- a/components/exo/wayland/test/wayland_server_test.cc
+++ b/components/exo/wayland/test/wayland_server_test.cc
@@ -12,13 +12,22 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "components/exo/security_delegate.h"
+#include "components/exo/wayland/server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace exo::wayland::test {
 
-WaylandServerTest::WaylandServerTest() = default;
+WaylandServerTest::WaylandServerTest() {
+  Server::SetServerGetter(base::BindLambdaForTesting([&](wl_display* display) {
+    // Currently tests run with a single Server instance.
+    EXPECT_EQ(display, server_->GetWaylandDisplay());
+    return server_.get();
+  }));
+}
 
-WaylandServerTest::~WaylandServerTest() = default;
+WaylandServerTest::~WaylandServerTest() {
+  Server::SetServerGetter(base::NullCallback());
+}
 
 void WaylandServerTest::SetUp() {
   WaylandServerTestBase::SetUp();
diff --git a/components/exo/wayland/test/wlcs/wlcs_helpers.cc b/components/exo/wayland/test/wlcs/wlcs_helpers.cc
index 7338eb3..8316478 100644
--- a/components/exo/wayland/test/wlcs/wlcs_helpers.cc
+++ b/components/exo/wayland/test/wlcs/wlcs_helpers.cc
@@ -64,7 +64,7 @@
   }
 
   struct wl_client* client =
-      wl_client_create(Get()->GetWaylandDisplayForTesting(), server_fd.get());
+      wl_client_create(Get()->GetWaylandDisplay(), server_fd.get());
   if (!client) {
     return -1;
   }
diff --git a/components/exo/wayland/wayland_display_observer.cc b/components/exo/wayland/wayland_display_observer.cc
index 04e9597..057766b0 100644
--- a/components/exo/wayland/wayland_display_observer.cc
+++ b/components/exo/wayland/wayland_display_observer.cc
@@ -29,22 +29,9 @@
 
 WaylandDisplayHandler::WaylandDisplayHandler(WaylandDisplayOutput* output,
                                              wl_resource* output_resource)
-    : output_(output), output_resource_(output_resource) {
-  // At construction time the client object is guaranteed to exist.
-  wl_client* client = wl_resource_get_client(output_resource_);
-  CHECK(client);
-  client_destroy_listener_.listener.notify =
-      &WaylandDisplayHandler::OnClientDestroyed;
-  wl_client_add_destroy_listener(client, &client_destroy_listener_.listener);
-}
+    : output_(output), output_resource_(output_resource) {}
 
 WaylandDisplayHandler::~WaylandDisplayHandler() {
-  // Remove the listener to cover the case where the client outlives the
-  // handler.
-  if (!client_destroy_listener_.notified) {
-    wl_list_remove(&client_destroy_listener_.listener.link);
-  }
-
   ash::Shell::Get()->RemoveShellObserver(this);
   for (auto& obs : observers_) {
     obs.OnOutputDestroyed();
@@ -158,14 +145,6 @@
   xdg_output_resource_ = nullptr;
 }
 
-bool WaylandDisplayHandler::IsClientDestroyedForTesting() const {
-  return client_destroy_listener_.notified;
-}
-
-AuraOutputManager* WaylandDisplayHandler::GetAuraOutputManagerForTesting() {
-  return GetAuraOutputManager();
-}
-
 void WaylandDisplayHandler::XdgOutputSendLogicalPosition(
     const gfx::Point& position) {
   zxdg_output_v1_send_logical_position(xdg_output_resource_, position.x(),
@@ -185,15 +164,6 @@
   zxdg_output_v1_send_description(xdg_output_resource_, desc.c_str());
 }
 
-// static.
-void WaylandDisplayHandler::OnClientDestroyed(struct wl_listener* listener,
-                                              void* data) {
-  ClientDestroyListener* client_destroy_listener = wl_container_of(
-      listener, /*sample=*/client_destroy_listener, /*member=*/listener);
-  client_destroy_listener->notified = true;
-  wl_list_remove(&client_destroy_listener->listener.link);
-}
-
 bool WaylandDisplayHandler::SendDisplayMetrics(const display::Display& display,
                                                uint32_t changed_metrics) {
   if (!output_resource_) {
@@ -278,14 +248,6 @@
 }
 
 AuraOutputManager* WaylandDisplayHandler::GetAuraOutputManager() {
-  // If the client has begun destruction avoid attempting to access the client's
-  // AuraOutputManager instance as libwayland may have freed the object's memory
-  // but not yet updated the data structures used to find the object (see
-  // crbug.com/1433187).
-  if (client_destroy_listener_.notified) {
-    return nullptr;
-  }
-
   wl_client* client = wl_resource_get_client(output_resource_);
   CHECK(client);
   return AuraOutputManager::Get(client);
diff --git a/components/exo/wayland/wayland_display_observer.h b/components/exo/wayland/wayland_display_observer.h
index 8881975..63f7c2e 100644
--- a/components/exo/wayland/wayland_display_observer.h
+++ b/components/exo/wayland/wayland_display_observer.h
@@ -71,8 +71,6 @@
   void UnsetXdgOutputResource();
 
   size_t CountObserversForTesting() const;
-  bool IsClientDestroyedForTesting() const;
-  AuraOutputManager* GetAuraOutputManagerForTesting();
 
  protected:
   wl_resource* output_resource() const { return output_resource_; }
@@ -83,18 +81,6 @@
   virtual void XdgOutputSendDescription(const std::string& desc);
 
  private:
-  // Tracks whether destruction of the associated server-side client object has
-  // begun. Note that the wl_resource associated with this output will remain
-  // valid until its cleanup routine is run during a later phase of the client's
-  // multi-part teardown.
-  struct ClientDestroyListener {
-    wl_listener listener;
-    bool notified = false;
-  };
-
-  // Called when the client associated with the handler begins destruction.
-  static void OnClientDestroyed(struct wl_listener* listener, void* data);
-
   // Overridden from WaylandDisplayObserver:
   bool SendDisplayMetrics(const display::Display& display,
                           uint32_t changed_metrics) override;
@@ -124,9 +110,6 @@
   raw_ptr<wl_resource, DanglingUntriaged | ExperimentalAsh>
       xdg_output_resource_ = nullptr;
 
-  // The listener is notified when the server-side client destruction begins.
-  ClientDestroyListener client_destroy_listener_;
-
   base::ObserverList<WaylandDisplayObserver> observers_;
 
   display::ScopedDisplayObserver display_observer_{this};
diff --git a/components/exo/wayland/wayland_display_observer_unittest.cc b/components/exo/wayland/wayland_display_observer_unittest.cc
index f9ded9f..3001506 100644
--- a/components/exo/wayland/wayland_display_observer_unittest.cc
+++ b/components/exo/wayland/wayland_display_observer_unittest.cc
@@ -120,24 +120,6 @@
   handler_->OnDisplayMetricsChanged(display, kAllChanges);
 }
 
-// Regression test for crbug.com/1433187. Ensures that the AuraOutputManager is
-// not accessible after client destruction (the client and its resources may be
-// destroyed before the handler).
-TEST_F(WaylandDisplayObserverTest,
-       AuraOutputManagerInaccessibleAfterClientDestruction) {
-  // Prior to client destruction the AuraOutputManager should be accessible.
-  EXPECT_FALSE(handler_->IsClientDestroyedForTesting());
-  EXPECT_TRUE(handler_->GetAuraOutputManagerForTesting());
-
-  // Destroys the client, which also destroys all associated resources.
-  DestroyClient();
-
-  // After client destruction has occurred assert the handler has been notified
-  // and the AuraOutputManager is no longer accessible.
-  EXPECT_TRUE(handler_->IsClientDestroyedForTesting());
-  EXPECT_FALSE(handler_->GetAuraOutputManagerForTesting());
-}
-
 }  // namespace
 }  // namespace wayland
 }  // namespace exo
diff --git a/components/exo/wayland/zaura_output_manager.cc b/components/exo/wayland/zaura_output_manager.cc
index def30f63..e411809 100644
--- a/components/exo/wayland/zaura_output_manager.cc
+++ b/components/exo/wayland/zaura_output_manager.cc
@@ -22,6 +22,11 @@
 
 // static.
 AuraOutputManager* AuraOutputManager::Get(wl_client* client) {
+  // Avoid querying client resources if it has already begun destruction.
+  if (IsClientDestroyed(client)) {
+    return nullptr;
+  }
+
   AuraOutputManager* output_manager = nullptr;
   wl_client_for_each_resource(
       client,
diff --git a/components/exo/wayland/zaura_output_manager_unittest.cc b/components/exo/wayland/zaura_output_manager_unittest.cc
index 99802f5..32da2a3 100644
--- a/components/exo/wayland/zaura_output_manager_unittest.cc
+++ b/components/exo/wayland/zaura_output_manager_unittest.cc
@@ -4,8 +4,10 @@
 
 #include "components/exo/wayland/zaura_output_manager.h"
 
+#include <sys/socket.h>
 #include <cstdint>
 
+#include "components/exo/wayland/server_util.h"
 #include "components/exo/wayland/test/test_client.h"
 #include "components/exo/wayland/test/wayland_server_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -210,12 +212,56 @@
     return test_client;
   }
 
+  // Creates a wl_client instance for this test.
+  void CreateClient() {
+    ASSERT_FALSE(client_);
+    socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds_);
+    client_ = wl_client_create(server_->GetWaylandDisplay(), fds_[0]);
+  }
+
+  // Destroys the wl_client instance for this test if it exists.
+  void DestroyClient() {
+    if (client_) {
+      wl_client_destroy(client_.ExtractAsDangling());
+      close(fds_[1]);
+      client_ = nullptr;
+    }
+  }
+
  protected:
   std::unique_ptr<MockAuraOutputManagerListener> mock_aura_output_manager_;
+  int fds_[2] = {0, 0};
+  raw_ptr<wl_client> client_ = nullptr;
 };
 
 }  // namespace
 
+// Regression test for crbug.com/1433187. Ensures AuraOutputManager::Get() does
+// not cause UAF crashes by attempting to iterate over resources belonging to a
+// client that has started destruction.
+TEST_F(AuraOutputManagerTest, GetterReturnsNullAfterClientDestroyed) {
+  CreateClient();
+  EXPECT_FALSE(IsClientDestroyed(client_));
+
+  // Create a resource associated with the client.
+  wl_resource* output_resource =
+      wl_resource_create(client_, &wl_output_interface, 2, 0);
+  wl_resource_set_user_data(output_resource, client_);
+
+  // Ensure that calls to AuraOutputManager::Get() after client destruction
+  // does not result in UAF crashes. This callback will run after the client's
+  // destruction sequence begins and associated resources are freed.
+  auto wl_resource_callback = [](wl_resource* resource) {
+    wl_client* client =
+        static_cast<wl_client*>(wl_resource_get_user_data(resource));
+    EXPECT_TRUE(IsClientDestroyed(client));
+    EXPECT_FALSE(AuraOutputManager::Get(client));
+  };
+  wl_resource_set_destructor(output_resource, wl_resource_callback);
+
+  DestroyClient();
+}
+
 TEST_F(AuraOutputManagerTest, SendOverscanInsets) {
   wl_output* client_output = nullptr;
 
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index ad88557..593679d 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -350,6 +350,10 @@
 
   // The AffiliationService must be destroyed from the main sequence.
   affiliated_match_helper_.reset();
+
+  // PrefService is destroyed together with BrowserContext, and cannot be used
+  // anymore.
+  prefs_ = nullptr;
 }
 
 std::unique_ptr<syncer::ProxyModelTypeControllerDelegate>
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index f5257e7..d39b4961 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -214,7 +214,7 @@
 
   std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_;
 
-  raw_ptr<PrefService, AcrossTasksDanglingUntriaged> prefs_ = nullptr;
+  raw_ptr<PrefService> prefs_ = nullptr;
 
   InitStatus init_status_ = InitStatus::kUnknown;
 };
diff --git a/components/policy/test/data/policy_test_cases.json b/components/policy/test/data/policy_test_cases.json
index 0451b81..bc54366 100644
--- a/components/policy/test/data/policy_test_cases.json
+++ b/components/policy/test/data/policy_test_cases.json
@@ -6974,16 +6974,9 @@
             "value": false
           }
         }
-      },
-      {
-        "policies": {},
-        "prefs": {
-          "webauthn.create_in_icloud_keychain": {
-            "default_value": true
-          }
-        }
       }
-    ]
+    ],
+    "note": "default value of the pref in case no policy is set evaluates differently on CQ/CI bots and will therefor be skipped here (see crbug.com/1477033)"
   },
   "ImportBookmarks": {
     "os": [
diff --git a/components/safe_browsing/content/browser/client_side_detection_host.cc b/components/safe_browsing/content/browser/client_side_detection_host.cc
index 66ffab19..d01785487 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_host.cc
@@ -626,9 +626,13 @@
           &token);
     }
 
+    // The check for image embedding model is important because the
+    // OptimizationGuide server can send a null model to signal there is a bad
+    // model in disk.
     if (base::FeatureList::IsEnabled(kClientSideDetectionModelImageEmbedder) &&
         IsEnhancedProtectionEnabled(*delegate_->GetPrefs()) &&
-        csd_service_->IsModelMetadataImageEmbeddingVersionMatching()) {
+        csd_service_->IsModelMetadataImageEmbeddingVersionMatching() &&
+        csd_service_->HasImageEmbeddingModel()) {
       content::RenderFrameHost* rfh = web_contents()->GetPrimaryMainFrame();
 
       phishing_image_embedder_.reset();
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc
index 8a6aa0e..4cf68e2 100644
--- a/components/safe_browsing/content/browser/client_side_detection_service.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -515,7 +515,11 @@
 
 void ClientSideDetectionService::SetPhishingModel(
     content::RenderProcessHost* rph) {
-  if (!IsModelAvailable()) {
+  // We want to check if the trigger model has been sent. If we have received a
+  // callback after sending the trigger models before and the models are now
+  // unavailable, that means the OptimizationGuide server sent us a null model
+  // to signal that a bad model is in disk.
+  if (!IsModelAvailable() && !sent_trigger_models_) {
     return;
   }
   if (!rph->GetChannel()) {
@@ -524,6 +528,11 @@
 
   mojo::AssociatedRemote<mojom::PhishingModelSetter> model_setter;
   rph->GetChannel()->GetRemoteAssociatedInterface(&model_setter);
+  if (!IsModelAvailable() && sent_trigger_models_) {
+    model_setter->ClearScorer();
+    return;
+  }
+
   switch (GetModelType()) {
     case CSDModelType::kNone:
       return;
@@ -532,7 +541,14 @@
           IsEnhancedProtectionEnabled(*delegate_->GetPrefs()) &&
           base::FeatureList::IsEnabled(
               kClientSideDetectionModelImageEmbedder)) {
-        if (IsModelMetadataImageEmbeddingVersionMatching()) {
+        // The check for image embedding model is important because the
+        // OptimizationGuide server can send a null image embedding model to
+        // signal there is a bad model in disk. If the image embedding model
+        // isn't available because of this, the scorer will be created without
+        // the image embedder model, temporarily halting the image embedding
+        // process on the renderer.
+        if (IsModelMetadataImageEmbeddingVersionMatching() &&
+            HasImageEmbeddingModel()) {
           base::UmaHistogramBoolean(
               "SBClientPhishing.ImageEmbeddingModelVersionMatch", true);
           model_setter->SetImageEmbeddingAndPhishingFlatBufferModel(
@@ -548,6 +564,7 @@
         model_setter->SetPhishingFlatBufferModel(
             GetModelSharedMemoryRegion(), GetVisualTfLiteModel().Duplicate());
       }
+      sent_trigger_models_ = true;
       return;
   }
 }
@@ -642,6 +659,14 @@
          client_side_phishing_model_->IsEnabled();
 }
 
+bool ClientSideDetectionService::HasImageEmbeddingModel() {
+  if (base::FeatureList::IsEnabled(kClientSideDetectionModelImageEmbedder)) {
+    return client_side_phishing_model_ &&
+           client_side_phishing_model_->HasImageEmbeddingModel();
+  }
+  return false;
+}
+
 bool ClientSideDetectionService::IsSubscribedToImageEmbeddingModelUpdates() {
   if (base::FeatureList::IsEnabled(kClientSideDetectionModelImageEmbedder)) {
     return client_side_phishing_model_ &&
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.h b/components/safe_browsing/content/browser/client_side_detection_service.h
index 421c84a04..955ea3a 100644
--- a/components/safe_browsing/content/browser/client_side_detection_service.h
+++ b/components/safe_browsing/content/browser/client_side_detection_service.h
@@ -185,6 +185,10 @@
   // that mock classes can override it.
   virtual bool IsModelAvailable();
 
+  // Checks whether the model class has an image embedding model available or
+  // not.
+  bool HasImageEmbeddingModel();
+
   // For testing the model in browser test.
   void SetModelAndVisualTfLiteForTesting(const base::FilePath& model,
                                          const base::FilePath& visual_tf_lite);
@@ -270,6 +274,12 @@
   // choice of model.
   bool extended_reporting_ = false;
 
+  // Whether the trigger models have been sent or not. This is used to determine
+  // whether an empty model in the model class determines whether the models
+  // haven't been sent or we should clear the models in the scorer because they
+  // have been sent.
+  bool sent_trigger_models_ = false;
+
   // Map of client report phishing request to the corresponding callback that
   // has to be invoked when the request is done.
   struct ClientPhishingReportInfo;
diff --git a/components/safe_browsing/content/browser/client_side_phishing_model.cc b/components/safe_browsing/content/browser/client_side_phishing_model.cc
index 78e1172..f6f943a1 100644
--- a/components/safe_browsing/content/browser/client_side_phishing_model.cc
+++ b/components/safe_browsing/content/browser/client_side_phishing_model.cc
@@ -180,12 +180,29 @@
     return;
   }
 
-  if (!model_info.has_value()) {
-    return;
-  }
-
   if (optimization_target ==
       optimization_guide::proto::OPTIMIZATION_TARGET_CLIENT_SIDE_PHISHING) {
+    // If the model_info has no value, that means the OptimizationGuide server
+    // has sent an intentionally null model value to indicate that there is a
+    // bad model on disk and it should be removed. Therefore, we will clear the
+    // current model in the class.
+    if (!model_info.has_value()) {
+      mapped_region_ = base::MappedReadOnlyRegion();
+      if (visual_tflite_model_) {
+        background_task_runner_->PostTask(
+            FROM_HERE,
+            base::BindOnce(&CloseModelFile, std::move(*visual_tflite_model_)));
+      }
+      // Run callback to remove models from the renderer process. When a
+      // callback is called and there are no models in this class while the
+      // model type is set, it's expected that it's asked to remove the models.
+      content::GetUIThreadTaskRunner({})->PostTask(
+          FROM_HERE,
+          base::BindOnce(&ClientSidePhishingModel::NotifyCallbacksOnUI,
+                         weak_ptr_factory_.GetWeakPtr()));
+      return;
+    }
+
     background_task_runner_->PostTaskAndReplyWithResult(
         FROM_HERE,
         base::BindOnce(&LoadModelAndVisualTfLiteFile,
@@ -197,6 +214,22 @@
   } else if (optimization_target ==
              optimization_guide::proto::
                  OPTIMIZATION_TARGET_CLIENT_SIDE_PHISHING_IMAGE_EMBEDDER) {
+    // If the model_info has no value for this target, we only remove the image
+    // embedding model, and if the trigger models are still valid, then the
+    // scorer will be created with the trigger models only.
+    if (!model_info.has_value()) {
+      if (image_embedding_model_) {
+        background_task_runner_->PostTask(
+            FROM_HERE, base::BindOnce(&CloseModelFile,
+                                      std::move(*image_embedding_model_)));
+      }
+      content::GetUIThreadTaskRunner({})->PostTask(
+          FROM_HERE,
+          base::BindOnce(&ClientSidePhishingModel::NotifyCallbacksOnUI,
+                         weak_ptr_factory_.GetWeakPtr()));
+      return;
+    }
+
     background_task_runner_->PostTaskAndReplyWithResult(
         FROM_HERE,
         base::BindOnce(&LoadImageEmbeddingModelFile,
@@ -338,6 +371,14 @@
     base::File image_embedding_model) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  if (image_embedding_model_) {
+    // If the image embedding model file is already loaded, it should be closed
+    // on a background thread.
+    background_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&CloseModelFile, std::move(*image_embedding_model_)));
+  }
+
   image_embedding_model_ = std::move(image_embedding_model);
 
   absl::optional<optimization_guide::proto::ClientSidePhishingModelMetadata>
diff --git a/components/safe_browsing/content/common/safe_browsing.mojom b/components/safe_browsing/content/common/safe_browsing.mojom
index 849e059bb6..8ba2e21f 100644
--- a/components/safe_browsing/content/common/safe_browsing.mojom
+++ b/components/safe_browsing/content/common/safe_browsing.mojom
@@ -163,6 +163,11 @@
   SetPhishingFlatBufferModel(mojo_base.mojom.ReadOnlySharedMemoryRegion region,
                              mojo_base.mojom.ReadOnlyFile? tflite_model);
 
+  // When OptimizationGuide server sends a null model, this signals there is a
+  // bad model on disk. Calling this function clears the current Scorer object
+  // in the renderer so that classification isn't used with the bad model.
+  ClearScorer();
+
   // This is used in tests to ensure that the model has been set before sending
   // IPCs to start classification.
   SetTestObserver(pending_remote<PhishingModelSetterTestObserver>? observer) =>
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.cc
index e50d8a1..0f29b1d 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.cc
@@ -59,10 +59,8 @@
       std::move(image_embedding_model));
 
   if (!scorer) {
-    // Log here that the image embedder creation has failed.
     return;
   }
-
   ScorerStorage::GetInstance()->SetScorer(std::move(scorer));
 
   if (observer_for_testing_.is_bound()) {
@@ -85,6 +83,10 @@
   }
 }
 
+void PhishingModelSetterImpl::ClearScorer() {
+  ScorerStorage::GetInstance()->ClearScorer();
+}
+
 void PhishingModelSetterImpl::SetTestObserver(
     mojo::PendingRemote<mojom::PhishingModelSetterTestObserver> observer,
     SetTestObserverCallback callback) {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.h b/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.h
index 564cf401..9590e89 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_model_setter_impl.h
@@ -37,6 +37,7 @@
   void SetPhishingFlatBufferModel(
       base::ReadOnlySharedMemoryRegion flatbuffer_region,
       base::File tflite_visual_model) override;
+  void ClearScorer() override;
   void SetTestObserver(
       mojo::PendingRemote<mojom::PhishingModelSetterTestObserver> observer,
       SetTestObserverCallback callback) override;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
index 491f53e..972bcef5 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
@@ -596,6 +596,13 @@
     obs.OnScorerChanged();
 }
 
+void ScorerStorage::ClearScorer() {
+  scorer_.reset();
+  for (Observer& obs : observers_) {
+    obs.OnScorerChanged();
+  }
+}
+
 Scorer* ScorerStorage::GetScorer() const {
   return scorer_.get();
 }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
index 4f47d98..939db71 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -208,6 +208,9 @@
 
   void SetScorer(std::unique_ptr<Scorer> scorer);
   Scorer* GetScorer() const;
+  // We will clear the scorer in situations where the OptimizationGuide server
+  // provides a null model to replace a bad model on disk.
+  void ClearScorer();
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
diff --git a/components/sync/service/BUILD.gn b/components/sync/service/BUILD.gn
index 01c34c47..37c5c572 100644
--- a/components/sync/service/BUILD.gn
+++ b/components/sync/service/BUILD.gn
@@ -42,6 +42,7 @@
     "sync_api_component_factory.h",
     "sync_auth_manager.cc",
     "sync_auth_manager.h",
+    "sync_client.cc",
     "sync_client.h",
     "sync_internals_util.cc",
     "sync_internals_util.h",
diff --git a/components/sync/service/sync_client.cc b/components/sync/service/sync_client.cc
new file mode 100644
index 0000000..60f14a3
--- /dev/null
+++ b/components/sync/service/sync_client.cc
@@ -0,0 +1,21 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/service/sync_client.h"
+
+#include "base/notreached.h"
+
+namespace syncer {
+
+void SyncClient::GetLocalDataDescriptions(
+    ModelTypeSet types,
+    base::OnceCallback<void(std::map<ModelType, LocalDataDescription>)>
+        callback) {
+  NOTIMPLEMENTED() << "SyncClient implementations should implement this.";
+}
+
+void SyncClient::TriggerLocalDataMigration(ModelTypeSet types) {
+  NOTIMPLEMENTED() << "SyncClient implementations should implement this.";
+}
+}  // namespace syncer
diff --git a/components/sync/service/sync_client.h b/components/sync/service/sync_client.h
index 0e1a095..7e494ae 100644
--- a/components/sync/service/sync_client.h
+++ b/components/sync/service/sync_client.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_SYNC_SERVICE_SYNC_CLIENT_H_
 #define COMPONENTS_SYNC_SERVICE_SYNC_CLIENT_H_
 
+#include <map>
+
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "components/sync/base/extensions_activity.h"
@@ -23,6 +25,7 @@
 
 namespace syncer {
 
+struct LocalDataDescription;
 class SyncApiComponentFactory;
 class SyncInvalidationsService;
 class SyncService;
@@ -69,6 +72,27 @@
   // TODO(crbug.com/1137346): Replace this mechanism with a more universal one,
   // e.g. using SyncServiceObserver.
   virtual void OnLocalSyncTransportDataCleared() = 0;
+
+  // Queries the count and description/preview of existing local data for
+  // `types` data types. This is an asynchronous method which returns the result
+  // via the callback `callback` once the information for all the data types in
+  // `types` is available.
+  // Note: Only data types that are enabled and support this functionality are
+  // part of the response.
+  // TODO(crbug.com/1451508): Mark as pure virtual once all implementations have
+  // overridden this.
+  virtual void GetLocalDataDescriptions(
+      ModelTypeSet types,
+      base::OnceCallback<void(std::map<ModelType, LocalDataDescription>)>
+          callback);
+
+  // Requests the client to move all local data to account for `types` data
+  // types. This is an asynchronous method which moves the local data for all
+  // `types` to the account store locally. Upload to the server will happen as
+  // part of the regular commit process, and is NOT part of this method.
+  // TODO(crbug.com/1451508): Mark as pure virtual once all implementations have
+  // overridden this.
+  virtual void TriggerLocalDataMigration(ModelTypeSet types);
 };
 
 }  // namespace syncer
diff --git a/components/sync/service/sync_service.h b/components/sync/service/sync_service.h
index c9f1e18..08ac38d 100644
--- a/components/sync/service/sync_service.h
+++ b/components/sync/service/sync_service.h
@@ -446,6 +446,8 @@
   // types. This is an asynchronous method which moves the local data for all
   // `types` to the account store locally. Upload to the server will happen as
   // part of the regular commit process, and is NOT part of this method.
+  // Note: Only data types that are enabled and support this functionality are
+  // triggered for upload.
   virtual void TriggerLocalDataMigration(ModelTypeSet types) = 0;
 
   //////////////////////////////////////////////////////////////////////////////
diff --git a/components/sync/service/sync_service_impl.cc b/components/sync/service/sync_service_impl.cc
index 39d0ad7..168698d 100644
--- a/components/sync/service/sync_service_impl.cc
+++ b/components/sync/service/sync_service_impl.cc
@@ -44,9 +44,11 @@
 #include "components/sync/model/type_entities_count.h"
 #include "components/sync/service/backend_migrator.h"
 #include "components/sync/service/configure_context.h"
+#include "components/sync/service/local_data_description.h"
 #include "components/sync/service/sync_api_component_factory.h"
 #include "components/sync/service/sync_auth_manager.h"
 #include "components/sync/service/sync_prefs.h"
+#include "components/sync/service/sync_service_utils.h"
 #include "components/sync/service/trusted_vault_histograms.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -2399,13 +2401,32 @@
     ModelTypeSet types,
     base::OnceCallback<void(std::map<ModelType, LocalDataDescription>)>
         callback) {
-  // TODO(crbug.com/1451508): Implement this.
-  NOTIMPLEMENTED();
+  // Return early if sync is disabled, or paused because of a persistent auth
+  // error.
+  if (GetTransportState() == TransportState::DISABLED ||
+      GetTransportState() == TransportState::PAUSED) {
+    std::move(callback).Run({});
+    return;
+  }
+
+  // Only retain the types that are enabled.
+  types.RetainAll(GetPreferredDataTypes());
+
+  sync_client_->GetLocalDataDescriptions(types, std::move(callback));
 }
 
 void SyncServiceImpl::TriggerLocalDataMigration(ModelTypeSet types) {
-  // TODO(crbug.com/1451508): Implement this.
-  NOTIMPLEMENTED();
+  // Return early if sync is disabled, or paused because of a persistent auth
+  // error.
+  if (GetTransportState() == TransportState::DISABLED ||
+      GetTransportState() == TransportState::PAUSED) {
+    return;
+  }
+
+  // Only retain the types that are enabled.
+  types.RetainAll(GetPreferredDataTypes());
+
+  sync_client_->TriggerLocalDataMigration(types);
 }
 
 }  // namespace syncer
diff --git a/components/sync/service/sync_service_impl_unittest.cc b/components/sync/service/sync_service_impl_unittest.cc
index f740360..ce36f5f5 100644
--- a/components/sync/service/sync_service_impl_unittest.cc
+++ b/components/sync/service/sync_service_impl_unittest.cc
@@ -1909,5 +1909,93 @@
             service()->GetTypesWithPendingDownloadForInitialSync());
 }
 
+TEST_F(SyncServiceImplTest,
+       ShouldOnlyForwardEnabledTypesToSyncClientUponGetLocalDataDescriptions) {
+  PopulatePrefsForInitialSyncFeatureSetupComplete();
+  SignInWithSyncConsent();
+  // Only PASSWORDS datatype is enabled.
+  InitializeService({{PASSWORDS, true}});
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_EQ(service()->GetActiveDataTypes(), ModelTypeSet({NIGORI, PASSWORDS}));
+
+  // PASSWORDS and BOOKMARKS is queried from the sync service.
+  ModelTypeSet requested_types{PASSWORDS, BOOKMARKS};
+  // Only PASSWORDS datatype is queried from the sync client.
+  EXPECT_CALL(*sync_client(),
+              GetLocalDataDescriptions(ModelTypeSet{PASSWORDS}, ::testing::_));
+
+  service()->GetLocalDataDescriptions(requested_types, base::DoNothing());
+}
+
+TEST_F(SyncServiceImplTest,
+       ShouldNotForwardToSyncClientUponGetLocalDataDescriptionsIfSyncDisabled) {
+  PopulatePrefsForInitialSyncFeatureSetupComplete();
+  prefs()->SetManagedPref(prefs::internal::kSyncManaged, base::Value(true));
+  SignInWithSyncConsent();
+  InitializeService({{PASSWORDS, true}, {BOOKMARKS, true}});
+  base::RunLoop().RunUntilIdle();
+
+  // Sync was disabled due to the policy.
+  EXPECT_EQ(SyncService::DisableReasonSet(
+                {SyncService::DISABLE_REASON_ENTERPRISE_POLICY}),
+            service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
+            service()->GetTransportState());
+
+  // PASSWORDS and BOOKMARKS is queried from the sync service.
+  ModelTypeSet requested_types{PASSWORDS, BOOKMARKS};
+  // No query to the sync client.
+  EXPECT_CALL(*sync_client(),
+              GetLocalDataDescriptions(ModelTypeSet{}, ::testing::_))
+      .Times(0);
+
+  service()->GetLocalDataDescriptions(requested_types, base::DoNothing());
+}
+
+TEST_F(SyncServiceImplTest,
+       ShouldOnlyForwardEnabledTypesToSyncClientUponTriggerLocalDataMigration) {
+  PopulatePrefsForInitialSyncFeatureSetupComplete();
+  SignInWithSyncConsent();
+  // Only PASSWORDS datatype is enabled.
+  InitializeService({{PASSWORDS, true}});
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_EQ(service()->GetActiveDataTypes(), ModelTypeSet({NIGORI, PASSWORDS}));
+
+  // PASSWORDS and BOOKMARKS is queried from the sync service.
+  ModelTypeSet requested_types{PASSWORDS, BOOKMARKS};
+  // Only PASSWORDS datatype is queried from the sync client.
+  EXPECT_CALL(*sync_client(),
+              TriggerLocalDataMigration(ModelTypeSet{PASSWORDS}));
+
+  service()->TriggerLocalDataMigration(ModelTypeSet{PASSWORDS, BOOKMARKS});
+}
+
+TEST_F(
+    SyncServiceImplTest,
+    ShouldNotForwardToSyncClientUponTriggerLocalDataMigrationIfSyncDisabled) {
+  PopulatePrefsForInitialSyncFeatureSetupComplete();
+  prefs()->SetManagedPref(prefs::internal::kSyncManaged, base::Value(true));
+  SignInWithSyncConsent();
+  InitializeService({{PASSWORDS, true}, {BOOKMARKS, true}});
+  base::RunLoop().RunUntilIdle();
+
+  // Sync was disabled due to the policy.
+  EXPECT_EQ(SyncService::DisableReasonSet(
+                {SyncService::DISABLE_REASON_ENTERPRISE_POLICY}),
+            service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
+            service()->GetTransportState());
+
+  // PASSWORDS and BOOKMARKS is queried from the sync service.
+  ModelTypeSet requested_types{PASSWORDS, BOOKMARKS};
+  // No query to the sync client.
+  EXPECT_CALL(*sync_client(), TriggerLocalDataMigration(ModelTypeSet{}))
+      .Times(0);
+
+  service()->TriggerLocalDataMigration(requested_types);
+}
+
 }  // namespace
 }  // namespace syncer
diff --git a/components/sync/test/sync_client_mock.h b/components/sync/test/sync_client_mock.h
index 790a382..4b8fa31e 100644
--- a/components/sync/test/sync_client_mock.h
+++ b/components/sync/test/sync_client_mock.h
@@ -5,7 +5,10 @@
 #ifndef COMPONENTS_SYNC_TEST_SYNC_CLIENT_MOCK_H_
 #define COMPONENTS_SYNC_TEST_SYNC_CLIENT_MOCK_H_
 
+#include <map>
+
 #include "base/files/file_path.h"
+#include "components/sync/service/local_data_description.h"
 #include "components/sync/service/sync_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -48,6 +51,17 @@
               (),
               (override));
   MOCK_METHOD(void, OnLocalSyncTransportDataCleared, (), (override));
+  MOCK_METHOD(
+      void,
+      GetLocalDataDescriptions,
+      (ModelTypeSet types,
+       base::OnceCallback<void(std::map<ModelType, LocalDataDescription>)>
+           callback),
+      (override));
+  MOCK_METHOD(void,
+              TriggerLocalDataMigration,
+              (ModelTypeSet types),
+              (override));
 };
 
 }  // namespace syncer
diff --git a/components/variations/service/generate_ui_string_overrider.py b/components/variations/service/generate_ui_string_overrider.py
index af94627..9a3c139 100755
--- a/components/variations/service/generate_ui_string_overrider.py
+++ b/components/variations/service/generate_ui_string_overrider.py
@@ -196,7 +196,6 @@
       "#include \"%(header_filename)s\"\n\n"
       "%(namespace_prefix)s"
       "namespace {\n\n"
-      "const size_t kNumResources = %(num_resources)i;\n\n"
       "%(hashes_array)s"
       "\n"
       "%(indices_array)s"
@@ -205,13 +204,12 @@
       "\n"
       "variations::UIStringOverrider CreateUIStringOverrider() {\n"
       "  return variations::UIStringOverrider(\n"
-      "      kResourceHashes, kResourceIndices, kNumResources);\n"
+      "      kResourceHashes, kResourceIndices);\n"
       "}\n"
       "%(namespace_suffix)s") % {
           'script_name': SCRIPT_NAME,
           'header_filename': header_filename,
           'namespace_prefix': namespace_prefix,
-          'num_resources': len(hashed_tuples),
           'hashes_array': hashes_array,
           'indices_array': indices_array,
           'namespace_suffix': namespace_suffix,
diff --git a/components/variations/service/generate_ui_string_overrider_unittest.py b/components/variations/service/generate_ui_string_overrider_unittest.py
index b4dbae7..3242285 100755
--- a/components/variations/service/generate_ui_string_overrider_unittest.py
+++ b/components/variations/service/generate_ui_string_overrider_unittest.py
@@ -73,8 +73,6 @@
 
 namespace {
 
-const size_t kNumResources = 4;
-
 const uint32_t kResourceHashes[] = {
     301430091U,  // IDS_BOOKMARKS_NO_ITEMS
     2654138887U,  // IDS_BOOKMARK_BAR_IMPORT_LINK
@@ -93,7 +91,7 @@
 
 variations::UIStringOverrider CreateUIStringOverrider() {
   return variations::UIStringOverrider(
-      kResourceHashes, kResourceIndices, kNumResources);
+      kResourceHashes, kResourceIndices);
 }
 
 }  // namespace chrome_variations
diff --git a/components/variations/service/ui_string_overrider.cc b/components/variations/service/ui_string_overrider.cc
index 5da4fad..78791448 100644
--- a/components/variations/service/ui_string_overrider.cc
+++ b/components/variations/service/ui_string_overrider.cc
@@ -7,35 +7,32 @@
 #include <algorithm>
 
 #include "base/check.h"
+#include "base/check_op.h"
 #include "ui/base/resource/resource_bundle.h"
 
 namespace variations {
 
-UIStringOverrider::UIStringOverrider()
-    : resource_hashes_(nullptr),
-      resource_indices_(nullptr),
-      num_resources_(0) {}
+UIStringOverrider::UIStringOverrider() = default;
 
-UIStringOverrider::UIStringOverrider(const uint32_t* resource_hashes,
-                                     const int* resource_indices,
-                                     size_t num_resources)
-    : resource_hashes_(resource_hashes),
-      resource_indices_(resource_indices),
-      num_resources_(num_resources) {
-  DCHECK(!num_resources || resource_hashes_);
-  DCHECK(!num_resources || resource_indices_);
+UIStringOverrider::UIStringOverrider(base::span<const uint32_t> resource_hashes,
+                                     base::span<const int> resource_indices)
+    : resource_hashes_(resource_hashes), resource_indices_(resource_indices) {
+  CHECK_EQ(resource_hashes_.size(), resource_indices_.size());
 }
 
-UIStringOverrider::~UIStringOverrider() {}
+UIStringOverrider::~UIStringOverrider() = default;
 
 int UIStringOverrider::GetResourceIndex(uint32_t hash) {
-  if (!num_resources_)
+  if (resource_hashes_.empty()) {
     return -1;
-  const uint32_t* end = resource_hashes_ + num_resources_;
-  const uint32_t* element = std::lower_bound(resource_hashes_.get(), end, hash);
-  if (element == end || *element != hash)
+  }
+  const auto begin = std::begin(resource_hashes_);
+  const auto end = std::end(resource_hashes_);
+  const auto element = std::lower_bound(begin, end, hash);
+  if (element == end || *element != hash) {
     return -1;
-  return resource_indices_[element - resource_hashes_];
+  }
+  return resource_indices_[element - begin];
 }
 
 }  // namespace variations
diff --git a/components/variations/service/ui_string_overrider.h b/components/variations/service/ui_string_overrider.h
index d1a114d..671cc13d 100644
--- a/components/variations/service/ui_string_overrider.h
+++ b/components/variations/service/ui_string_overrider.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/memory/raw_ptr.h"
+#include "base/containers/span.h"
 
 namespace variations {
 
@@ -32,9 +32,8 @@
 class UIStringOverrider {
  public:
   UIStringOverrider();
-  UIStringOverrider(const uint32_t* resource_hashes,
-                    const int* resource_indices,
-                    size_t num_resources);
+  UIStringOverrider(base::span<const uint32_t> resource_hashes,
+                    base::span<const int> resource_indices);
 
   UIStringOverrider& operator=(const UIStringOverrider&) = delete;
 
@@ -45,9 +44,8 @@
   int GetResourceIndex(uint32_t hash);
 
  private:
-  const raw_ptr<const uint32_t, AllowPtrArithmetic> resource_hashes_;
-  const raw_ptr<const int, DanglingUntriaged> resource_indices_;
-  size_t const num_resources_;
+  const base::span<const uint32_t> resource_hashes_;
+  const base::span<const int> resource_indices_;
 };
 
 }  // namespace variations
diff --git a/components/variations/service/ui_string_overrider_unittest.cc b/components/variations/service/ui_string_overrider_unittest.cc
index 55559c41..965bc5c 100644
--- a/components/variations/service/ui_string_overrider_unittest.cc
+++ b/components/variations/service/ui_string_overrider_unittest.cc
@@ -32,8 +32,7 @@
 
 class UIStringOverriderTest : public ::testing::Test {
  public:
-  UIStringOverriderTest()
-      : provider_(kResourceHashes, kResourceIndices, kNumResources) {}
+  UIStringOverriderTest() : provider_(kResourceHashes, kResourceIndices) {}
 
   UIStringOverriderTest(const UIStringOverriderTest&) = delete;
   UIStringOverriderTest& operator=(const UIStringOverriderTest&) = delete;
diff --git a/components/web_package/BUILD.gn b/components/web_package/BUILD.gn
index 279e2d9c..4a18202 100644
--- a/components/web_package/BUILD.gn
+++ b/components/web_package/BUILD.gn
@@ -91,6 +91,10 @@
     "//mojo/public/cpp/test_support:test_utils",
     "//testing/gtest",
   ]
+
+  if (is_ios) {
+    deps += [ "//components/test:web_package_test_bundle_data" ]
+  }
 }
 
 fuzzer_test("web_bundle_parser_fuzzer") {
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index 0febdc84..401927e 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -704,7 +704,7 @@
 }
 
 void AttributionDataHostManagerImpl::SourceDataAvailable(
-    attribution_reporting::SuitableOrigin reporting_origin,
+    SuitableOrigin reporting_origin,
     attribution_reporting::SourceRegistration data) {
   // This is validated by the Mojo typemapping.
   DCHECK(reporting_origin.IsValid());
@@ -728,7 +728,7 @@
 }
 
 void AttributionDataHostManagerImpl::TriggerDataAvailable(
-    attribution_reporting::SuitableOrigin reporting_origin,
+    SuitableOrigin reporting_origin,
     attribution_reporting::TriggerRegistration data,
     std::vector<network::TriggerVerification> verifications) {
   // This is validated by the Mojo typemapping.
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
index 4a601760..efa233c5 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
@@ -141,8 +141,7 @@
       HandleSource(AllOf(SourceRegistrationIs(SourceRegistrationMatches(
                              SourceRegistrationMatcherConfig(
                                  /*source_event_id=*/10,
-                                 *attribution_reporting::DestinationSet::Create(
-                                     {destination_site}),
+                                 *DestinationSet::Create({destination_site}),
                                  /*priority=*/20,
                                  /*debug_key=*/Optional(789), aggregation_keys,
                                  /*debug_reporting=*/true))),
@@ -485,20 +484,18 @@
 
     EXPECT_CALL(
         mock_manager_,
-        HandleSource(
-            AllOf(SourceRegistrationIs(
-                      SourceRegistrationMatches(SourceRegistrationMatcherConfig(
-                          /*source_event_id=*/10,
-                          *attribution_reporting::DestinationSet::Create(
-                              {destination_site}),
-                          /*priority=*/20, /*debug_key=*/Optional(789),
-                          aggregation_keys,
-                          /*debug_reporting=*/true))),
-                  SourceTypeIs(SourceType::kNavigation),
-                  ImpressionOriginIs(page_origin),
-                  ReportingOriginIs(reporting_origin),
-                  SourceIsWithinFencedFrameIs(false)),
-            kFrameId));
+        HandleSource(AllOf(SourceRegistrationIs(SourceRegistrationMatches(
+                               SourceRegistrationMatcherConfig(
+                                   /*source_event_id=*/10,
+                                   *DestinationSet::Create({destination_site}),
+                                   /*priority=*/20, /*debug_key=*/Optional(789),
+                                   aggregation_keys,
+                                   /*debug_reporting=*/true))),
+                           SourceTypeIs(SourceType::kNavigation),
+                           ImpressionOriginIs(page_origin),
+                           ReportingOriginIs(reporting_origin),
+                           SourceIsWithinFencedFrameIs(false)),
+                     kFrameId));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(mock_manager_, HandleSource);
   }
@@ -1795,8 +1792,7 @@
       HandleSource(AllOf(SourceRegistrationIs(SourceRegistrationMatches(
                              SourceRegistrationMatcherConfig(
                                  /*source_event_id=*/10,
-                                 *attribution_reporting::DestinationSet::Create(
-                                     {destination_site})))),
+                                 *DestinationSet::Create({destination_site})))),
                          SourceTypeIs(SourceType::kEvent),
                          ImpressionOriginIs(page_origin),
                          ReportingOriginIs(reporting_origin),
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
index 0be85f3a..f8af521 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
@@ -337,7 +337,7 @@
 
 double AttributionStorageDelegateImpl::ComputeChannelCapacity(
     const CommonSourceInfo& source,
-    const attribution_reporting::EventReportWindows& event_report_windows,
+    const EventReportWindows& event_report_windows,
     base::Time source_time,
     int max_event_level_reports,
     double randomized_response_rate) {
@@ -356,11 +356,11 @@
 base::Time AttributionStorageDelegateImpl::GetExpiryTime(
     absl::optional<base::TimeDelta> declared_expiry,
     base::Time source_time,
-    attribution_reporting::mojom::SourceType source_type) {
+    SourceType source_type) {
   base::TimeDelta expiry =
       declared_expiry.value_or(kDefaultAttributionSourceExpiry);
 
-  if (source_type == attribution_reporting::mojom::SourceType::kEvent) {
+  if (source_type == SourceType::kEvent) {
     expiry = expiry.RoundToMultiple(base::Days(1));
   }
 
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc
index 329a65f..6c6a2ae 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -1190,10 +1190,8 @@
           new_aggregatable_report = absl::nullopt;
         }
 
-        if (event_level_status ==
-                AttributionTrigger::EventLevelResult::kInternalError ||
-            aggregatable_status ==
-                AttributionTrigger::AggregatableResult::kInternalError) {
+        if (event_level_status == EventLevelResult::kInternalError ||
+            aggregatable_status == AggregatableResult::kInternalError) {
           min_null_aggregatable_report_time.reset();
         }
 
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
index 51a7532..4c33f6e 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
@@ -997,12 +997,10 @@
 
 TEST_P(AttributionStorageSqlTest, DeleteAttributionDataByDataKey) {
   OpenDatabase();
-  storage()->StoreSource(
-      SourceBuilder()
-          .SetReportingOrigin(
-              *attribution_reporting::SuitableOrigin::Deserialize(
-                  "https://report1.test"))
-          .Build());
+  storage()->StoreSource(SourceBuilder()
+                             .SetReportingOrigin(*SuitableOrigin::Deserialize(
+                                 "https://report1.test"))
+                             .Build());
 
   delegate()->set_null_aggregatable_reports(
       {AttributionStorageDelegate::NullAggregatableReport{
@@ -1011,8 +1009,7 @@
   AttributionTrigger trigger =
       DefaultAggregatableTriggerBuilder()
           .SetReportingOrigin(
-              *attribution_reporting::SuitableOrigin::Deserialize(
-                  "https://report2.test"))
+              *SuitableOrigin::Deserialize("https://report2.test"))
           .Build();
   storage()->MaybeCreateAndStoreReport(trigger);
 
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc
index 13de12c..a2524df 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.cc
+++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -425,10 +425,9 @@
 
     event_triggers.emplace_back(
         event_source_trigger_data_, priority_, dedup_key_,
-        attribution_reporting::FilterPair(
-            /*positive=*/attribution_reporting::FiltersForSourceType(
-                SourceType::kEvent),
-            /*negative=*/{}));
+        FilterPair(/*positive=*/attribution_reporting::FiltersForSourceType(
+                       SourceType::kEvent),
+                   /*negative=*/{}));
   }
 
   return AttributionTrigger(
@@ -443,8 +442,7 @@
       destination_origin_, verifications_, is_within_fenced_frame_);
 }
 
-AttributionInfoBuilder::AttributionInfoBuilder(
-    attribution_reporting::SuitableOrigin context_origin)
+AttributionInfoBuilder::AttributionInfoBuilder(SuitableOrigin context_origin)
     : context_origin_(std::move(context_origin)) {}
 
 AttributionInfoBuilder::~AttributionInfoBuilder() = default;
diff --git a/content/browser/attribution_reporting/attributions_browsertest.cc b/content/browser/attribution_reporting/attributions_browsertest.cc
index f61f8564..5d136ad 100644
--- a/content/browser/attribution_reporting/attributions_browsertest.cc
+++ b/content/browser/attribution_reporting/attributions_browsertest.cc
@@ -1021,7 +1021,7 @@
       ContentBrowserTestContentBrowserClient>
       browser_client;
   EXPECT_CALL(browser_client, IsWebAttributionReportingAllowed())
-      .WillRepeatedly(testing::Return(false));
+      .WillRepeatedly(Return(false));
 
   auto register_response =
       std::make_unique<net::test_server::ControllableHttpResponse>(
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index c86f1e0..c34c085 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -62,7 +62,6 @@
 
 scoped_refptr<viz::ContextProviderCommandBuffer> CreateContextProvider(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
-    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     bool supports_locking,
     bool supports_gles2_interface,
     bool supports_raster_interface,
@@ -83,10 +82,9 @@
 
   GURL url("chrome://gpu/VizProcessTransportFactory::CreateContextProvider");
   return base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-      std::move(gpu_channel_host), gpu_memory_buffer_manager,
-      kGpuStreamIdDefault, kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
-      std::move(url), kAutomaticFlushes, supports_locking, supports_grcontext,
-      memory_limits, attributes, type);
+      std::move(gpu_channel_host), kGpuStreamIdDefault, kGpuStreamPriorityUI,
+      gpu::kNullSurfaceHandle, std::move(url), kAutomaticFlushes,
+      supports_locking, supports_grcontext, memory_limits, attributes, type);
 }
 
 bool IsContextLost(viz::ContextProvider* context_provider) {
@@ -528,8 +526,7 @@
 
   if (!worker_context_provider_wrapper_) {
     auto worker_context_provider = CreateContextProvider(
-        gpu_channel_host, GetGpuMemoryBufferManager(),
-        /*supports_locking=*/true,
+        gpu_channel_host, /*supports_locking=*/true,
         /*supports_gles2_interface=*/false,
         /*supports_raster_interface=*/true,
         /*supports_grcontext=*/false, enable_gpu_rasterization,
@@ -563,10 +560,9 @@
     constexpr bool kCompositorContextSupportsOOPR = false;
 
     main_context_provider_ = CreateContextProvider(
-        std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
-        kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2,
-        kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext,
-        kCompositorContextSupportsOOPR,
+        std::move(gpu_channel_host), kCompositorContextSupportsLocking,
+        kCompositorContextSupportsGLES2, kCompositorContextSupportsRaster,
+        kCompositorContextSupportsGrContext, kCompositorContextSupportsOOPR,
         viz::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
     main_context_provider_->SetDefaultTaskRunner(resize_task_runner_);
 
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc
index fabf29b4..ccdd164 100644
--- a/content/browser/interest_group/interest_group_auction.cc
+++ b/content/browser/interest_group/interest_group_auction.cc
@@ -98,7 +98,11 @@
 
 namespace {
 
+#if !defined(NDEBUG)
+constexpr base::TimeDelta kMaxPerBuyerTimeout = base::Seconds(60);
+#else
 constexpr base::TimeDelta kMaxPerBuyerTimeout = base::Milliseconds(500);
+#endif
 
 // For group freshness metrics.
 constexpr base::TimeDelta kGroupFreshnessMin = base::Minutes(1);
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index a140f9d..c1e6d113 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -15568,23 +15568,20 @@
 }
 
 // TODO(crbug.com/1474303): Re-enable this test
-IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, DISABLED_AuctionNonceIsValid) {
+IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, AuctionNonceIsValid) {
   GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html");
   ASSERT_TRUE(NavigateToURL(shell(), test_url));
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess,
-            JoinInterestGroupAndVerify(
-                blink::TestInterestGroupBuilder(
-                    /*owner=*/test_origin,
-                    /*name=*/"cars")
-                    .SetBiddingUrl(https_server_->GetURL(
-                        "a.test", "/interest_group/bidding_logic_use_wasm.js"))
-                    .SetBiddingWasmHelperUrl(https_server_->GetURL(
-                        "a.test", "/interest_group/multiply.wasm"))
-                    .SetAds({{{ad_url, R"({"ad":"metadata","here":[1,2]})"}}})
-                    .Build()));
+  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
+                          blink::TestInterestGroupBuilder(
+                              /*owner=*/test_origin,
+                              /*name=*/"cars")
+                              .SetBiddingUrl(https_server_->GetURL(
+                                  "a.test", "/interest_group/bidding_logic.js"))
+                              .SetAds({{{ad_url, /*metadata=*/absl::nullopt}}})
+                              .Build()));
 
   std::string auction_nonce = CreateAuctionNonceAndWait();
 
@@ -15608,17 +15605,14 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(
-      kSuccess,
-      JoinInterestGroupAndVerify(
-          /*owner=*/test_origin,
-          /*name=*/"cars",
-          /*priority=*/0.0,
-          /*execution_mode=*/
-          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
-          /*bidding_url=*/
-          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
-          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
+                          blink::TestInterestGroupBuilder(
+                              /*owner=*/test_origin,
+                              /*name=*/"cars")
+                              .SetBiddingUrl(https_server_->GetURL(
+                                  "a.test", "/interest_group/bidding_logic.js"))
+                              .SetAds({{{ad_url, /*metadata=*/absl::nullopt}}})
+                              .Build()));
 
   std::string auction_nonce = CreateAuctionNonceAndWait();
 
diff --git a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
index e360acd..a20ef820 100644
--- a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
+++ b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
@@ -31,9 +31,6 @@
   attributes.bind_generates_resource = false;
   attributes.enable_raster_interface = true;
 
-  gpu::GpuChannelEstablishFactory* factory =
-      BrowserMainLoop::GetInstance()->gpu_channel_establish_factory();
-
   int32_t stream_id = kGpuStreamIdDefault;
   gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;
 
@@ -43,8 +40,8 @@
 
   auto context_provider =
       base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-          std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
-          stream_id, stream_priority, gpu::kNullSurfaceHandle,
+          std::move(gpu_channel_host), stream_id, stream_priority,
+          gpu::kNullSurfaceHandle,
           GURL(std::string("chrome://gpu/"
                            "BrowserGpuVideoAcceleratorFactories::"
                            "CreateGpuVideoAcceleratorFactories")),
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 0bce0275e..f30af14 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -158,9 +158,6 @@
     return;
   }
 
-  gpu::GpuChannelEstablishFactory* factory =
-      BrowserGpuChannelHostFactory::instance();
-
   int32_t stream_id = kGpuStreamIdDefault;
   gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;
 
@@ -170,8 +167,7 @@
 
   auto context_provider =
       base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-          std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
-          stream_id, stream_priority, handle,
+          std::move(gpu_channel_host), stream_id, stream_priority, handle,
           GURL(std::string("chrome://gpu/Compositor::CreateContextProvider")),
           automatic_flushes, support_locking, support_grcontext,
           shared_memory_limits, attributes,
@@ -658,9 +654,6 @@
   DCHECK(window_);
   DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle);
 
-  gpu::GpuChannelEstablishFactory* factory =
-      BrowserGpuChannelHostFactory::instance();
-
   int32_t stream_id = kGpuStreamIdDefault;
   gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;
 
@@ -673,8 +666,8 @@
 
   auto context_provider =
       base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-          std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
-          stream_id, stream_priority, gpu::kNullSurfaceHandle,
+          std::move(gpu_channel_host), stream_id, stream_priority,
+          gpu::kNullSurfaceHandle,
           GURL(std::string("chrome://gpu/CompositorImpl::") +
                std::string("CompositorContextProvider")),
           automatic_flushes, support_locking, support_grcontext,
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc
index d93e9f2..0ed07a8 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader.cc
+++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -14,6 +14,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "base/strings/strcat.h"
+#include "base/time/time.h"
 #include "base/trace_event/common/trace_event_common.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/service_worker/service_worker_container_host.h"
@@ -570,10 +571,21 @@
       blink::ServiceWorkerStatusToString(status), "result",
       ComposeFetchEventResultString(fetch_result, *response));
 
+  bool is_fallback =
+      fetch_result ==
+      ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback;
+
+  // When AutoPreload is dispatched, set the fetch handler end time and record
+  // loading metrics.
+  if (dispatched_preload_type() == DispatchedPreloadType::kAutoPreload) {
+    race_network_request_url_loader_client_
+        ->MaybeRecordResponseReceivedToFetchHandlerEndTiming(
+            base::TimeTicks::Now(), /*is_fallback=*/is_fallback);
+  }
+
   // Transition the state if the fetch result is fallback. This is a special
   // treatment for RaceNetworkRequest and AutoPreload.
-  if (fetch_result ==
-      ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
+  if (is_fallback) {
     switch (commit_responsibility()) {
       case FetchResponseFrom::kNoResponseYet:
         // If the RaceNetworkRequest or AutoPreload is triggered but the
@@ -692,8 +704,7 @@
   // the service workers because we aim to see the fallback ratio and timing.
   RecordFetchEventHandlerMetrics(fetch_result);
 
-  if (fetch_result ==
-      ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
+  if (is_fallback) {
     TransitionToStatus(Status::kCompleted);
     RecordTimingMetricsForNetworkFallbackCase();
     if (fallback_callback_) {
diff --git a/content/common/service_worker/race_network_request_url_loader_client.cc b/content/common/service_worker/race_network_request_url_loader_client.cc
index d4ae377c..dc15ba2 100644
--- a/content/common/service_worker/race_network_request_url_loader_client.cc
+++ b/content/common/service_worker/race_network_request_url_loader_client.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "base/strings/strcat.h"
+#include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "content/common/features.h"
 #include "content/common/service_worker/service_worker_resource_loader.h"
@@ -20,6 +21,11 @@
 
 namespace content {
 namespace {
+const char kMainResourceHistogramLoadTiming[] =
+    "ServiceWorker.LoadTiming.MainFrame.MainResource";
+const char kSubresourceHistogramLoadTiming[] =
+    "ServiceWorker.LoadTiming.Subresource";
+
 MojoResult CreateDataPipe(mojo::ScopedDataPipeProducerHandle& producer_handle,
                           mojo::ScopedDataPipeConsumerHandle& consumer_handle,
                           uint32_t capacity_num_bytes) {
@@ -100,6 +106,15 @@
   }
 
   TransitionState(State::kResponseReceived);
+
+  // Set the response received time, and record the time delta between the
+  // response received time and the fetch handler end time if the fetch handler
+  // is already completed.
+  if (!response_received_time_) {
+    response_received_time_ = base::TimeTicks::Now();
+  }
+  MaybeRecordResponseReceivedToFetchHandlerEndTiming();
+
   switch (data_consume_policy_) {
     case DataConsumePolicy::kTeeResponse:
       head_ = std::move(head);
@@ -123,6 +138,7 @@
   TransitionState(State::kRedirect);
   // If redirect happened, we don't have to create another data pipe.
   data_consume_policy_ = DataConsumePolicy::kForwardingOnly;
+  response_received_time_ = base::TimeTicks::Now();
 
   // TODO(crbug.com/1420517): Return a redirect response to |owner| as a
   // RaceNetworkRequest result without breaking the cache storage compatibility.
@@ -494,6 +510,45 @@
   body_consumer_watcher_.Cancel();
 }
 
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::SetFetchHandlerEndTiming(
+    base::TimeTicks fetch_handler_end_time,
+    bool is_fallback) {
+  fetch_handler_end_time_ = fetch_handler_end_time;
+  is_fetch_handler_fallback_ = is_fallback;
+}
+
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::
+    MaybeRecordResponseReceivedToFetchHandlerEndTiming() {
+  if (response_received_time_ && fetch_handler_end_time_ &&
+      is_fetch_handler_fallback_.has_value()) {
+    RecordResponseReceivedToFetchHandlerEndTiming();
+  }
+}
+
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::
+    MaybeRecordResponseReceivedToFetchHandlerEndTiming(
+        base::TimeTicks fetch_handler_end_time,
+        bool is_fallback) {
+  SetFetchHandlerEndTiming(fetch_handler_end_time, is_fallback);
+  MaybeRecordResponseReceivedToFetchHandlerEndTiming();
+}
+
+void ServiceWorkerRaceNetworkRequestURLLoaderClient::
+    RecordResponseReceivedToFetchHandlerEndTiming() {
+  if (!owner_) {
+    return;
+  }
+
+  base::UmaHistogramTimes(
+      base::StrCat({owner_->IsMainResourceLoader()
+                        ? kMainResourceHistogramLoadTiming
+                        : kSubresourceHistogramLoadTiming,
+                    ".AutoPreloadResponseReceivedToFetchHandlerEnd.",
+                    is_fetch_handler_fallback_ ? "WithoutServiceWorker"
+                                               : "ServiceWorker"}),
+      fetch_handler_end_time_.value() - response_received_time_.value());
+}
+
 void ServiceWorkerRaceNetworkRequestURLLoaderClient::TransitionState(
     State new_state) {
   switch (new_state) {
diff --git a/content/common/service_worker/race_network_request_url_loader_client.h b/content/common/service_worker/race_network_request_url_loader_client.h
index e7afec4..ec0fde92 100644
--- a/content/common/service_worker/race_network_request_url_loader_client.h
+++ b/content/common/service_worker/race_network_request_url_loader_client.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_COMMON_SERVICE_WORKER_RACE_NETWORK_REQUEST_URL_LOADER_CLIENT_H_
 #define CONTENT_COMMON_SERVICE_WORKER_RACE_NETWORK_REQUEST_URL_LOADER_CLIENT_H_
 
+#include "base/time/time.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_resource_loader.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -141,6 +142,10 @@
   // Commit and complete the response. Those can be called from |owner_|.
   void CommitAndCompleteResponseIfDataTransferFinished();
 
+  void MaybeRecordResponseReceivedToFetchHandlerEndTiming(
+      base::TimeTicks fetch_handler_end_time,
+      bool is_fallback);
+
  private:
   struct DataPipeInfo {
     mojo::ScopedDataPipeProducerHandle producer;
@@ -191,6 +196,14 @@
 
   void Abort();
 
+  void RecordResponseReceivedToFetchHandlerEndTiming();
+  // Record the time between the response received time and the fetch handler
+  // end time iff both events are already reached.
+  void MaybeRecordResponseReceivedToFetchHandlerEndTiming();
+
+  void SetFetchHandlerEndTiming(base::TimeTicks fetch_handler_end_time,
+                                bool is_fallback);
+
   State state_ = State::kWaitForBody;
   mojo::Receiver<network::mojom::URLLoaderClient> receiver_{this};
   const network::ResourceRequest request_;
@@ -208,6 +221,9 @@
   bool redirected_ = false;
   std::unique_ptr<mojo::DataPipeDrainer> data_drainer_;
   DataConsumePolicy data_consume_policy_ = DataConsumePolicy::kTeeResponse;
+  absl::optional<base::TimeTicks> response_received_time_;
+  absl::optional<base::TimeTicks> fetch_handler_end_time_;
+  absl::optional<bool> is_fetch_handler_fallback_;
 
   base::WeakPtrFactory<ServiceWorkerRaceNetworkRequestURLLoaderClient>
       weak_factory_{this};
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc
index 6f61efe..123da0e8 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc
@@ -131,12 +131,10 @@
 class MockContextProviderCommandBuffer
     : public viz::ContextProviderCommandBuffer {
  public:
-  MockContextProviderCommandBuffer(
-      scoped_refptr<gpu::GpuChannelHost> channel,
-      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
+  explicit MockContextProviderCommandBuffer(
+      scoped_refptr<gpu::GpuChannelHost> channel)
       : viz::ContextProviderCommandBuffer(
             std::move(channel),
-            gpu_memory_buffer_manager,
             content::kGpuStreamIdDefault,
             content::kGpuStreamPriorityDefault,
             gpu::kNullSurfaceHandle,
@@ -371,8 +369,7 @@
             base::MakeRefCounted<TestGpuChannelHost>(mock_gpu_channel_)),
         mock_context_provider_(
             base::MakeRefCounted<NiceMock<MockContextProviderCommandBuffer>>(
-                gpu_channel_host_,
-                &gpu_memory_buffer_manager_)) {}
+                gpu_channel_host_)) {}
   ~GpuVideoAcceleratorFactoriesImplTest() override = default;
 
   void SetUp() override {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index d1f8638..328ed025 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -319,7 +319,6 @@
 
 scoped_refptr<viz::ContextProviderCommandBuffer> CreateOffscreenContext(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
-    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     const gpu::SharedMemoryLimits& limits,
     bool support_locking,
     bool support_gles2_interface,
@@ -349,8 +348,8 @@
                                         support_raster_interface &&
                                         !support_gles2_interface;
   return base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-      std::move(gpu_channel_host), gpu_memory_buffer_manager, stream_id,
-      stream_priority, gpu::kNullSurfaceHandle,
+      std::move(gpu_channel_host), stream_id, stream_priority,
+      gpu::kNullSurfaceHandle,
       GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext/" +
            viz::command_buffer_metrics::ContextTypeToString(type)),
       automatic_flushes, support_locking, support_grcontext, limits, attributes,
@@ -1047,12 +1046,12 @@
   bool support_grcontext = false;
   bool automatic_flushes = false;
   scoped_refptr<viz::ContextProviderCommandBuffer> media_context_provider =
-      CreateOffscreenContext(
-          gpu_channel_host, GetGpuMemoryBufferManager(), limits,
-          support_locking, support_gles2_interface, support_raster_interface,
-          support_oop_rasterization, support_grcontext, automatic_flushes,
-          viz::command_buffer_metrics::ContextType::MEDIA, kGpuStreamIdMedia,
-          kGpuStreamPriorityMedia);
+      CreateOffscreenContext(gpu_channel_host, limits, support_locking,
+                             support_gles2_interface, support_raster_interface,
+                             support_oop_rasterization, support_grcontext,
+                             automatic_flushes,
+                             viz::command_buffer_metrics::ContextType::MEDIA,
+                             kGpuStreamIdMedia, kGpuStreamPriorityMedia);
 
   const bool enable_video_decode_accelerator =
 #if BUILDFLAG(IS_LINUX)
@@ -1140,9 +1139,9 @@
   bool support_grcontext = false;
   bool automatic_flushes = false;
   video_frame_compositor_context_provider_ = CreateOffscreenContext(
-      gpu_channel_host, GetGpuMemoryBufferManager(), limits, support_locking,
-      support_gles2_interface, support_raster_interface,
-      support_oop_rasterization, support_grcontext, automatic_flushes,
+      gpu_channel_host, limits, support_locking, support_gles2_interface,
+      support_raster_interface, support_oop_rasterization, support_grcontext,
+      automatic_flushes,
       viz::command_buffer_metrics::ContextType::RENDER_COMPOSITOR,
       kGpuStreamIdMedia, kGpuStreamPriorityMedia);
   return video_frame_compositor_context_provider_;
@@ -1184,10 +1183,9 @@
   // synchronization between the pepper context and the shared main thread
   // context.
   shared_main_thread_contexts_ = CreateOffscreenContext(
-      std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
-      gpu::SharedMemoryLimits(), support_locking, support_gles2_interface,
-      support_raster_interface, support_oop_rasterization, support_grcontext,
-      automatic_flushes,
+      std::move(gpu_channel_host), gpu::SharedMemoryLimits(), support_locking,
+      support_gles2_interface, support_raster_interface,
+      support_oop_rasterization, support_grcontext, automatic_flushes,
       viz::command_buffer_metrics::ContextType::RENDERER_MAIN_THREAD,
       kGpuStreamIdDefault, kGpuStreamPriorityDefault);
   auto result = shared_main_thread_contexts_->BindToCurrentSequence();
@@ -1225,9 +1223,8 @@
   // synchronization between the pepper context and the shared main thread
   // context.
   pepper_video_decode_contexts_ = CreateOffscreenContext(
-      std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
-      gpu::SharedMemoryLimits::ForMailboxContext(), support_locking,
-      support_gles2_interface, support_raster_interface,
+      std::move(gpu_channel_host), gpu::SharedMemoryLimits::ForMailboxContext(),
+      support_locking, support_gles2_interface, support_raster_interface,
       support_oop_rasterization, support_grcontext, automatic_flushes,
       viz::command_buffer_metrics::ContextType::RENDERER_MAIN_THREAD,
       kGpuStreamIdDefault, kGpuStreamPriorityDefault);
@@ -1701,10 +1698,9 @@
                                 : gpu::SharedMemoryLimits();
   scoped_refptr<viz::ContextProviderCommandBuffer>
       shared_worker_context_provider = CreateOffscreenContext(
-          std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
-          shared_memory_limits, support_locking, support_gles2_interface,
-          support_raster_interface, support_gpu_rasterization,
-          support_grcontext, automatic_flushes,
+          std::move(gpu_channel_host), shared_memory_limits, support_locking,
+          support_gles2_interface, support_raster_interface,
+          support_gpu_rasterization, support_grcontext, automatic_flushes,
           viz::command_buffer_metrics::ContextType::RENDER_WORKER,
           kGpuStreamIdWorker, kGpuStreamPriorityWorker);
 
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 321cfcb..0371357 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -677,7 +677,7 @@
   scoped_refptr<viz::ContextProviderCommandBuffer> provider(
       new viz::ContextProviderCommandBuffer(
           std::move(gpu_channel_host),
-          RenderThreadImpl::current()->GetGpuMemoryBufferManager(),
+
           kGpuStreamIdDefault, kGpuStreamPriorityDefault,
           gpu::kNullSurfaceHandle, GURL(document_url), automatic_flushes,
           support_locking, use_grcontext, gpu::SharedMemoryLimits(), attributes,
@@ -750,7 +750,7 @@
   scoped_refptr<viz::ContextProviderCommandBuffer> provider(
       new viz::ContextProviderCommandBuffer(
           std::move(gpu_channel_host),
-          RenderThreadImpl::current()->GetGpuMemoryBufferManager(),
+
           kGpuStreamIdDefault, kGpuStreamPriorityDefault,
           gpu::kNullSurfaceHandle, GURL(document_url), automatic_flushes,
           support_locking, support_grcontext,
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index ec74af3..f8b9f0c 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -612,11 +612,16 @@
                           TRACE_ID_LOCAL(request_id_)),
       TRACE_EVENT_FLAG_FLOW_IN);
 
-  // Update the commit responsibility to the intermediate state
-  // |kAutoPreloadHandlingFallback| for the fallback. This is a special
-  // treatment for AutoPreload.
   if (dispatched_preload_type() == DispatchedPreloadType::kAutoPreload &&
       commit_responsibility() == FetchResponseFrom::kServiceWorker) {
+    // When AutoPreload is dispatched, set the fetch handler end time and record
+    // loading metrics.
+    race_network_request_loader_client_
+        ->MaybeRecordResponseReceivedToFetchHandlerEndTiming(
+            base::TimeTicks::Now(), /*is_fallback=*/true);
+    // Update the commit responsibility to the intermediate state
+    // |kAutoPreloadHandlingFallback| for the fallback. This is a special
+    // treatment for AutoPreload.
     SetCommitResponsibility(FetchResponseFrom::kAutoPreloadHandlingFallback);
   }
 
@@ -725,6 +730,13 @@
 void ServiceWorkerSubresourceLoader::StartResponse(
     blink::mojom::FetchAPIResponsePtr response,
     blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+  // When AutoPreload is dispatched, set the fetch handler end time and record
+  // loading metrics.
+  if (dispatched_preload_type() == DispatchedPreloadType::kAutoPreload) {
+    race_network_request_loader_client_
+        ->MaybeRecordResponseReceivedToFetchHandlerEndTiming(
+            base::TimeTicks::Now(), /*is_fallback=*/false);
+  }
   switch (commit_responsibility()) {
     case FetchResponseFrom::kNoResponseYet:
     case FetchResponseFrom::kSubresourceLoaderIsHandlingRedirect:
diff --git a/content/services/isolated_xr_device/xr_runtime_provider.cc b/content/services/isolated_xr_device/xr_runtime_provider.cc
index 27c89a1..4d59786a 100644
--- a/content/services/isolated_xr_device/xr_runtime_provider.cc
+++ b/content/services/isolated_xr_device/xr_runtime_provider.cc
@@ -193,9 +193,9 @@
 
   scoped_refptr<viz::ContextProvider> context_provider =
       base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-          viz_gpu_->GetGpuChannel(), nullptr /* gpu_memory_buffer_manager */,
-          content::kGpuStreamIdDefault, content::kGpuStreamPriorityUI,
-          gpu::kNullSurfaceHandle, GURL(std::string("chrome://gpu/XrRuntime")),
+          viz_gpu_->GetGpuChannel(), content::kGpuStreamIdDefault,
+          content::kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
+          GURL(std::string("chrome://gpu/XrRuntime")),
           false /* automatic flushes */, false /* support locking */,
           false /* support grcontext */,
           gpu::SharedMemoryLimits::ForMailboxContext(),
diff --git a/content/test/fuzzer/browser_accessibility_fuzzer.cc b/content/test/fuzzer/browser_accessibility_fuzzer.cc
index cb478857..f2f62ccb 100644
--- a/content/test/fuzzer/browser_accessibility_fuzzer.cc
+++ b/content/test/fuzzer/browser_accessibility_fuzzer.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
 #include "content/browser/accessibility/test_browser_accessibility_delegate.h"
 #include "content/public/test/browser_task_environment.h"
@@ -71,6 +72,7 @@
 // functions that walk the tree in various ways to ensure they don't crash.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   static Env env;
+  auto accessibility_state = BrowserAccessibilityStateImpl::Create();
   FuzzedDataProvider fdp(data, size);
 
   // The tree structure is always the same, only the data changes.
diff --git a/content/test/gpu_browsertest_helpers.cc b/content/test/gpu_browsertest_helpers.cc
index 7314fbd..7993bc7 100644
--- a/content/test/gpu_browsertest_helpers.cc
+++ b/content/test/gpu_browsertest_helpers.cc
@@ -49,18 +49,16 @@
 
 scoped_refptr<viz::ContextProviderCommandBuffer> GpuBrowsertestCreateContext(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
-  gpu::GpuChannelEstablishFactory* factory =
-      content::BrowserMainLoop::GetInstance()->gpu_channel_establish_factory();
   gpu::ContextCreationAttribs attributes;
   attributes.bind_generates_resource = false;
   constexpr bool automatic_flushes = false;
   constexpr bool support_locking = false;
   constexpr bool support_grcontext = true;
   return base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-      std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
-      content::kGpuStreamIdDefault, content::kGpuStreamPriorityDefault,
-      gpu::kNullSurfaceHandle, GURL(), automatic_flushes, support_locking,
-      support_grcontext, gpu::SharedMemoryLimits(), attributes,
+      std::move(gpu_channel_host), content::kGpuStreamIdDefault,
+      content::kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, GURL(),
+      automatic_flushes, support_locking, support_grcontext,
+      gpu::SharedMemoryLimits(), attributes,
       viz::command_buffer_metrics::ContextType::FOR_TESTING);
 }
 
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 950eace..c99f2936 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -589,6 +589,7 @@
     "//components/permissions",
     "//components/pref_registry",
     "//components/prefs",
+    "//components/safe_browsing/core/browser/hashprefix_realtime:hash_realtime_utils",
     "//components/safe_browsing/core/common",
     "//components/services/unzip/content",
     "//components/services/unzip/public/cpp",
@@ -955,6 +956,8 @@
     "//components/permissions:permissions_common",
     "//components/pref_registry:pref_registry",
     "//components/prefs:test_support",
+    "//components/safe_browsing/core/browser/hashprefix_realtime:hash_realtime_utils",
+    "//components/safe_browsing/core/common",
     "//components/services/unzip:in_process",
     "//components/services/unzip/content",
     "//components/storage_monitor:test_support",
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index ad9f30775..817f2f2 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -6,6 +6,7 @@
   "+components/guest_view",
   "+components/keyed_service",
   "+components/pref_registry",
+  "+components/safe_browsing/core/browser/hashprefix_realtime",
   "+components/services/unzip/content",
   "+components/services/unzip/public",
   "+components/sessions",
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc
index 4b175b4..e68c01fa 100644
--- a/extensions/browser/api/web_request/web_request_permissions.cc
+++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -9,6 +9,8 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "build/chromeos_buildflags.h"
+#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/browser/api/extensions_api_client.h"
@@ -339,6 +341,12 @@
       extension_urls::IsBlocklistUpdateUrl(url) ||
       extension_urls::IsSafeBrowsingUrl(url::Origin::Create(url),
                                         url.path_piece()) ||
+      // TODO(crbug.com/1476651): The following check should ideally be within
+      // IsSafeBrowsingUrl. This will be possible if hash_realtime_utils is
+      // moved to live within /content instead of /browser.
+      (safe_browsing::hash_realtime_utils::
+           IsHashRealTimeLookupEligibleInSession() &&
+       url == safe_browsing::kHashPrefixRealTimeLookupsRelayUrl.Get()) ||
       (url.DomainIs("chrome.google.com") &&
        base::StartsWith(url.path_piece(), "/webstore",
                         base::CompareCase::SENSITIVE)) ||
diff --git a/extensions/browser/api/web_request/web_request_permissions_unittest.cc b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
index 49fa9e2..11b2ef7 100644
--- a/extensions/browser/api/web_request/web_request_permissions_unittest.cc
+++ b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
@@ -6,6 +6,9 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_utils.h"
+#include "components/safe_browsing/core/common/features.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/web_request/permission_helper.h"
@@ -28,7 +31,41 @@
 
 using ExtensionWebRequestPermissionsTest = ExtensionsTest;
 
-TEST_F(ExtensionWebRequestPermissionsTest, TestHideRequestForURL) {
+constexpr char kTestRelayUrl[] = "https://ohttp.endpoint.test/";
+
+class ExtensionWebRequestPermissionsWithHashRealTimeDependenceTest
+    : public ExtensionsTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  void SetUp() override {
+    ExtensionsTest::SetUp();
+    if (GetParam()) {
+      feature_list_.InitWithFeaturesAndParameters(
+          /*enabled_features=*/
+          {{safe_browsing::kHashPrefixRealTimeLookups,
+            {{"SafeBrowsingHashPrefixRealTimeLookupsRelayUrl",
+              kTestRelayUrl}}}},
+          /*disabled_features=*/{});
+    } else {
+      feature_list_.InitWithFeatures(
+          /*enabled_features=*/{},
+          /*disabled_features=*/{safe_browsing::kHashPrefixRealTimeLookups});
+    }
+  }
+
+ private:
+  safe_browsing::hash_realtime_utils::GoogleChromeBrandingPretenderForTesting
+      apply_branding_;
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    ExtensionWebRequestPermissionsWithHashRealTimeDependenceTest,
+    testing::Bool());
+
+TEST_P(ExtensionWebRequestPermissionsWithHashRealTimeDependenceTest,
+       TestHideRequestForURL) {
   enum HideRequestMask {
     HIDE_NONE = 0,
     HIDE_RENDERER_REQUEST = 1,
@@ -45,7 +82,8 @@
   struct TestCase {
     const char* url;
     int expected_hide_request_mask;
-  } cases[] = {
+  };
+  std::vector<TestCase> cases = {
       {"https://www.google.com", HIDE_BROWSER_SUB_RESOURCE_REQUEST},
       {"http://www.example.com", HIDE_BROWSER_SUB_RESOURCE_REQUEST},
       {"https://www.example.com", HIDE_BROWSER_SUB_RESOURCE_REQUEST},
@@ -111,6 +149,19 @@
        "kcnhkahnjcbndmmehfkdnkjomaanaooo",
        HIDE_ALL},
   };
+  std::vector<TestCase> additional_cases;
+  if (GetParam()) {
+    additional_cases = {
+        {"https://ohttp.endpoint.test", HIDE_ALL},
+        {"https://ohttp.endpoint.test/", HIDE_ALL},
+        {"https://ohttp.endpoint.test/path", HIDE_BROWSER_SUB_RESOURCE_REQUEST},
+        {"https://endpoint.test/", HIDE_BROWSER_SUB_RESOURCE_REQUEST}};
+  } else {
+    additional_cases = {
+        {"https://ohttp.endpoint.test/", HIDE_BROWSER_SUB_RESOURCE_REQUEST}};
+  }
+  cases.insert(cases.end(), additional_cases.begin(), additional_cases.end());
+
   const int kRendererProcessId = 1;
   const int kBrowserProcessId = -1;
 
diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc
index c316256..ef3eb6c 100644
--- a/gin/array_buffer.cc
+++ b/gin/array_buffer.cc
@@ -34,27 +34,31 @@
 partition_alloc::PartitionRoot* ArrayBufferAllocator::partition_ = nullptr;
 
 void* ArrayBufferAllocator::Allocate(size_t length) {
-  unsigned int flags = partition_alloc::AllocFlags::kZeroFill |
-                       partition_alloc::AllocFlags::kReturnNull;
-  return AllocateInternal(length, flags);
+  constexpr unsigned int flags = partition_alloc::AllocFlags::kZeroFill |
+                                 partition_alloc::AllocFlags::kReturnNull;
+  return AllocateInternal<flags>(length);
 }
 
 void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
-  unsigned int flags = partition_alloc::AllocFlags::kReturnNull;
-  return AllocateInternal(length, flags);
+  constexpr unsigned int flags = partition_alloc::AllocFlags::kReturnNull;
+  return AllocateInternal<flags>(length);
 }
 
-void* ArrayBufferAllocator::AllocateInternal(size_t length,
-                                             unsigned int flags) {
+template <unsigned int flags>
+void* ArrayBufferAllocator::AllocateInternal(size_t length) {
 #ifdef V8_ENABLE_SANDBOX
   // The V8 sandbox requires all ArrayBuffer backing stores to be allocated
   // inside the sandbox address space. This isn't guaranteed if allocation
   // override hooks (which are e.g. used by GWP-ASan) are enabled or if a
   // memory tool (e.g. ASan) overrides malloc, so disable both.
-  flags |= partition_alloc::AllocFlags::kNoOverrideHooks;
-  flags |= partition_alloc::AllocFlags::kNoMemoryToolOverride;
+  constexpr auto new_flags = flags |
+                             partition_alloc::AllocFlags::kNoOverrideHooks |
+                             partition_alloc::AllocFlags::kNoMemoryToolOverride;
+#else
+  constexpr auto new_flags = flags;
 #endif
-  return partition_->AllocWithFlags(flags, length, "gin::ArrayBufferAllocator");
+  return partition_->AllocInline<new_flags>(length,
+                                            "gin::ArrayBufferAllocator");
 }
 
 void ArrayBufferAllocator::Free(void* data, size_t length) {
diff --git a/gin/array_buffer.h b/gin/array_buffer.h
index 5c109b7..5e546dc 100644
--- a/gin/array_buffer.h
+++ b/gin/array_buffer.h
@@ -29,7 +29,8 @@
  private:
   friend class V8Initializer;
 
-  void* AllocateInternal(size_t length, unsigned int flags);
+  template <unsigned int flags>
+  void* AllocateInternal(size_t length);
 
   // Initialize the PartitionAlloc partition from which instances of this class
   // allocate memory. This is called after initializing V8 since, when enabled,
diff --git a/gin/v8_platform_thread_isolated_allocator.cc b/gin/v8_platform_thread_isolated_allocator.cc
index a2167295..b9a1577 100644
--- a/gin/v8_platform_thread_isolated_allocator.cc
+++ b/gin/v8_platform_thread_isolated_allocator.cc
@@ -32,8 +32,8 @@
 }
 
 void* ThreadIsolatedAllocator::Allocate(size_t size) {
-  return allocator_.root()->AllocWithFlagsNoHooks(
-      0, size, partition_alloc::PartitionPageSize());
+  return allocator_.root()->AllocNoHooks(size,
+                                         partition_alloc::PartitionPageSize());
 }
 
 void ThreadIsolatedAllocator::Free(void* object) {
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 999e2c9..9662228 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -102,6 +102,7 @@
   visibility = [ "//gpu/*" ]
 
   deps = []
+  defines = []
   sources = [
     "buffer_manager.cc",
     "buffer_manager.h",
@@ -324,6 +325,9 @@
 
   if (use_dawn) {
     deps += [ "//gpu/webgpu:common" ]
+    if (dawn_use_built_dxc) {
+      defines += [ "DAWN_USE_BUILT_DXC" ]
+    }
     sources += [
       "dawn_caching_interface.cc",
       "dawn_caching_interface.h",
@@ -577,7 +581,7 @@
     # Abstract out the platform specific defines. Right now we need the android
     # platform specific define here to be able to include android specific
     # functions.
-    defines = [ "VK_USE_PLATFORM_ANDROID_KHR" ]
+    defines += [ "VK_USE_PLATFORM_ANDROID_KHR" ]
     deps += [ "//third_party/libsync" ]
     if (enable_vulkan) {
       deps += [ "//gpu/vulkan" ]
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index 7e7ab4f..8eb5edb 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -32,8 +32,9 @@
 bool GetUintFromSwitch(const base::CommandLine* command_line,
                        const base::StringPiece& switch_string,
                        uint32_t* value) {
-  if (!command_line->HasSwitch(switch_string))
+  if (!command_line->HasSwitch(switch_string)) {
     return false;
+  }
   std::string switch_value(command_line->GetSwitchValueASCII(switch_string));
   return base::StringToUint(switch_value, value);
 }
@@ -185,6 +186,18 @@
         command_line->GetSwitchValueASCII(switches::kDisableDawnFeatures), ",",
         base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
   }
+#ifdef DAWN_USE_BUILT_DXC
+  // Drive "use_dxc" with Finch feature flag, unless user forces option via
+  // command line.
+  if (!base::Contains(gpu_preferences.enabled_dawn_features_list, "use_dxc") &&
+      !base::Contains(gpu_preferences.disabled_dawn_features_list, "use_dxc")) {
+    if (base::FeatureList::IsEnabled(features::kWebGPUUseDXC)) {
+      gpu_preferences.enabled_dawn_features_list.push_back("use_dxc");
+    } else {
+      gpu_preferences.disabled_dawn_features_list.push_back("use_dxc");
+    }
+  }
+#endif
   gpu_preferences.gr_context_type = ParseGrContextType(command_line);
   gpu_preferences.use_vulkan = ParseVulkanImplementationName(command_line);
 
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index f0138ac..3e1396c 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -287,6 +287,8 @@
 BASE_FEATURE(kWebGPUBlobCache, "WebGPUBlobCache", WEBGPU_ENABLED);
 #undef WEBGPU_ENABLED
 
+BASE_FEATURE(kWebGPUUseDXC, "WebGPUUseDXC", base::FEATURE_DISABLED_BY_DEFAULT);
+
 #if BUILDFLAG(IS_ANDROID)
 
 const base::FeatureParam<std::string> kVulkanBlockListByHardware{
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index c77113d..130555d 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -102,6 +102,7 @@
 
 GPU_EXPORT BASE_DECLARE_FEATURE(kWebGPUService);
 GPU_EXPORT BASE_DECLARE_FEATURE(kWebGPUBlobCache);
+GPU_EXPORT BASE_DECLARE_FEATURE(kWebGPUUseDXC);
 
 GPU_EXPORT BASE_DECLARE_FEATURE(kIncreasedCmdBufferParseSlice);
 
diff --git a/ios/chrome/app/app_startup_parameters.h b/ios/chrome/app/app_startup_parameters.h
index f82e32b..ff4d6338 100644
--- a/ios/chrome/app/app_startup_parameters.h
+++ b/ios/chrome/app/app_startup_parameters.h
@@ -32,6 +32,8 @@
   SEARCH_PASSWORDS,
   OPEN_READING_LIST,
   OPEN_BOOKMARKS,
+  OPEN_RECENT_TABS,
+  OPEN_TAB_GRID,
   TAB_OPENING_POST_OPENING_ACTION_COUNT,
 };
 
diff --git a/ios/chrome/app/app_startup_parameters.mm b/ios/chrome/app/app_startup_parameters.mm
index fbcabde..95838367 100644
--- a/ios/chrome/app/app_startup_parameters.mm
+++ b/ios/chrome/app/app_startup_parameters.mm
@@ -91,6 +91,12 @@
     case OPEN_BOOKMARKS:
       [description appendString:@", should open bookmarks"];
       break;
+    case OPEN_RECENT_TABS:
+      [description appendString:@", should open recent tabs"];
+      break;
+    case OPEN_TAB_GRID:
+      [description appendString:@", should open tab grid"];
+      break;
     default:
       break;
   }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index eb54629..1d812cab 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -63,6 +63,8 @@
 NSString* const kSiriShortcutOpenInIncognito = @"OpenInChromeIncognitoIntent";
 NSString* const kSiriOpenReadingList = @"OpenReadingListIntent";
 NSString* const kSiriOpenBookmarks = @"OpenBookmarksIntent";
+NSString* const kSiriOpenRecentTabs = @"OpenRecentTabsIntent";
+NSString* const kSiriOpenTabGrid = @"OpenTabGridIntent";
 
 // Constants for compatible mode for user activities.
 NSString* const kRegularMode = @"RegularMode";
@@ -302,21 +304,21 @@
                                 initStage:initStage];
 
   } else if ([userActivity.activityType isEqualToString:kSiriOpenReadingList]) {
-    AppStartupParameters* startupParams = [[AppStartupParameters alloc]
-        initWithExternalURL:GURL(kChromeUINewTabURL)
-                completeURL:GURL(kChromeUINewTabURL)
-            applicationMode:ApplicationModeForTabOpening::NORMAL];
-
-    startupParams.postOpeningAction = OPEN_READING_LIST;
-    [connectionInformation setStartupParameters:startupParams];
+    [connectionInformation
+        setStartupParameters:[self startupParametersForOpeningNewTabWithAction:
+                                       OPEN_READING_LIST]];
   } else if ([userActivity.activityType isEqualToString:kSiriOpenBookmarks]) {
-    AppStartupParameters* startupParams = [[AppStartupParameters alloc]
-        initWithExternalURL:GURL(kChromeUINewTabURL)
-                completeURL:GURL(kChromeUINewTabURL)
-            applicationMode:ApplicationModeForTabOpening::NORMAL];
-
-    startupParams.postOpeningAction = OPEN_BOOKMARKS;
-    [connectionInformation setStartupParameters:startupParams];
+    [connectionInformation
+        setStartupParameters:
+            [self startupParametersForOpeningNewTabWithAction:OPEN_BOOKMARKS]];
+  } else if ([userActivity.activityType isEqualToString:kSiriOpenRecentTabs]) {
+    [connectionInformation
+        setStartupParameters:[self startupParametersForOpeningNewTabWithAction:
+                                       OPEN_RECENT_TABS]];
+  } else if ([userActivity.activityType isEqualToString:kSiriOpenTabGrid]) {
+    [connectionInformation
+        setStartupParameters:
+            [self startupParametersForOpeningNewTabWithAction:OPEN_TAB_GRID]];
   } else {
     // Do nothing for unknown activity type.
     return NO;
@@ -633,6 +635,18 @@
 
 #pragma mark - Internal methods.
 
+// Returns an app startup parameter for opening a new tab with a post action.
++ (AppStartupParameters*)startupParametersForOpeningNewTabWithAction:
+    (TabOpeningPostOpeningAction)action {
+  AppStartupParameters* startupParams = [[AppStartupParameters alloc]
+      initWithExternalURL:GURL(kChromeUINewTabURL)
+              completeURL:GURL(kChromeUINewTabURL)
+          applicationMode:ApplicationModeForTabOpening::NORMAL];
+
+  startupParams.postOpeningAction = action;
+  return startupParams;
+}
+
 + (BOOL)handleShortcutItem:(UIApplicationShortcutItem*)shortcutItem
      connectionInformation:(id<ConnectionInformation>)connectionInformation
                  initStage:(InitStage)initStage {
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index f5e9b74..bc5b28b 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -41,6 +41,8 @@
 #import "ios/chrome/common/intents/OpenInChromeIncognitoIntent.h"
 #import "ios/chrome/common/intents/OpenInChromeIntent.h"
 #import "ios/chrome/common/intents/OpenReadingListIntent.h"
+#import "ios/chrome/common/intents/OpenRecentTabsIntent.h"
+#import "ios/chrome/common/intents/OpenTabGridIntent.h"
 #import "ios/testing/scoped_block_swizzler.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "net/base/mac/url_conversions.h"
@@ -928,3 +930,63 @@
   EXPECT_EQ(OPEN_BOOKMARKS,
             [connectionInformationMock startupParameters].postOpeningAction);
 }
+
+// Test that Chrome respond to open recent tabs intent.
+TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentOpenRecentTabs) {
+  NSUserActivity* userActivity =
+      [[NSUserActivity alloc] initWithActivityType:@"OpenRecentTabsIntent"];
+
+  OpenRecentTabsIntent* intent = [[OpenRecentTabsIntent alloc] init];
+
+  INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent
+                                                            response:nil];
+
+  id mock_user_activity = CreateMockNSUserActivity(userActivity, interaction);
+
+  FakeStartupInformation* fakeStartupInformation =
+      [[FakeStartupInformation alloc] init];
+  FakeConnectionInformation* connectionInformationMock =
+      [[FakeConnectionInformation alloc] init];
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
+
+  [UserActivityHandler continueUserActivity:mock_user_activity
+                        applicationIsActive:YES
+                                  tabOpener:tabOpener
+                      connectionInformation:connectionInformationMock
+                         startupInformation:fakeStartupInformation
+                               browserState:nullptr
+                                  initStage:InitStageFinal];
+
+  EXPECT_EQ(OPEN_RECENT_TABS,
+            [connectionInformationMock startupParameters].postOpeningAction);
+}
+
+// Tests that Chrome respond to open tab grid intent.
+TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentOpenTabGrid) {
+  NSUserActivity* userActivity =
+      [[NSUserActivity alloc] initWithActivityType:@"OpenTabGridIntent"];
+
+  OpenTabGridIntent* intent = [[OpenTabGridIntent alloc] init];
+
+  INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent
+                                                            response:nil];
+
+  id mock_user_activity = CreateMockNSUserActivity(userActivity, interaction);
+
+  FakeStartupInformation* fakeStartupInformation =
+      [[FakeStartupInformation alloc] init];
+  FakeConnectionInformation* connectionInformationMock =
+      [[FakeConnectionInformation alloc] init];
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
+
+  [UserActivityHandler continueUserActivity:mock_user_activity
+                        applicationIsActive:YES
+                                  tabOpener:tabOpener
+                      connectionInformation:connectionInformationMock
+                         startupInformation:fakeStartupInformation
+                               browserState:nullptr
+                                  initStage:InitStageFinal];
+
+  EXPECT_EQ(OPEN_TAB_GRID,
+            [connectionInformationMock startupParameters].postOpeningAction);
+}
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 78e837d..b684940 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -175,6 +175,9 @@
 // Constants for deferring saving field trial values
 NSString* const kSaveFieldTrialValues = @"SaveFieldTrialValues";
 
+// Constants for refreshing the WidgetKit after five minutes
+NSString* const kWidgetKitRefreshFiveMinutes = @"WidgetKitRefreshFiveMinutes";
+
 // Constants for deferred check if it is necessary to send pings to
 // Chrome distribution related services.
 NSString* const kSendInstallPingIfNecessary = @"SendInstallPingIfNecessary";
@@ -1107,6 +1110,11 @@
       kFieldTrialValueKey : credentialProviderExtensionPasswordNotesValue,
       kFieldTrialVersionKey : credentialProviderExtensionPasswordNotesVersion,
     },
+    kWidgetKitRefreshFiveMinutes : @{
+      kFieldTrialValueKey : @([[NSUserDefaults standardUserDefaults]
+          boolForKey:kWidgetKitRefreshFiveMinutes]),
+      kFieldTrialVersionKey : @1,
+    },
   };
   [sharedDefaults setObject:fieldTrialValues
                      forKey:app_group::kChromeExtensionFieldTrialPreference];
diff --git a/ios/chrome/app/resources/chrome_localize_strings_config.plist b/ios/chrome/app/resources/chrome_localize_strings_config.plist
index 451a43a..26d146f 100644
--- a/ios/chrome/app/resources/chrome_localize_strings_config.plist
+++ b/ios/chrome/app/resources/chrome_localize_strings_config.plist
@@ -67,6 +67,54 @@
 			<array>
 				<dict>
 					<key>output</key>
+					<string>hB4zxD</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>0wmLKV</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>j61w32</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION</string>
+				</dict>
+				<dict>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE</string>
+					<key>output</key>
+					<string>t9NbV2</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>vp7qIi</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>h5ylvP</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>Dnbiji</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION</string>
+				</dict>
+				<dict>
+					<key>output</key>
+					<string>Lx9GhK</string>
+					<key>input</key>
+					<string>IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE</string>
+				</dict>
+				<dict>
+					<key>output</key>
 					<string>NjxAwS</string>
 					<key>input</key>
 					<string>IDS_IOS_INTENTS_OPEN_BOOKMARKS_TITLE</string>
@@ -192,12 +240,12 @@
 					<key>output</key>
 					<string>NSBluetoothPeripheralUsageDescription</string>
 				</dict>
-                                <dict>
-                                     	<key>input</key>
-                                        <string>IDS_IOS_CONTACTS_USAGE_DESCRIPTION</string>
-                                        <key>output</key>
-                                        <string>NSContactsUsageDescription</string>
-                                </dict>
+				<dict>
+					<key>input</key>
+					<string>IDS_IOS_CONTACTS_USAGE_DESCRIPTION</string>
+					<key>output</key>
+					<string>NSContactsUsageDescription</string>
+				</dict>
 				<dict>
 					<key>input</key>
 					<string>IDS_IOS_CAMERA_USAGE_DESCRIPTION</string>
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd
index 99e7f3e3..ba86e2e2 100644
--- a/ios/chrome/app/strings/ios_chromium_strings.grd
+++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -201,9 +201,6 @@
         Chromium has features that help you manage your internet data and how quickly you're able to load webpages.
 <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph>
       </message>
-      <message name="IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the Bottom Toolbar Tip is presented to the user, explaining that the bottom toolbar can be used to reach some controls. Read by Text-to-Speech. [iOS only]">
-        Chromium tip. Some buttons are now at the bottom of your screen, like Back, Forward, and Search.
-      </message>
       <message name="IDS_IOS_CLEAR_BROWSING_DATA_FOOTER_SIGN_OUT_EVERY_WEBSITE" desc="Footer message in the settings to clear browsing data that allows user to sign out of Chrome to sign out their Google account from all websites. [iOS only]">
         To sign out of your Google Account on all websites, <ph name="BEGIN_LINK">BEGIN_LINK</ph>sign out of Chromium<ph name="END_LINK">END_LINK</ph>.
       </message>
@@ -400,9 +397,6 @@
       <message name="IDS_IOS_LOGIN_ERROR_AUTHENTICATING_HOSTED" desc="Couldn't sign in because hosted account is used.">
         Your account does not work on Chromium. Please contact your domain administrator or use a regular Google Account to sign in.
       </message>
-      <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_VOICE_OVER" desc="Text to be read by VoiceOver when the LongPress Toolbar Tip is presented to the user. Read by Text-to-Speech.">
-        Chromium tip. For more tab options, touch &amp; hold the Show Tabs button in the toolbar, which is at the bottom or top of your screen.
-      </message>
       <message name="IDS_IOS_MANAGE_SYNC_DATA_FROM_CHROME_SYNC_TITLE" desc="Title for the cell to open 'Data from Chromium sync' web page where the user can control all their data data from sync.">
         Data from Chromium sync
       </message>
@@ -737,6 +731,18 @@
       <message name="IDS_IOS_INTENTS_OPEN_BOOKMARKS_DESCRIPTION" desc="Shortcut description to open bookmarks in chrome [iOS only].">
         Opens the Chromium bookmarks.
       </message>
+      <message name="IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE" desc="Siri Shortcut for open recent tabs title [iOS only]">
+        See Chromium Recent Tabs
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION" desc="Shortcut description to open recent tabs in chrome [iOS only].">
+        Opens the Chromium Recent Tabs.
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE" desc="Siri Shortcut for open tab grid title [iOS only]">
+        Visit the Tab Grid in Chromium
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION" desc="Shortcut description to open tab grid in chrome [iOS only].">
+        Opens the Chromium Tab Grid.
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..c0f1fa2
--- /dev/null
+++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+1146afae7cc7541d34e15be561d3432e27abf42b
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1
new file mode 100644
index 0000000..c0f1fa2
--- /dev/null
+++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1
@@ -0,0 +1 @@
+1146afae7cc7541d34e15be561d3432e27abf42b
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..2321bec
--- /dev/null
+++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+96196802e5226e3d31f8fda5e99a5f3e319f86b7
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1
new file mode 100644
index 0000000..2321bec
--- /dev/null
+++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1
@@ -0,0 +1 @@
+96196802e5226e3d31f8fda5e99a5f3e319f86b7
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd
index ecd4e49..c3b9a10 100644
--- a/ios/chrome/app/strings/ios_google_chrome_strings.grd
+++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -737,6 +737,18 @@
       <message name="IDS_IOS_INTENTS_OPEN_BOOKMARKS_DESCRIPTION" desc="Shortcut description to open bookmarks in chrome [iOS only].">
         Opens the Chrome bookmarks.
       </message>
+      <message name="IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE" desc="Siri Shortcut for open recent tabs title [iOS only]">
+        See Chrome Recent Tabs
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION" desc="Shortcut description to open recent tabs in chrome [iOS only].">
+        Opens the Chrome Recent Tabs.
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE" desc="Siri Shortcut for open tab grid title [iOS only]">
+        Visit the Tab Grid in Chrome
+      </message>
+      <message name="IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION" desc="Shortcut description to open tab grid in chrome [iOS only].">
+        Opens the Chrome Tab Grid.
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..c0f1fa2
--- /dev/null
+++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+1146afae7cc7541d34e15be561d3432e27abf42b
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1
new file mode 100644
index 0000000..c0f1fa2
--- /dev/null
+++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_RECENT_TABS_TITLE.png.sha1
@@ -0,0 +1 @@
+1146afae7cc7541d34e15be561d3432e27abf42b
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..2321bec
--- /dev/null
+++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+96196802e5226e3d31f8fda5e99a5f3e319f86b7
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1
new file mode 100644
index 0000000..2321bec
--- /dev/null
+++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_INTENTS_OPEN_TAB_GRID_TITLE.png.sha1
@@ -0,0 +1 @@
+96196802e5226e3d31f8fda5e99a5f3e319f86b7
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 6988b68..3b9d0b3 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -586,9 +586,6 @@
       <message name="IDS_IOS_BOOKMARK_URL_FIELD_VALIDATION_FAILED" desc="Error message shown below URL input field when the URL is incorrect. [Length: 20em]">
         Invalid URL
       </message>
-      <message name="IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_TEXT" desc="Text for the Bottom Toolbar Tip in-product help promotion, explaining that the bottom toolbar can be used to focus the Search Bar, instead of having to reach to the top toolbar. [iOS only]">
-        Search bar is now easier to reach
-      </message>
       <message name="IDS_IOS_BRING_ANDROID_TABS_CANCEL_BUTTON" desc="Button to dismiss the 'Bring Android Tabs' prompt. [iOS only]">
         Cancel
       </message>
@@ -1633,9 +1630,6 @@
       <message name="IDS_IOS_KEYBOARD_VOICE_SEARCH" desc="Title for the Voice Search keyboard shortcut in the discoverability." meaning="Used as a command title in the iPad command menu.">
         Voice Search
       </message>
-      <message name="IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT" desc="Text for the LongPress Toolbar Tip in-product help promotion, explaining that the user can long press on the toolbar's button to display more options. [iOS only]">
-        Touch &amp; hold for more tab options
-      </message>
       <message name="IDS_IOS_MAGIC_STACK_SEE_MORE" desc="The See More button in Magic Stack modules to show a detailed view. [Length: 10em]">
         See More
       </message>
@@ -1804,9 +1798,6 @@
       <message name="IDS_IOS_NEW_INCOGNITO_TAB" desc="Label for text saying the tab is a new Incognito tab.">
         New Incognito Tab
       </message>
-      <message name="IDS_IOS_NEW_INCOGNITO_TAB_IPH_PROMOTION_TEXT" desc="Text for the New Incognito Tab Tip in-product help promotion, explaining that Incognito tabs can be used to browse privately. [iOS only]" meaning="The user has never created an Incognito tab before. A bubble is displayed pointing to the tools menu button and informing users about how to use Incognito mode.">
-        To browse privately, open an Incognito tab
-      </message>
       <message name="IDS_IOS_NEW_INCOGNITO_TAB_PAGE" desc="Label for text saying the user is on the new Incognito tab page">
         New Incognito Tab Page
       </message>
diff --git a/ios/chrome/browser/consent_auditor/DIR_METADATA b/ios/chrome/browser/consent_auditor/DIR_METADATA
index df3ee936..9a5074d 100644
--- a/ios/chrome/browser/consent_auditor/DIR_METADATA
+++ b/ios/chrome/browser/consent_auditor/DIR_METADATA
@@ -6,4 +6,4 @@
 # For the schema of this file, see Metadata message:
 #   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
-mixins: "//components/consent_auditor/COMMON_METADATA"
+mixins: "//components/sync/COMMON_METADATA"
diff --git a/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm b/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm
index 0e663bd..d5f7b5c6 100644
--- a/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm
+++ b/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm
@@ -61,18 +61,6 @@
       grey_ancestor(TranslateManualTriggerButton()), nil);
 }
 
-// Matcher for the Bottom Toolbar Tip Bubble.
-id<GREYMatcher> BottomToolbarTipBubble() {
-  return grey_accessibilityLabel(l10n_util::GetNSStringWithFixup(
-      IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_TEXT));
-}
-
-// Matcher for the Long Press Tip Bubble.
-id<GREYMatcher> LongPressTipBubble() {
-  return grey_accessibilityLabel(l10n_util::GetNSStringWithFixup(
-      IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT));
-}
-
 // Matcher for the DefaultSiteView tip.
 id<GREYMatcher> DefaultSiteViewTip() {
   return grey_accessibilityLabel(
@@ -154,87 +142,6 @@
       assertWithMatcher:grey_notNil()];
 }
 
-// Verifies that the bottom toolbar tip is displayed when the phone is in split
-// toolbar mode.
-- (void)testBottomToolbarAppear {
-  if (![ChromeEarlGrey isSplitToolbarMode])
-    return;
-
-  // The IPH appears immediately on startup, so don't open a new tab when the
-  // app starts up.
-  [[self class] testForStartup];
-
-  // Scope for the synchronization disabled.
-  {
-    ScopedSynchronizationDisabler syncDisabler;
-
-    [self enableDemoModeForFeature:"IPH_BottomToolbarTip"];
-
-    // Verify that the Bottom toolbar Tip appeared.
-    ConditionBlock condition = ^{
-      NSError* error = nil;
-      [[EarlGrey selectElementWithMatcher:BottomToolbarTipBubble()]
-          assertWithMatcher:grey_sufficientlyVisible()
-                      error:&error];
-      return error == nil;
-    };
-    // The app relaunch (to enable a feature flag) may take a while, therefore
-    // the timeout is extended to 15 seconds.
-    GREYAssert(WaitUntilConditionOrTimeout(base::Seconds(15), condition),
-               @"Waiting for the Bottom Toolbar tip to appear");
-  }  // End of the sync disabler scope.
-}
-
-// Verifies that the bottom toolbar tip is not displayed when the phone is not
-// in split toolbar mode.
-- (void)testBottomToolbarDontAppearOnNonSplitToolbar {
-  if ([ChromeEarlGrey isSplitToolbarMode])
-    return;
-
-  // The IPH appears immediately on startup, so don't open a new tab when the
-  // app starts up.
-  [[self class] testForStartup];
-
-  [self enableDemoModeForFeature:"IPH_BottomToolbarTip"];
-
-  // Verify that the Bottom toolbar Tip didn't appear.
-  ConditionBlock condition = ^{
-    NSError* error = nil;
-    [[EarlGrey selectElementWithMatcher:BottomToolbarTipBubble()]
-        assertWithMatcher:grey_sufficientlyVisible()
-                    error:&error];
-    return error == nil;
-  };
-  GREYAssert(!WaitUntilConditionOrTimeout(base::Seconds(2), condition),
-             @"The Bottom Toolbar tip shouldn't appear");
-}
-
-// Verifies that the LongPress tip is displayed only after the Bottom Toolbar
-// tip is presented.
-// TODO(crbug.com/934248) The test is flaky.
-- (void)DISABLED_testLongPressTipAppearAfterBottomToolbar {
-  if (![ChromeEarlGrey isSplitToolbarMode])
-    return;
-
-  // The IPH appears immediately on startup, so don't open a new tab when the
-  // app starts up.
-  [[self class] testForStartup];
-
-  [self enableDemoModeForFeature:"IPH_LongPressToolbarTip"];
-
-  // Verify that the Long Press Tip appears now that the Bottom Toolbar tip has
-  // been shown.
-  ConditionBlock condition = ^{
-    NSError* error = nil;
-    [[EarlGrey selectElementWithMatcher:LongPressTipBubble()]
-        assertWithMatcher:grey_sufficientlyVisible()
-                    error:&error];
-    return error == nil;
-  };
-  GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition),
-             @"Waiting for the Long Press tip.");
-}
-
 // Verifies that the IPH for Request desktop shows when triggered
 - (void)testRequestDesktopTip {
   [self enableDemoModeForFeature:"IPH_DefaultSiteView"];
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index 16cc530..0cc6600f 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -250,6 +250,16 @@
                 </dict>
 		<dict>
 			<key>Type</key>
+			<string>PSToggleSwitchSpecifier</string>
+			<key>Title</key>
+			<string>WidgetKit refresh 5 minutes</string>
+			<key>Key</key>
+			<string>WidgetKitRefreshFiveMinutes</string>
+			<key>DefaultValue</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 			<key>Title</key>
 			<string>Debug Settings</string>
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index 339de04d..3dfe3bff 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -1558,7 +1558,6 @@
 - (void)displayTabSwitcherForcingRegularTabs:(BOOL)forcing {
   DCHECK(!self.mainCoordinator.isTabGridActive);
   if (!self.isProcessingVoiceSearchCommand) {
-    [self.currentInterface.bvc userEnteredTabSwitcher];
 
     if (forcing && self.currentInterface.incognito) {
       [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
@@ -2494,6 +2493,14 @@
       return ^{
         [weakSelf openBookmarks];
       };
+    case OPEN_RECENT_TABS:
+      return ^{
+        [weakSelf openRecentTabs];
+      };
+    case OPEN_TAB_GRID:
+      return ^{
+        [weakSelf.mainCoordinator showTabGrid];
+      };
     default:
       return nil;
   }
@@ -2588,6 +2595,16 @@
   [browserCoordinatorCommandsHandler showBookmarksManager];
 }
 
+- (void)openRecentTabs {
+  if (!self.currentInterface.browser) {
+    return;
+  }
+  id<BrowserCoordinatorCommands> browserCoordinatorCommandsHandler =
+      HandlerForProtocol(self.currentInterface.browser->GetCommandDispatcher(),
+                         BrowserCoordinatorCommands);
+  [browserCoordinatorCommandsHandler showRecentTabs];
+}
+
 #pragma mark - TabOpening implementation.
 
 - (void)dismissModalsAndMaybeOpenSelectedTabInMode:
diff --git a/ios/chrome/browser/shared/public/commands/help_commands.h b/ios/chrome/browser/shared/public/commands/help_commands.h
index c01b13f..0282de06 100644
--- a/ios/chrome/browser/shared/public/commands/help_commands.h
+++ b/ios/chrome/browser/shared/public/commands/help_commands.h
@@ -8,12 +8,6 @@
 // Commands to control the display of in-product help UI ("bubbles").
 @protocol HelpCommands <NSObject>
 
-// Shows a relevant help bubble, if any.
-- (void)showHelpBubbleIfEligible;
-
-// Shows a relevant help bubble for long-press state, if any.
-- (void)showLongPressHelpBubbleIfEligible;
-
 // Dismisses all bubbles.
 - (void)hideAllHelpBubbles;
 
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index 346aa258..8a6c102 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -254,7 +254,7 @@
 
 BASE_FEATURE(kHideSettingsSyncPromo,
              "HideSettingsSyncPromo",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kDefaultBrowserTriggerCriteriaExperiment,
              "DefaultBrowserTriggerCriteriaExperiment",
diff --git a/ios/chrome/browser/shared/ui/elements/top_aligned_image_view.mm b/ios/chrome/browser/shared/ui/elements/top_aligned_image_view.mm
index 87d0d8f..7994e3d 100644
--- a/ios/chrome/browser/shared/ui/elements/top_aligned_image_view.mm
+++ b/ios/chrome/browser/shared/ui/elements/top_aligned_image_view.mm
@@ -26,20 +26,20 @@
 
 - (void)layoutSubviews {
   [super layoutSubviews];
-  if (!self.image) {
+  const CGSize imageSize = self.image.size;
+  if (imageSize.width == 0 || imageSize.height == 0) {
     return;
   }
-  CGFloat widthScaleFactor = CGRectGetWidth(self.frame) / self.image.size.width;
-  CGFloat heightScaleFactor =
-      CGRectGetHeight(self.frame) / self.image.size.height;
+  CGFloat widthScaleFactor = CGRectGetWidth(self.frame) / imageSize.width;
+  CGFloat heightScaleFactor = CGRectGetHeight(self.frame) / imageSize.height;
   CGFloat imageViewWidth;
   CGFloat imageViewHeight;
-  if (self.image.size.width > self.image.size.height) {
-    imageViewWidth = self.image.size.width * heightScaleFactor;
+  if (imageSize.width > imageSize.height) {
+    imageViewWidth = imageSize.width * heightScaleFactor;
     imageViewHeight = CGRectGetHeight(self.frame);
   } else {
     imageViewWidth = CGRectGetWidth(self.frame);
-    imageViewHeight = self.image.size.height * widthScaleFactor;
+    imageViewHeight = imageSize.height * widthScaleFactor;
   }
   self.innerImageView.frame =
       CGRectMake((self.frame.size.width - imageViewWidth) / 2.0f, 0,
diff --git a/ios/chrome/browser/sync/sync_setup_service.cc b/ios/chrome/browser/sync/sync_setup_service.cc
index 1089089..0b1a6880 100644
--- a/ios/chrome/browser/sync/sync_setup_service.cc
+++ b/ios/chrome/browser/sync/sync_setup_service.cc
@@ -52,6 +52,8 @@
   CHECK(sync_blocker_);
   // Turn on the sync setup completed flag only if the user did not turn sync
   // off.
+  // TODO(crbug.com/1462858): Remove this code once
+  // kReplaceSyncPromosWithSignInPromos launches.
   if (sync_service_->CanSyncFeatureStart()) {
     sync_service_->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
         source);
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.mm
index 629cdd1..352550d 100644
--- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.mm
+++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.mm
@@ -80,17 +80,27 @@
         fakeIdentity.gaiaID, [SigninEarlGreyAppInterface primaryAccountGaiaID]);
     return;
   }
-  [SigninEarlGreyUI tapPrimarySignInButtonInRecentTabs];
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                          kIdentityButtonControlIdentifier)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail(
-                                          fakeIdentity.userEmail)]
-      performAction:grey_tap()];
-  if ([ChromeEarlGrey isReplaceSyncWithSigninEnabled]) {
-    [self tapSigninBottomSheetAndHistoryConfirmationDialog];
+
+  if ([SigninEarlGreyAppInterface isSignedOut] ||
+      ![ChromeEarlGrey isReplaceSyncWithSigninEnabled]) {
+    [SigninEarlGreyUI tapPrimarySignInButtonInRecentTabs];
+    [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                            kIdentityButtonControlIdentifier)]
+        performAction:grey_tap()];
+    [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail(
+                                            fakeIdentity.userEmail)]
+        performAction:grey_tap()];
   } else {
-    [self tapSigninConfirmationDialog];
+    [SigninEarlGreyUI
+        openRecentTabsAndTapButton:
+            grey_accessibilityID(
+                kRecentTabsTabSyncOffButtonAccessibilityIdentifier)];
+  }
+
+  if ([ChromeEarlGrey isReplaceSyncWithSigninEnabled]) {
+    [SigninEarlGreyUI maybeTapSigninBottomSheetAndHistoryConfirmationDialog];
+  } else {
+    [SigninEarlGreyUI tapSigninConfirmationDialog];
     CloseSigninManagedAccountDialogIfAny(fakeIdentity);
   }
 
@@ -202,12 +212,16 @@
   [[EarlGrey selectElementWithMatcher:buttonMatcher] performAction:grey_tap()];
 }
 
-+ (void)tapSigninBottomSheetAndHistoryConfirmationDialog {
-  // First tap the "Continue as ..." button in the signin bottom sheet.
-  [ChromeEarlGreyUI waitForAppToIdle];
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::
-                                          WebSigninPrimaryButtonMatcher()]
-      performAction:grey_tap()];
+// Taps the sign-in sheet confirmation if the user is not signed-in yet, and
+// the history opt-in confirmation if the user is not opted-in yet.
++ (void)maybeTapSigninBottomSheetAndHistoryConfirmationDialog {
+  if ([SigninEarlGreyAppInterface isSignedOut]) {
+    // First tap the "Continue as ..." button in the signin bottom sheet.
+    [ChromeEarlGreyUI waitForAppToIdle];
+    [[EarlGrey selectElementWithMatcher:chrome_test_util::
+                                            WebSigninPrimaryButtonMatcher()]
+        performAction:grey_tap()];
+  }
 
   [ChromeEarlGreyUI waitForAppToIdle];
   // If the history type isn't enabled yet, the history opt-in dialog should
@@ -330,18 +344,7 @@
 }
 
 + (void)tapPrimarySignInButtonInRecentTabs {
-  [ChromeEarlGreyUI openToolsMenu];
-  [ChromeEarlGreyUI
-      tapToolsMenuButton:chrome_test_util::RecentTabsDestinationButton()];
-  [[[EarlGrey
-      selectElementWithMatcher:grey_allOf(PrimarySignInButton(),
-                                          grey_sufficientlyVisible(), nil)]
-         usingSearchAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)
-      onElementWithMatcher:
-          grey_allOf(grey_accessibilityID(
-                         kRecentTabsTableViewControllerAccessibilityIdentifier),
-                     grey_sufficientlyVisible(), nil)]
-      performAction:grey_tap()];
+  [SigninEarlGreyUI openRecentTabsAndTapButton:PrimarySignInButton()];
 }
 
 + (void)tapPrimarySignInButtonInTabSwitcher {
@@ -394,4 +397,21 @@
   // so there's no reason to tap the 'enter' button.
 }
 
+#pragma mark - Private
+
++ (void)openRecentTabsAndTapButton:(id<GREYMatcher>)buttonMatcher {
+  [ChromeEarlGreyUI openToolsMenu];
+  [ChromeEarlGreyUI
+      tapToolsMenuButton:chrome_test_util::RecentTabsDestinationButton()];
+  [[[EarlGrey
+      selectElementWithMatcher:grey_allOf(buttonMatcher,
+                                          grey_sufficientlyVisible(), nil)]
+         usingSearchAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)
+      onElementWithMatcher:
+          grey_allOf(grey_accessibilityID(
+                         kRecentTabsTableViewControllerAccessibilityIdentifier),
+                     grey_sufficientlyVisible(), nil)]
+      performAction:grey_tap()];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator_unittest.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator_unittest.mm
index 30934689..6537d65 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator_unittest.mm
@@ -8,6 +8,7 @@
 #import "base/run_loop.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
+#import "base/test/scoped_feature_list.h"
 #import "build/branding_buildflags.h"
 #import "components/pref_registry/pref_registry_syncable.h"
 #import "components/prefs/pref_service.h"
@@ -21,6 +22,7 @@
 #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/shared/model/prefs/browser_prefs.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/chrome_account_manager_service_factory.h"
@@ -44,6 +46,7 @@
 #import "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/gtest_support.h"
+#import "third_party/ocmock/ocmock_extensions.h"
 #import "ui/base/l10n/l10n_util.h"
 
 using base::SysNSStringToUTF16;
@@ -466,6 +469,9 @@
 
 // Tests the view state while signing in.
 TEST_F(SigninPromoViewMediatorTest, SigninPromoViewStateSignedin) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kHideSettingsSyncPromo);
+
   CreateMediator(signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS);
   [mediator_ signinPromoViewIsVisible];
   __block ShowSigninCommandCompletionCallback completion;
@@ -503,6 +509,9 @@
 // while the sign-in is in progress, when an identity is added.
 TEST_F(SigninPromoViewMediatorTest,
        SigninPromoViewNoUpdateNotificationWhileSignin) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kHideSettingsSyncPromo);
+
   CreateMediator(signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS);
   [mediator_ signinPromoViewIsVisible];
   __block ShowSigninCommandCompletionCallback completion;
@@ -537,6 +546,9 @@
 // while the sign-in is in progress.
 TEST_F(SigninPromoViewMediatorTest,
        SigninPromoViewNoUpdateNotificationWhileSignin2) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kHideSettingsSyncPromo);
+
   AddDefaultIdentity();
   CreateMediator(signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS);
   [mediator_ signinPromoViewIsVisible];
@@ -608,34 +620,46 @@
 // called at the end of the sign-in.
 TEST_F(SigninPromoViewMediatorTest,
        RemoveSigninPromoAndDeallocMediatorWhileSignedIn) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kHideSettingsSyncPromo);
+
   // Setup.
   AddDefaultIdentity();
   CreateMediator(signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS);
-  [mediator_ signinPromoViewIsVisible];
-  __block ShowSigninCommandCompletionCallback completion;
-  id completion_arg =
-      [OCMArg checkWithBlock:^BOOL(ShowSigninCommandCompletionCallback value) {
-        completion = value;
-        return YES;
-      }];
   __weak __typeof(mediator_) weak_mediator = mediator_;
-  id mediator_checker = [OCMArg checkWithBlock:^BOOL(id value) {
-    return value == weak_mediator;
-  }];
-  OCMExpect([consumer_ signinPromoViewMediator:mediator_checker
-                  shouldOpenSigninWithIdentity:identity_
-                                   promoAction:signin_metrics::PromoAction::
-                                                   PROMO_ACTION_WITH_DEFAULT
-                                    completion:completion_arg]);
-  OCMExpect([consumer_ promoProgressStateDidChange]);
-  ExpectConfiguratorNotification(NO /* identity changed */);
-  // Start sign-in with an identity.
-  [mediator_ signinPromoViewDidTapSigninWithDefaultAccount:signin_promo_view_];
-  // Remove the sign-in promo.
-  [mediator_ disconnect];
-  EXPECT_EQ(SigninPromoViewState::kInvalid, mediator_.signinPromoViewState);
-  // Dealloc the mediator.
-  mediator_ = nil;
+  __block ShowSigninCommandCompletionCallback completion;
+  // This test wants to verify behavior when `mediator_` gets deallocated.
+  // OCMock uses autorelease in places, which could result in `mediator_`
+  // staying allocated longer than we want without this @autoreleasepool.
+  @autoreleasepool {
+    [mediator_ signinPromoViewIsVisible];
+    id completion_arg = [OCMArg
+        checkWithBlock:^BOOL(ShowSigninCommandCompletionCallback value) {
+          completion = value;
+          return YES;
+        }];
+    OCMExpect([consumer_ signinPromoViewMediator:mediator_
+                    shouldOpenSigninWithIdentity:identity_
+                                     promoAction:signin_metrics::PromoAction::
+                                                     PROMO_ACTION_WITH_DEFAULT
+                                      completion:completion_arg]);
+    OCMExpect([consumer_ promoProgressStateDidChange]);
+    ExpectConfiguratorNotification(NO /* identity changed */);
+    // Start sign-in with an identity.
+    [mediator_
+        signinPromoViewDidTapSigninWithDefaultAccount:signin_promo_view_];
+    // Remove the sign-in promo.
+    [mediator_ disconnect];
+    EXPECT_EQ(SigninPromoViewState::kInvalid, mediator_.signinPromoViewState);
+    // Dealloc the mediator.
+    mediator_ = nil;
+    // Also clear all invocations from `consumer_` after verifying them, as the
+    // invocations also contain a reference to `mediator_`. Generally this is
+    // what `stopMocking` is meant for, but we still want to verify that
+    // `signinDidfinish` is called below, so we can't just stop mocking yet.
+    EXPECT_OCMOCK_VERIFY(consumer_);
+    [(OCMockObject*)consumer_ clearInvocations];
+  }
   EXPECT_EQ(weak_mediator, nil);
   // Finish the sign-in.
   OCMExpect([consumer_ signinDidFinish]);
@@ -645,6 +669,9 @@
 // Tests that the sign-in promo view being removed, and tests the consumer is
 // still called at the end of the sign-in.
 TEST_F(SigninPromoViewMediatorTest, RemoveSigninPromoWhileSignedIn) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kHideSettingsSyncPromo);
+
   // Setup.
   AddDefaultIdentity();
   CreateMediator(signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS);
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_account_storage_promo_egtest.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_account_storage_promo_egtest.mm
index 9953a64..01e6d48b 100644
--- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_account_storage_promo_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_account_storage_promo_egtest.mm
@@ -42,6 +42,14 @@
 - (AppLaunchConfiguration)appConfigurationForTestCase {
   AppLaunchConfiguration config;
   config.features_enabled.push_back(syncer::kEnableBookmarksAccountStorage);
+  if ([self isRunningTest:@selector
+            (testPromoViewNotShownWhenSyncDataNotRemoved)]) {
+    config.features_disabled.push_back(
+        syncer::kReplaceSyncPromosWithSignInPromos);
+  } else {
+    config.features_enabled.push_back(
+        syncer::kReplaceSyncPromosWithSignInPromos);
+  }
   return config;
 }
 
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_promo_egtest.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_promo_egtest.mm
index 8911c701..e606d6b 100644
--- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_promo_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_promo_egtest.mm
@@ -85,6 +85,10 @@
                    (testNoSyncPromoIfSyncToSigninEnabled)]) {
     config.features_enabled.push_back(
         syncer::kReplaceSyncPromosWithSignInPromos);
+  } else if ([self isRunningTest:@selector
+                   (testSigninWithSyncPassphraseAndTurnOnSync)]) {
+    config.features_disabled.push_back(
+        syncer::kReplaceSyncPromosWithSignInPromos);
   }
 
   return config;
diff --git a/ios/chrome/browser/ui/broadcaster/BUILD.gn b/ios/chrome/browser/ui/broadcaster/BUILD.gn
index a3619864..feebe2f 100644
--- a/ios/chrome/browser/ui/broadcaster/BUILD.gn
+++ b/ios/chrome/browser/ui/broadcaster/BUILD.gn
@@ -13,6 +13,7 @@
   deps = [
     "//base",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
+    "//ios/web/common:features",
   ]
 }
 
@@ -25,6 +26,8 @@
   deps = [
     ":broadcaster",
     "//base",
+    "//base/test:test_support",
+    "//ios/web/common:features",
     "//testing/gtest",
     "//testing/perf",
   ]
diff --git a/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.mm b/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.mm
index ff100571..c344443 100644
--- a/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.mm
+++ b/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.h"
 
 #import "base/check.h"
+#import "ios/web/common/features.h"
 
 ChromeBroadcastObserverInterface::~ChromeBroadcastObserverInterface() = default;
 
@@ -36,6 +37,7 @@
 }
 
 - (void)broadcastScrollViewIsScrolling:(BOOL)scrolling {
+  CHECK(base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault));
   self.observer->OnScrollViewIsScrollingBroadcasted(scrolling);
 }
 
diff --git a/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge_unittest.mm b/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge_unittest.mm
index 76cad4e8..ff8d000 100644
--- a/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge_unittest.mm
+++ b/ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge_unittest.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.h"
 
+#import "base/test/scoped_feature_list.h"
+#import "ios/web/common/features.h"
 #import "testing/platform_test.h"
 
 // Test implementation of ChromeBroadcastObserverInterface.
@@ -87,6 +89,9 @@
 // Tests that `-broadcastScrollViewIsScrolling:` is correctly forwarded to the
 // observer.
 TEST_F(ChromeBroadcastObserverBridgeTest, ScrollViewIsScrolling) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      web::features::kSmoothScrollingDefault);
   ASSERT_FALSE(observer().scroll_view_scrolling());
   [bridge() broadcastScrollViewIsScrolling:YES];
   EXPECT_TRUE(observer().scroll_view_scrolling());
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.h b/ios/chrome/browser/ui/browser_view/browser_view_controller.h
index f502d31..cfe61132 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.h
@@ -140,9 +140,6 @@
 // Whether the receiver is currently the primary BVC.
 - (void)setPrimary:(BOOL)primary;
 
-// Called when the user explicitly opens the tab switcher.
-- (void)userEnteredTabSwitcher;
-
 // Opens a new tab as if originating from `originPoint` and `focusOmnibox`.
 - (void)openNewTabFromOriginPoint:(CGPoint)originPoint
                      focusOmnibox:(BOOL)focusOmnibox
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 2c4137d6..e3ecc39d 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -620,10 +620,6 @@
   [self.omniboxCommandsHandler cancelOmniboxEdit];
 }
 
-- (void)userEnteredTabSwitcher {
-  [_bubblePresenter userEnteredTabSwitcher];
-}
-
 - (void)openNewTabFromOriginPoint:(CGPoint)originPoint
                      focusOmnibox:(BOOL)focusOmnibox
                     inheritOpener:(BOOL)inheritOpener {
@@ -953,8 +949,6 @@
   self.viewVisible = YES;
   [self updateBroadcastState];
   [self updateToolbarState];
-  [self.helpHandler showHelpBubbleIfEligible];
-  [self.helpHandler showLongPressHelpBubbleIfEligible];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.h b/ios/chrome/browser/ui/bubble/bubble_presenter.h
index e2060d7..142be1b 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter.h
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter.h
@@ -63,12 +63,6 @@
 // Stops this presenter.
 - (void)stop;
 
-// Notifies the presenter that the user entered the tab switcher.
-- (void)userEnteredTabSwitcher;
-
-// Notifies the presenter that the tools menu has been displayed.
-- (void)toolsMenuDisplayed;
-
 // Presents a bubble associated with the Discover feed header's menu button.
 - (void)presentDiscoverFeedHeaderTipBubble;
 
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
index b6ea38bdc..1a869d5e 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -46,10 +46,6 @@
 #import "ui/base/device_form_factor.h"
 #import "ui/base/l10n/l10n_util.h"
 
-namespace {
-const CGFloat kBubblePresentationDelay = 1;
-}  // namespace
-
 @interface BubblePresenter () <SceneStateObserver, URLLoadingObserver>
 
 // Used to display the bottom toolbar tip in-product help promotion bubble.
@@ -57,12 +53,6 @@
 // dismissed, it remains allocated so that `userEngaged` remains accessible.
 @property(nonatomic, strong)
     BubbleViewControllerPresenter* bottomToolbarTipBubblePresenter;
-// Used to display the long press on toolbar buttons tip in-product help
-// promotion bubble. `nil` if the tip bubble has not yet been presented. Once
-// the bubble is dismissed, it remains allocated so that `userEngaged` remains
-// accessible.
-@property(nonatomic, strong)
-    BubbleViewControllerPresenter* longPressToolbarTipBubblePresenter;
 // Used to display the new tab tip in-product help promotion bubble. `nil` if
 // the new tab tip bubble has not yet been presented. Once the bubble is
 // dismissed, it remains allocated so that `userEngaged` remains accessible.
@@ -70,8 +60,6 @@
     BubbleViewControllerPresenter* openNewTabIPHBubblePresenter;
 @property(nonatomic, strong)
     BubbleViewControllerPresenter* tabGridIPHBubblePresenter;
-@property(nonatomic, strong, readwrite)
-    BubbleViewControllerPresenter* incognitoTabTipBubblePresenter;
 @property(nonatomic, strong)
     BubbleViewControllerPresenter* discoverFeedHeaderMenuTipBubblePresenter;
 @property(nonatomic, strong)
@@ -148,59 +136,10 @@
   _loadingObserverBridge.reset();
 }
 
-- (void)showHelpBubbleIfEligible {
-  if (!self.engagementTracker) {
-    return;
-  }
-  // Waits to present the bubbles until the feature engagement tracker database
-  // is fully initialized.
-  __weak BubblePresenter* weakSelf = self;
-  void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) {
-    if (!successfullyLoaded)
-      return;
-    dispatch_after(
-        dispatch_time(DISPATCH_TIME_NOW,
-                      (int64_t)(kBubblePresentationDelay * NSEC_PER_SEC)),
-        dispatch_get_main_queue(), ^{
-          [weakSelf presentBubbles];
-        });
-  };
-
-  // Because the new tab tip occurs on startup, the feature engagement
-  // tracker's database is not guaranteed to be loaded by this time. For the
-  // bubble to appear properly, a callback is used to guarantee the event data
-  // is loaded before the check to see if the promotion should be displayed.
-  self.engagementTracker->AddOnInitializedCallback(
-      base::BindRepeating(onInitializedBlock));
-}
-
-- (void)showLongPressHelpBubbleIfEligible {
-  if (!self.engagementTracker) {
-    return;
-  }
-  // Waits to present the bubble until the feature engagement tracker database
-  // is fully initialized.
-  __weak BubblePresenter* weakSelf = self;
-  void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) {
-    if (!successfullyLoaded)
-      return;
-    [weakSelf presentLongPressBubble];
-  };
-
-  // Because the new tab tip occurs on startup, the feature engagement
-  // tracker's database is not guaranteed to be loaded by this time. For the
-  // bubble to appear properly, a callback is used to guarantee the event data
-  // is loaded before the check to see if the promotion should be displayed.
-  self.engagementTracker->AddOnInitializedCallback(
-      base::BindRepeating(onInitializedBlock));
-}
-
 - (void)hideAllHelpBubbles {
   [self.openNewTabIPHBubblePresenter dismissAnimated:NO];
   [self.tabGridIPHBubblePresenter dismissAnimated:NO];
-  [self.incognitoTabTipBubblePresenter dismissAnimated:NO];
   [self.bottomToolbarTipBubblePresenter dismissAnimated:NO];
-  [self.longPressToolbarTipBubblePresenter dismissAnimated:NO];
   [self.discoverFeedHeaderMenuTipBubblePresenter dismissAnimated:NO];
   [self.readingListTipBubblePresenter dismissAnimated:NO];
   [self.followWhileBrowsingBubbleTipPresenter dismissAnimated:NO];
@@ -209,18 +148,6 @@
   [self.defaultPageModeTipBubblePresenter dismissAnimated:NO];
 }
 
-// TODO(crbug.com/1448656): remove code.
-- (void)userEnteredTabSwitcher {
-}
-
-// TODO(crbug.com/1448656): remove code.
-- (void)toolsMenuDisplayed {
-  if (self.incognitoTabTipBubblePresenter.userEngaged) {
-    base::RecordAction(
-        base::UserMetricsAction("NewIncognitoTabTipTargetSelected"));
-  }
-}
-
 - (void)presentDiscoverFeedHeaderTipBubble {
   BubbleArrowDirection arrowDirection = BubbleArrowDirectionDown;
   NSString* text =
@@ -372,50 +299,6 @@
 
 #pragma mark - Private
 
-- (void)presentBubbles {
-  // TODO(crbug.com/1448656): remove code.
-  if (!self.incognitoTabTipBubblePresenter.userEngaged)
-    [self presentNewIncognitoTabTipBubble];
-
-  // TODO(crbug.com/1448656): remove code.
-  // The bottom toolbar and Discover feed header menu don't use the
-  // isUserEngaged, so don't check if the user is engaged here.
-  [self presentBottomToolbarTipBubble];
-}
-
-// TODO(crbug.com/1448656): remove code.
-- (void)presentLongPressBubble {
-  if (self.longPressToolbarTipBubblePresenter.userEngaged)
-    return;
-
-  if (![self canPresentBubble])
-    return;
-
-  BubbleArrowDirection arrowDirection =
-      IsSplitToolbarMode(self.rootViewController) ? BubbleArrowDirectionDown
-                                                  : BubbleArrowDirectionUp;
-  NSString* text =
-      l10n_util::GetNSString(IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_TEXT);
-  CGPoint tabGridButtonAnchor = [self anchorPointToGuide:kTabSwitcherGuide
-                                               direction:arrowDirection];
-
-  // If the feature engagement tracker does not consider it valid to display
-  // the tip, then end early to prevent the potential reassignment of the
-  // existing `longPressToolbarTipBubblePresenter` to nil.
-  BubbleViewControllerPresenter* presenter = [self
-      presentBubbleForFeature:feature_engagement::kIPHLongPressToolbarTipFeature
-                    direction:arrowDirection
-                         text:text
-        voiceOverAnnouncement:
-            l10n_util::GetNSString(
-                IDS_IOS_LONG_PRESS_TOOLBAR_IPH_PROMOTION_VOICE_OVER)
-                  anchorPoint:tabGridButtonAnchor];
-  if (!presenter)
-    return;
-
-  self.longPressToolbarTipBubblePresenter = presenter;
-}
-
 // Convenience method that calls -presentBubbleForFeature with default param
 // values for `alignment`, `presentAction`, and `dismissAction`.
 - (BubbleViewControllerPresenter*)
@@ -469,44 +352,6 @@
   return presenter;
 }
 
-// TODO(crbug.com/1448656): remove code.
-// Presents a bubble associated with the bottom toolbar tip in-product help
-// promotion.
-- (void)presentBottomToolbarTipBubble {
-  if (!IsSplitToolbarMode(self.rootViewController))
-    return;
-
-  if (![self canPresentBubble])
-    return;
-
-  BubbleArrowDirection arrowDirection = BubbleArrowDirectionDown;
-  NSString* text = l10n_util::GetNSStringWithFixup(
-      IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_TEXT);
-  CGPoint newTabButtonAnchor = [self anchorPointToGuide:kNewTabButtonGuide
-                                              direction:arrowDirection];
-
-  // If the feature engagement tracker does not consider it valid to display
-  // the tip, then end early to prevent the potential reassignment of the
-  // existing `bottomToolbarTipBubblePresenter` to nil.
-  BubbleViewControllerPresenter* presenter = [self
-      presentBubbleForFeature:feature_engagement::kIPHBottomToolbarTipFeature
-                    direction:arrowDirection
-                    alignment:BubbleAlignmentCenter
-                         text:text
-        voiceOverAnnouncement:
-            l10n_util::GetNSString(
-                IDS_IOS_BOTTOM_TOOLBAR_IPH_PROMOTION_VOICE_OVER)
-                  anchorPoint:newTabButtonAnchor
-                presentAction:nil
-                dismissAction:nil];
-  if (!presenter)
-    return;
-
-  self.bottomToolbarTipBubblePresenter = presenter;
-  self.engagementTracker->NotifyEvent(
-      feature_engagement::events::kBottomToolbarOpened);
-}
-
 // Optionally presents a bubble associated with the new tab iph. If the feature
 // engagement tracker determines it is valid to show the new tab tip, then it
 // initializes `openNewTabIPHBubblePresenter` and presents the bubble. If it is
@@ -519,8 +364,16 @@
     return;
   }
 
-  if (![self canPresentBubble])
+  UIView* newTabToolbarView =
+      [_layoutGuideCenter referencedViewUnderName:kNewTabButtonGuide];
+  // Do not present if the new tab button is not visible.
+  if (!newTabToolbarView || newTabToolbarView.hidden) {
     return;
+  }
+
+  if (![self canPresentBubbleWithCheckTabScrolledToTop:NO]) {
+    return;
+  }
 
   // Do not present the new tab IPH on NTP.
   web::WebState* currentWebState = self.webStateList->GetActiveWebState();
@@ -582,7 +435,14 @@
     return;
   }
 
-  if (![self canPresentBubble]) {
+  UIView* tabGridToolbarView =
+      [_layoutGuideCenter referencedViewUnderName:kNewTabButtonGuide];
+  // Do not present if the tab grid button is not visible.
+  if (!tabGridToolbarView || tabGridToolbarView.hidden) {
+    return;
+  }
+
+  if (![self canPresentBubbleWithCheckTabScrolledToTop:NO]) {
     return;
   }
 
@@ -628,37 +488,6 @@
   self.tabGridIPHBubblePresenter = presenter;
 }
 
-// TODO(crbug.com/1448656): remove code.
-// Presents a bubble associated with the new incognito tab tip in-product help
-// promotion.
-- (void)presentNewIncognitoTabTipBubble {
-  if (![self canPresentBubble])
-    return;
-
-  BubbleArrowDirection arrowDirection =
-      IsSplitToolbarMode(self.rootViewController) ? BubbleArrowDirectionDown
-                                                  : BubbleArrowDirectionUp;
-  NSString* text = l10n_util::GetNSStringWithFixup(
-      IDS_IOS_NEW_INCOGNITO_TAB_IPH_PROMOTION_TEXT);
-
-  CGPoint toolsButtonAnchor = [self anchorPointToGuide:kToolsMenuGuide
-                                             direction:arrowDirection];
-
-  // If the feature engagement tracker does not consider it valid to display
-  // the incognito tab tip, then end early to prevent the potential reassignment
-  // of the existing `incognitoTabTipBubblePresenter` to nil.
-  BubbleViewControllerPresenter* presenter = [self
-      presentBubbleForFeature:feature_engagement::kIPHNewIncognitoTabTipFeature
-                    direction:arrowDirection
-                         text:text
-        voiceOverAnnouncement:nil
-                  anchorPoint:toolsButtonAnchor];
-  if (!presenter)
-    return;
-
-  self.incognitoTabTipBubblePresenter = presenter;
-}
-
 #pragma mark - Private Utils
 
 // Returns the anchor point for a bubble with an `arrowDirection` pointing to a
@@ -679,7 +508,16 @@
 }
 
 // Returns whether the tab can present a bubble tip.
+// TODO(crbug.com/1448656): make most callsites pass NO for
+// `CheckTabScrolledToTop` as it's error-prone.
 - (BOOL)canPresentBubble {
+  return [self canPresentBubbleWithCheckTabScrolledToTop:YES];
+}
+
+// Returns whether the tab can present a bubble tip. Whether tab being scrolled
+// to top is required for presenting the bubble tip is determined by
+// `checkTabScrolledToTop`.
+- (BOOL)canPresentBubbleWithCheckTabScrolledToTop:(BOOL)checkTabScrolledToTop {
   // If BubblePresenter has been stopped, do not present the bubble.
   if (!self.started) {
     return NO;
@@ -693,7 +531,7 @@
     return NO;
   }
   // Do not present the bubble if the tab is not scrolled to the top.
-  if (![self isTabScrolledToTop]) {
+  if (checkTabScrolledToTop && ![self isTabScrolledToTop]) {
     return NO;
   }
   return YES;
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter_egtest.mm b/ios/chrome/browser/ui/bubble/bubble_presenter_egtest.mm
index a3cea091..c5dc45e 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter_egtest.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter_egtest.mm
@@ -54,22 +54,11 @@
   config.additional_args.push_back("-ForceExperienceForDeviceSwitcher");
   config.additional_args.push_back("SyncedAndFirstDevice");
   config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  // TODO(crbug.com/1470901): remove after fixing the bug on iphone.
-  if (![ChromeEarlGrey isIPadIdiom]) {
-    config.features_disabled.push_back(kBottomOmniboxDefaultSetting);
-    config.features_disabled.push_back(kBottomOmniboxSteadyState);
-  }
 
   [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
 
-  // Open an URL from NTP is likely not triggering showing the IPH due to
-  // failing the check `BubblePresenter::isTabScrolledToTop`, hence need to open
-  // an URL from non-NTP page below.
   [self openURLFromOmniboxWithIsAfterNewAppLaunch:YES];
 
-  // Open an URL from non-NTP page.
-  [self openURLFromOmniboxWithIsAfterNewAppLaunch:NO];
-
   [ChromeEarlGrey
       waitForUIElementToAppearWithMatcher:grey_accessibilityID(
                                               @"BubbleViewLabelIdentifier")];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_tile_saver.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_tile_saver.mm
index c1e2ed0..23ba88fa 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_tile_saver.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_tile_saver.mm
@@ -158,6 +158,7 @@
 }
 
 void WriteSavedMostVisited(NSDictionary<NSURL*, NTPTile*>* most_visited_data) {
+  NSDate* last_modification_date = NSDate.date;
   NSError* error = nil;
   NSData* data = [NSKeyedArchiver archivedDataWithRootObject:most_visited_data
                                        requiringSecureCoding:NO
@@ -171,6 +172,8 @@
   NSUserDefaults* sharedDefaults = app_group::GetGroupUserDefaults();
 
   [sharedDefaults setObject:data forKey:app_group::kSuggestedItems];
+  [sharedDefaults setObject:last_modification_date
+                     forKey:app_group::kSuggestedItemsLastModificationDate];
   UpdateShortcutsWidget();
 }
 
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
index 5a898214..5eb2957 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.h"
 #import "ios/chrome/browser/ui/broadcaster/chrome_broadcaster.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.h"
+#import "ios/web/common/features.h"
 
 // static
 FullscreenController* FullscreenController::FromBrowser(Browser* browser) {
@@ -45,8 +46,10 @@
                 forSelector:@selector(broadcastScrollViewContentInset:)];
   [broadcaster_ addObserver:bridge_
                 forSelector:@selector(broadcastContentScrollOffset:)];
-  [broadcaster_ addObserver:bridge_
-                forSelector:@selector(broadcastScrollViewIsScrolling:)];
+  if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    [broadcaster_ addObserver:bridge_
+                  forSelector:@selector(broadcastScrollViewIsScrolling:)];
+  }
   [broadcaster_ addObserver:bridge_
                 forSelector:@selector(broadcastScrollViewIsZooming:)];
   [broadcaster_ addObserver:bridge_
@@ -73,8 +76,10 @@
                    forSelector:@selector(broadcastScrollViewContentInset:)];
   [broadcaster_ removeObserver:bridge_
                    forSelector:@selector(broadcastContentScrollOffset:)];
-  [broadcaster_ removeObserver:bridge_
-                   forSelector:@selector(broadcastScrollViewIsScrolling:)];
+  if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    [broadcaster_ removeObserver:bridge_
+                     forSelector:@selector(broadcastScrollViewIsScrolling:)];
+  }
   [broadcaster_ removeObserver:bridge_
                    forSelector:@selector(broadcastScrollViewIsZooming:)];
   [broadcaster_ removeObserver:bridge_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
index b27dbde..ded3845e 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -9,6 +9,7 @@
 #import "base/check_op.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h"
 #import "ios/chrome/common/ui/util/ui_util.h"
+#import "ios/web/common/features.h"
 
 namespace {
 // Object that increments `counter` by 1 for its lifetime.
@@ -410,6 +411,7 @@
 }
 
 void FullscreenModel::OnScrollViewIsScrollingBroadcasted(bool scrolling) {
+  CHECK(base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault));
   SetScrollViewIsScrolling(scrolling);
 }
 
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
index 24634313..3a94a4e 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_proxy_observer.mm
@@ -9,6 +9,7 @@
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h"
 #import "ios/chrome/common/ui/util/ui_util.h"
+#import "ios/web/common/features.h"
 #import "ios/web/public/ui/crw_web_view_proxy.h"
 #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
 
@@ -60,4 +61,28 @@
   return scrollToTop;
 }
 
+- (void)webViewScrollViewWillBeginDragging:
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
+  if (!base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    self.model->SetScrollViewIsScrolling(true);
+  }
+}
+
+- (void)webViewScrollViewWillEndDragging:
+            (CRWWebViewScrollViewProxy*)webViewScrollViewProxy
+                            withVelocity:(CGPoint)velocity
+                     targetContentOffset:(inout CGPoint*)targetContentOffset {
+  if (!base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    self.model->SetScrollViewIsScrolling(false);
+  }
+}
+
+- (void)webViewScrollViewDidEndDragging:
+            (CRWWebViewScrollViewProxy*)webViewScrollViewProxy
+                         willDecelerate:(BOOL)decelerate {
+  if (!base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    self.model->SetScrollViewIsScrolling(false);
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/main_content/BUILD.gn b/ios/chrome/browser/ui/main_content/BUILD.gn
index bfb928f..0458ceb 100644
--- a/ios/chrome/browser/ui/main_content/BUILD.gn
+++ b/ios/chrome/browser/ui/main_content/BUILD.gn
@@ -35,7 +35,9 @@
 
   deps = [
     ":main_content_ui",
+    "//base",
     "//ios/chrome/browser/ui/broadcaster",
+    "//ios/web/common:features",
   ]
 }
 
diff --git a/ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.mm b/ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.mm
index 8056da58..ea1619e 100644
--- a/ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.mm
+++ b/ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.mm
@@ -7,6 +7,7 @@
 #import "ios/chrome/browser/ui/broadcaster/chrome_broadcaster.h"
 #import "ios/chrome/browser/ui/main_content/main_content_ui.h"
 #import "ios/chrome/browser/ui/main_content/main_content_ui_state.h"
+#import "ios/web/common/features.h"
 
 void StartBroadcastingMainContentUI(id<MainContentUI> main_content,
                                     ChromeBroadcaster* broadcaster) {
@@ -22,9 +23,11 @@
   [broadcaster broadcastValue:@"yContentOffset"
                      ofObject:main_content.mainContentUIState
                      selector:@selector(broadcastContentScrollOffset:)];
-  [broadcaster broadcastValue:@"scrolling"
-                     ofObject:main_content.mainContentUIState
-                     selector:@selector(broadcastScrollViewIsScrolling:)];
+  if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    [broadcaster broadcastValue:@"scrolling"
+                       ofObject:main_content.mainContentUIState
+                       selector:@selector(broadcastScrollViewIsScrolling:)];
+  }
   [broadcaster broadcastValue:@"zooming"
                      ofObject:main_content.mainContentUIState
                      selector:@selector(broadcastScrollViewIsZooming:)];
@@ -41,8 +44,10 @@
       stopBroadcastingForSelector:@selector(broadcastScrollViewContentInset:)];
   [broadcaster
       stopBroadcastingForSelector:@selector(broadcastContentScrollOffset:)];
-  [broadcaster
-      stopBroadcastingForSelector:@selector(broadcastScrollViewIsScrolling:)];
+  if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
+    [broadcaster
+        stopBroadcastingForSelector:@selector(broadcastScrollViewIsScrolling:)];
+  }
   [broadcaster
       stopBroadcastingForSelector:@selector(broadcastScrollViewIsZooming:)];
   [broadcaster
diff --git a/ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.mm b/ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.mm
index 95cfbe1..03aa8c1 100644
--- a/ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.mm
+++ b/ios/chrome/browser/ui/main_content/test/main_content_broadcast_test_util.mm
@@ -19,27 +19,22 @@
   TestMainContentUIStateModifier(TestMainContentUIState* state)
       : state_(state),
         original_offset_(state.yContentOffset),
-        was_scrolling_(state.scrolling),
         was_dragging_(state.dragging) {
     state_.yContentOffset += kOffsetDelta;
-    state_.scrolling = !was_scrolling_;
     state_.dragging = !was_dragging_;
   }
   ~TestMainContentUIStateModifier() {
     state_.yContentOffset = original_offset_;
-    state_.scrolling = was_scrolling_;
     state_.dragging = was_dragging_;
   }
 
   // The original values of the UI state.
   CGFloat original_offset() { return original_offset_; }
-  bool was_scrolling() { return was_scrolling_; }
   bool was_dragging() { return was_dragging_; }
 
  private:
   __strong TestMainContentUIState* state_ = nil;
   CGFloat original_offset_ = 0.0;
-  bool was_scrolling_ = false;
   bool was_dragging_ = false;
 };
 }  // namespace
@@ -57,11 +52,9 @@
   // Verify whether the changed or original UI elements are observed.
   if (should_broadcast) {
     EXPECT_TRUE(AreCGFloatsEqual(observer.yOffset, ui_state.yContentOffset));
-    EXPECT_EQ(observer.scrolling, ui_state.scrolling);
     EXPECT_EQ(observer.dragging, ui_state.dragging);
   } else {
     EXPECT_TRUE(AreCGFloatsEqual(observer.yOffset, modifier.original_offset()));
-    EXPECT_EQ(observer.scrolling, modifier.was_scrolling());
     EXPECT_EQ(observer.dragging, modifier.was_dragging());
   }
   // Stop observing `broadcaster`.
diff --git a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h
index 25aafa8..6cf8fe5 100644
--- a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h
+++ b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.h
@@ -18,7 +18,6 @@
 @property(nonatomic, strong) ChromeBroadcaster* broadcaster;
 // The broadcasted UI state observed by this object.
 @property(nonatomic, readonly) CGFloat yOffset;
-@property(nonatomic, readonly, getter=isScrolling) BOOL scrolling;
 @property(nonatomic, readonly, getter=isDragging) BOOL dragging;
 
 @end
diff --git a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.mm b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.mm
index 679525a..40c4d0e 100644
--- a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.mm
+++ b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_observer.mm
@@ -7,22 +7,17 @@
 @implementation TestMainContentUIObserver
 @synthesize broadcaster = _broadcaster;
 @synthesize yOffset = _yOffset;
-@synthesize scrolling = _scrolling;
 @synthesize dragging = _dragging;
 
 - (void)setBroadcaster:(ChromeBroadcaster*)broadcaster {
   [_broadcaster removeObserver:self
                    forSelector:@selector(broadcastContentScrollOffset:)];
   [_broadcaster removeObserver:self
-                   forSelector:@selector(broadcastScrollViewIsScrolling:)];
-  [_broadcaster removeObserver:self
                    forSelector:@selector(broadcastScrollViewIsDragging:)];
   _broadcaster = broadcaster;
   [_broadcaster addObserver:self
                 forSelector:@selector(broadcastContentScrollOffset:)];
   [_broadcaster addObserver:self
-                forSelector:@selector(broadcastScrollViewIsScrolling:)];
-  [_broadcaster addObserver:self
                 forSelector:@selector(broadcastScrollViewIsDragging:)];
 }
 
@@ -30,10 +25,6 @@
   _yOffset = offset;
 }
 
-- (void)broadcastScrollViewIsScrolling:(BOOL)scrolling {
-  _scrolling = scrolling;
-}
-
 - (void)broadcastScrollViewIsDragging:(BOOL)dragging {
   _dragging = dragging;
 }
diff --git a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h
index 6ba2ad9..a2139cb 100644
--- a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h
+++ b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.h
@@ -13,7 +13,6 @@
 
 // Redefine broadcast properties as readwrite.
 @property(nonatomic, assign) CGFloat yContentOffset;
-@property(nonatomic, assign, getter=isScrolling) BOOL scrolling;
 @property(nonatomic, assign, getter=isDragging) BOOL dragging;
 
 @end
diff --git a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.mm b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.mm
index 141ed30..a651d73e4 100644
--- a/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.mm
+++ b/ios/chrome/browser/ui/main_content/test/test_main_content_ui_state.mm
@@ -6,6 +6,5 @@
 
 @implementation TestMainContentUIState
 @synthesize yContentOffset = _yContentOffset;
-@synthesize scrolling = _scrolling;
 @synthesize dragging = _dragging;
 @end
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h
index e55876a14..642f68d0 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h
@@ -23,9 +23,6 @@
 // Whether the NewOverflowMenu feature is enabled.
 bool IsNewOverflowMenuEnabled();
 
-// Whether or not the NewOverflowMenuReorderSettings feature is enabled.
-bool IsNewOverflowMenuReorderSettingsEnabled();
-
 // Whether or not the NewOverflowMenuShareChromeAction is enabled.
 bool IsNewOverflowMenuShareChromeActionEnabled();
 
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
index 7422529..38208a76 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -996,8 +996,10 @@
   __weak __typeof(self) weakSelf = self;
   ActionRanking reorderableActions = [self basePageActions];
   // If this action is not reorderable, then don't add any longpress items.
-  if (std::find(reorderableActions.begin(), reorderableActions.end(),
-                actionType) != reorderableActions.end()) {
+  bool actionIsReorderable =
+      std::find(reorderableActions.begin(), reorderableActions.end(),
+                actionType) != reorderableActions.end();
+  if (IsOverflowMenuCustomizationEnabled() && actionIsReorderable) {
     action.longPressItems = @[
       [[OverflowMenuLongPressItem alloc]
           initWithTitle:l10n_util::GetNSString(
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
index 13e3bcaf..1ffef73 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
@@ -220,8 +220,6 @@
   // Allow the non-modal promo scheduler to close the promo.
   [nonModalPromoScheduler logPopupMenuEntered];
 
-  [self.bubblePresenter toolsMenuDisplayed];
-
   self.requestStartTime = [NSDate timeIntervalSinceReferenceDate];
 
   PopupMenuTableViewController* tableViewController =
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index 9c035dbd..b070687 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -279,7 +279,6 @@
     "//base",
     "//base/test:test_support",
     "//ios/chrome/app/strings",
-    "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/reading_list/DEPS b/ios/chrome/browser/ui/reading_list/DEPS
index ac4b905..320dc09d 100644
--- a/ios/chrome/browser/ui/reading_list/DEPS
+++ b/ios/chrome/browser/ui/reading_list/DEPS
@@ -3,7 +3,6 @@
   "+ios/chrome/browser/ui/incognito_reauth",
   "+ios/chrome/browser/ui/menu",
   "+ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h",
-  "+ios/chrome/browser/ui/popup_menu",
   "+ios/chrome/browser/ui/settings/cells/sync_switch_item.h",
   "+ios/chrome/browser/ui/sharing",
 ]
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_account_storage_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_account_storage_egtest.mm
index 15f5b75..b8fe6777 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_account_storage_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_account_storage_egtest.mm
@@ -149,7 +149,11 @@
   config.features_enabled.push_back(
       syncer::kReadingListEnableSyncTransportModeUponSignIn);
   if ([self isRunningTest:@selector
-            (testSignInWithSecondaryAccountInPromo_WithSnackbar)]) {
+            (testSignInWithSecondaryAccountInPromo_WithSnackbar)] ||
+      [self isRunningTest:@selector(testAddAccountItemThenUpgradeToFullSync)] ||
+      [self isRunningTest:@selector(testAddItemWithFullSync)] ||
+      [self isRunningTest:@selector(testUndoAddItemWithFullSync)] ||
+      [self isRunningTest:@selector(testPromoNotShownWhenSyncDataNotRemoved)]) {
     config.features_disabled.push_back(
         syncer::kReplaceSyncPromosWithSignInPromos);
   }
@@ -372,9 +376,16 @@
   [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail(
                                           fakeIdentity2.userEmail)]
       performAction:grey_tap()];
-  [ChromeEarlGrey
-      waitForUIElementToAppearWithMatcher:SignedInSnackbar(
-                                              fakeIdentity2.userEmail)];
+
+  // The sign-in snackbar is only displayed if the feature
+  // syncer::kReplaceSyncPromosWithSignInPromos is disabled, as per logic
+  // introduced in https://crrev.com/c/4733378.
+  if (![ChromeEarlGrey isReplaceSyncWithSigninEnabled]) {
+    [ChromeEarlGrey
+        waitForUIElementToAppearWithMatcher:SignedInSnackbar(
+                                                fakeIdentity2.userEmail)];
+  }
+
   // Verify that the second account is signed-in.
   [SigninEarlGrey verifyPrimaryAccountWithEmail:fakeIdentity2.userEmail
                                         consent:signin::ConsentLevel::kSignin];
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest_utils.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest_utils.mm
index 4469fbdb..677be05 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest_utils.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest_utils.mm
@@ -4,7 +4,6 @@
 
 #import "ios/chrome/browser/ui/reading_list/reading_list_egtest_utils.h"
 
-#import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_app_interface.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_constants.h"
 #import "ios/chrome/grit/ios_strings.h"
@@ -52,20 +51,6 @@
   [ChromeEarlGrey waitForPageToFinishLoading];
   // Add the page to the Reading List.
   [ChromeEarlGreyUI openToolsMenu];
-
-  // TODO(crbug.com/1473383): Remove workaround when tapping works properly.
-  if (![ChromeEarlGrey isIPadIdiom]) {
-    if (@available(iOS 17.0, *)) {
-      // The button is manually tappable which is why tests that use this method
-      // are not disabled. Instead, we implement this workaround for the tools
-      // menu action item not being tappable on iPhone after being tapped in a
-      // separate instance during EG tests.
-      [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                              kPopupMenuToolsMenuActionListId)]
-          performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
-    }
-  }
-
   [ChromeEarlGreyUI
       tapToolsMenuAction:chrome_test_util::ButtonWithAccessibilityLabelId(
                              IDS_IOS_SHARE_MENU_READING_LIST_ACTION)];
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
index b0b92842..c33fb10 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
@@ -709,7 +709,10 @@
 
   [[EarlGrey
       selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
-                                   IDS_IOS_MANAGE_SYNC_SETTINGS_TITLE))]
+                                   [ChromeEarlGrey
+                                       isReplaceSyncWithSigninEnabled]
+                                       ? IDS_IOS_HISTORY_SYNC_TITLE
+                                       : IDS_IOS_MANAGE_SYNC_SETTINGS_TITLE))]
       assertWithMatcher:grey_sufficientlyVisible()];
 }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
index 77cc364..5aa43c6 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
@@ -63,7 +63,6 @@
     "//ios/chrome/browser/ui/commerce:price_card",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/history/public",
-    "//ios/chrome/browser/ui/incognito_reauth:incognito_reauth_scene_agent",
     "//ios/chrome/browser/ui/main",
     "//ios/chrome/browser/ui/menu:tab_context_menu_delegate",
     "//ios/chrome/browser/ui/recent_tabs",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator_unittest.mm
index c0109d5..328edf1 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator_unittest.mm
@@ -46,7 +46,9 @@
   void SetUp() override {
     GridMediatorTestClass::SetUp();
     if (GetParam() == TEST_INCOGNITO_MEDIATOR) {
-      mediator_ = [[IncognitoGridMediator alloc] initWithConsumer:consumer_];
+      mediator_ = [[IncognitoGridMediator alloc]
+          initWithPrefService:scoped_testing_local_state_.Get()
+                     consumer:consumer_];
     } else {
       mediator_ = [[RegularGridMediator alloc] initWithConsumer:consumer_];
     }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
index 6801f94..76aaf1a 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -269,6 +269,11 @@
       return [weakSelf headerForSectionAtIndexPath:indexPath];
     };
     collectionView.dataSource = self.diffableDataSource;
+
+    // UICollectionViewDropPlaceholder uses a GridCell and needs the class to be
+    // registered.
+    [collectionView registerClass:[GridCell class]
+        forCellWithReuseIdentifier:kCellIdentifier];
   } else {
     [collectionView registerClass:[GridCell class]
         forCellWithReuseIdentifier:kCellIdentifier];
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/BUILD.gn
index e87464d5..01dacbb 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/BUILD.gn
@@ -11,12 +11,19 @@
   ]
 
   deps = [
+    ":incognito_grid_mediator_delegate",
     "//base",
+    "//components/prefs",
+    "//components/prefs/ios",
+    "//components/supervised_user/core/common",
     "//ios/chrome/browser/policy:policy_util",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
+    "//ios/chrome/browser/shared/coordinator/scene:scene_state_browser_agent",
     "//ios/chrome/browser/shared/model/browser_state",
     "//ios/chrome/browser/shared/model/web_state_list",
+    "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/snapshots",
+    "//ios/chrome/browser/ui/incognito_reauth:incognito_reauth_scene_agent",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid:tab_grid_metrics",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid:tab_grid_ui",
     "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid",
@@ -38,3 +45,9 @@
     "//ios/chrome/browser/ui/tab_switcher/test:fakes",
   ]
 }
+
+source_set("incognito_grid_mediator_delegate") {
+  sources = [ "incognito_grid_mediator_delegate.h" ]
+
+  deps = [ "//base" ]
+}
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.h
index 7f3b8a0..14ee675b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.h
@@ -6,13 +6,15 @@
 #define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_INCOGNITO_INCOGNITO_GRID_COORDINATOR_H_
 
 #import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_delegate.h"
 
 @protocol GridMediatorDelegate;
 @protocol GridToolbarsMutator;
 @class IncognitoGridMediator;
 @class TabGridViewController;
 
-@interface IncognitoGridCoordinator : ChromeCoordinator
+@interface IncognitoGridCoordinator
+    : ChromeCoordinator <IncognitoGridMediatorDelegate>
 // Incognito view controller.
 // TODO(crbug.com/1457146): Replace this once the incognito grid view controller
 // is created.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.mm
index c68061c..4a2f243 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.mm
@@ -4,6 +4,11 @@
 
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_coordinator.h"
 
+#import "ios/chrome/browser/shared/coordinator/scene/scene_state_browser_agent.h"
+#import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h"
+#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h"
 
@@ -14,6 +19,10 @@
   __weak id<GridToolbarsMutator> _toolbarsMutator;
   // Delegate to handle presenting the action sheet.
   __weak id<GridMediatorDelegate> _gridMediatorDelegate;
+  // Mediator for incognito reauth.
+  IncognitoReauthMediator* _incognitoAuthMediator;
+  // Commad dispatcher used while this coordinator's view controller is active.
+  CommandDispatcher* _dispatcher;
 }
 
 - (instancetype)initWithBaseViewController:(UIViewController*)baseViewController
@@ -44,20 +53,56 @@
 #pragma mark - ChromeCoordinator
 
 - (void)start {
+  // TODO(crbug.com/1246931): refactor to call setIncognitoBrowser from this
+  // function.
+  IncognitoReauthSceneAgent* reauthAgent = [IncognitoReauthSceneAgent
+      agentFromScene:SceneStateBrowserAgent::FromBrowser(self.browser)
+                         ->GetSceneState()];
+
+  _dispatcher = [[CommandDispatcher alloc] init];
+  [_dispatcher startDispatchingToTarget:reauthAgent
+                            forProtocol:@protocol(IncognitoReauthCommands)];
+
   // TODO(crbug.com/1457146): Init view controller here instead of having a
   // public property.
+  self.incognitoViewController.reauthAgent = reauthAgent;
+  self.incognitoViewController.reauthHandler =
+      HandlerForProtocol(_dispatcher, IncognitoReauthCommands);
 
   _mediator = [[IncognitoGridMediator alloc]
-      initWithConsumer:self.incognitoViewController.incognitoTabsConsumer];
+      initWithPrefService:self.browser->GetBrowserState()->GetPrefs()
+                 consumer:self.incognitoViewController.incognitoTabsConsumer];
   _mediator.browser = self.browser;
   _mediator.delegate = _gridMediatorDelegate;
   _mediator.toolbarsMutator = _toolbarsMutator;
   _mediator.actionWrangler = self.incognitoViewController;
+  _mediator.incognitoDelegate = self;
+
+  _incognitoAuthMediator =
+      [[IncognitoReauthMediator alloc] initWithReauthAgent:reauthAgent];
+  _incognitoAuthMediator.consumer =
+      self.incognitoViewController.incognitoTabsConsumer;
 }
 
 - (void)stop {
   _mediator = nil;
-  _toolbarsMutator = nil;
+  _incognitoAuthMediator = nil;
+
+  [_dispatcher stopDispatchingForProtocol:@protocol(IncognitoReauthCommands)];
+  _dispatcher = nil;
+}
+
+#pragma mark - IncognitoGridMediatorDelegate
+
+- (void)shouldDisableIncognito:(BOOL)disable {
+  // TODO(crbug.com/1457146): When the incognito view controller will be managed
+  // here, the view controller should be updated here (disabled VC <-> enabled
+  // VC)
+
+  _incognitoAuthMediator.consumer =
+      self.incognitoViewController.incognitoTabsConsumer;
+  self.incognitoViewController.reauthHandler =
+      HandlerForProtocol(_dispatcher, IncognitoReauthCommands);
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.h
index d750fbb9..0f193bf0 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.h
@@ -7,9 +7,24 @@
 
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.h"
 
+@protocol IncognitoGridMediatorDelegate;
+@protocol TabCollectionConsumer;
+class PrefService;
+
 // Mediates between model layer and incognito grid UI layer.
 @interface IncognitoGridMediator : BaseGridMediator
 
+// Incognito mediator delegate.
+@property(nonatomic, weak) id<IncognitoGridMediatorDelegate> incognitoDelegate;
+
+- (instancetype)initWithPrefService:(PrefService*)prefService
+                           consumer:(id<TabCollectionConsumer>)consumer
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithConsumer:(id<TabCollectionConsumer>)consumer
+    NS_UNAVAILABLE;
+- (instancetype)init NS_UNAVAILABLE;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_INCOGNITO_INCOGNITO_GRID_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.mm
index 90a0262..481fa5d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator.mm
@@ -7,15 +7,52 @@
 #import "base/metrics/histogram_functions.h"
 #import "base/metrics/user_metrics.h"
 #import "base/metrics/user_metrics_action.h"
+#import "components/prefs/ios/pref_observer_bridge.h"
+#import "components/prefs/pref_change_registrar.h"
+#import "components/supervised_user/core/common/features.h"
+#import "components/supervised_user/core/common/pref_names.h"
+#import "components/supervised_user/core/common/supervised_user_utils.h"
 #import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/snapshots/snapshot_browser_agent.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_toolbars_mutator.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_delegate.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_configuration.h"
 
-@implementation IncognitoGridMediator
+@interface IncognitoGridMediator () <PrefObserverDelegate>
+@end
+
+@implementation IncognitoGridMediator {
+  // Preference service from the application context.
+  PrefService* _prefService;
+  // Pref observer to track changes to prefs.
+  std::unique_ptr<PrefObserverBridge> _prefObserverBridge;
+  // Registrar for pref changes notifications.
+  PrefChangeRegistrar _prefChangeRegistrar;
+  // YES if incognito is disabled.
+  BOOL _incognitoDisabled;
+}
+
+- (instancetype)initWithPrefService:(PrefService*)prefService
+                           consumer:(id<TabCollectionConsumer>)consumer {
+  if (self = [super initWithConsumer:consumer]) {
+    // Register to observe any changes on supervised_user status.
+    if (base::FeatureList::IsEnabled(
+            supervised_user::
+                kFilterWebsitesForSupervisedUsersOnDesktopAndIOS)) {
+      CHECK(prefService);
+      _prefService = prefService;
+      _prefChangeRegistrar.Init(_prefService);
+      _prefObserverBridge.reset(new PrefObserverBridge(self));
+      _prefObserverBridge->ObserveChangesForPreference(prefs::kSupervisedUserId,
+                                                       &_prefChangeRegistrar);
+      _incognitoDisabled = [self isIncognitoModeDisabled];
+    }
+  }
+  return self;
+}
 
 // TODO(crbug.com/1457146): Refactor the grid commands to have the same function
 // name to close all.
@@ -78,4 +115,24 @@
   [self.toolbarsMutator setToolbarConfiguration:toolbarsConfiguration];
 }
 
+#pragma mark - PrefObserverDelegate
+
+- (void)onPreferenceChanged:(const std::string&)preferenceName {
+  if (preferenceName == prefs::kSupervisedUserId) {
+    BOOL isDisabled = [self isIncognitoModeDisabled];
+    if (_incognitoDisabled != isDisabled) {
+      _incognitoDisabled = isDisabled;
+      [self.incognitoDelegate shouldDisableIncognito:_incognitoDisabled];
+    }
+  }
+}
+
+#pragma mark - Private
+
+// Returns YES if incognito is disabled.
+- (BOOL)isIncognitoModeDisabled {
+  return supervised_user::IsSubjectToParentalControls(_prefService) ||
+         IsIncognitoModeDisabled(_prefService);
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_delegate.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_delegate.h
new file mode 100644
index 0000000..1b16939
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_delegate.h
@@ -0,0 +1,18 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_INCOGNITO_INCOGNITO_GRID_MEDIATOR_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_INCOGNITO_INCOGNITO_GRID_MEDIATOR_DELEGATE_H_
+
+// Delegate allowing the incognito grid mediator to update the incognito tab
+// grid coordinator.
+@protocol IncognitoGridMediatorDelegate
+
+// `disable` set to YES if the incognito view controller should be the disabled
+// one.
+- (void)shouldDisableIncognito:(BOOL)disable;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_INCOGNITO_INCOGNITO_GRID_MEDIATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_unittest.mm
index 44f49df9..59eeea5 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/incognito/incognito_grid_mediator_unittest.mm
@@ -16,7 +16,9 @@
 
   void SetUp() override {
     GridMediatorTestClass::SetUp();
-    mediator_ = [[IncognitoGridMediator alloc] initWithConsumer:consumer_];
+    mediator_ = [[IncognitoGridMediator alloc]
+        initWithPrefService:scoped_testing_local_state_.Get()
+                   consumer:consumer_];
     mediator_.browser = browser_.get();
   }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
index 658e1423..a792652b4 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -69,8 +69,6 @@
 #import "ios/chrome/browser/ui/history/history_coordinator.h"
 #import "ios/chrome/browser/ui/history/history_coordinator_delegate.h"
 #import "ios/chrome/browser/ui/history/public/history_presentation_delegate.h"
-#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_mediator.h"
-#import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h"
 #import "ios/chrome/browser/ui/menu/tab_context_menu_delegate.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.h"
@@ -199,8 +197,6 @@
 @property(nonatomic, strong) IncognitoGridMediator* incognitoTabsMediator;
 // Mediator for PriceCardView - this is only for regular Tabs.
 @property(nonatomic, strong) PriceCardMediator* priceCardMediator;
-// Mediator for incognito reauth.
-@property(nonatomic, strong) IncognitoReauthMediator* incognitoAuthMediator;
 // Mediator for remote Tabs.
 @property(nonatomic, strong) RecentTabsMediator* remoteTabsMediator;
 // Mediator for pinned Tabs.
@@ -700,15 +696,6 @@
 #pragma mark - ChromeCoordinator
 
 - (void)start {
-  // TODO(crbug.com/1246931): refactor to call setIncognitoBrowser from this
-  // function.
-  IncognitoReauthSceneAgent* reauthAgent = [IncognitoReauthSceneAgent
-      agentFromScene:SceneStateBrowserAgent::FromBrowser(_incognitoBrowser)
-                         ->GetSceneState()];
-
-  [self.dispatcher startDispatchingToTarget:reauthAgent
-                                forProtocol:@protocol(IncognitoReauthCommands)];
-
   _mediator = [[TabGridMediator alloc]
       initWithPrefService:self.regularBrowser->GetBrowserState()->GetPrefs()];
 
@@ -718,9 +705,6 @@
   TabGridViewController* baseViewController = [[TabGridViewController alloc]
       initWithPageConfiguration:_pageConfiguration];
   baseViewController.handler = applicationCommandsHandler;
-  baseViewController.reauthHandler =
-      HandlerForProtocol(self.dispatcher, IncognitoReauthCommands);
-  baseViewController.reauthAgent = reauthAgent;
   baseViewController.tabPresentationDelegate = self;
   baseViewController.layoutGuideCenter = LayoutGuideCenterForBrowser(nil);
   baseViewController.delegate = self;
@@ -807,11 +791,6 @@
   self.baseViewController.incognitoTabsShareableItemsProvider =
       self.incognitoTabsMediator;
 
-  self.incognitoAuthMediator =
-      [[IncognitoReauthMediator alloc] initWithReauthAgent:reauthAgent];
-  self.incognitoAuthMediator.consumer =
-      self.baseViewController.incognitoTabsConsumer;
-
   self.recentTabsContextMenuHelper =
       [[RecentTabsContextMenuHelper alloc] initWithBrowser:self.regularBrowser
                             recentTabsPresentationDelegate:self
@@ -1118,13 +1097,9 @@
   // Reconnect the incognito mediators to the incognito view controller.
   self.incognitoTabsMediator.consumer =
       self.baseViewController.incognitoTabsConsumer;
-  self.incognitoAuthMediator.consumer =
-      self.baseViewController.incognitoTabsConsumer;
 
   // Reset the connection between the incognito view controller and the
   // mediator.
-  self.baseViewController.reauthHandler =
-      HandlerForProtocol(self.dispatcher, IncognitoReauthCommands);
   self.baseViewController.incognitoTabsContextMenuProvider =
       self.incognitoTabContextMenuHelper;
   self.baseViewController.incognitoTabsShareableItemsProvider =
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
index 1ebf7e1..b69ca258 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.h
@@ -15,6 +15,7 @@
 class PrefService;
 
 // Delegate allowing the tab grid coordinator to update the incognito tab grid.
+// TODO(crbug.com/1457146): To remove when incognito is fully isolated.
 @protocol TabGridMediatorDelegate
 // Repopulates the incognito tab grid with incognito tabs if applicable.
 - (void)updateIncognitoTabGridState;
@@ -23,11 +24,6 @@
 // Mediates between model layer and tab grid UI layer.
 @interface TabGridMediator : NSObject <TabGridMutator>
 
-- (instancetype)initWithPrefService:(PrefService*)prefService
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)init NS_UNAVAILABLE;
-
 // Mutator for regular Tabs.
 @property(nonatomic, weak) id<TabGridPageMutator> regularPageMutator;
 // Mutator for incognito Tabs.
@@ -37,8 +33,13 @@
 
 // Consumer for state changes in tab grid.
 @property(nonatomic, weak) id<TabGridConsumer> consumer;
-// Delegate allowing the mediator to update the incognito tab grid.
+// Delegate allowing the mediator to update the tab grid coordinator.
 @property(nonatomic, weak) id<TabGridMediatorDelegate> delegate;
+
+- (instancetype)initWithPrefService:(PrefService*)prefService
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
 // Set the current displayed page (incognito, regular or remote).
 - (void)setPage:(TabGridPage)page;
 // Stops mediating and disconnects from backend models.
diff --git a/ios/chrome/common/app_group/app_group_constants.h b/ios/chrome/common/app_group/app_group_constants.h
index 836f77e..06cc88ea 100644
--- a/ios/chrome/common/app_group/app_group_constants.h
+++ b/ios/chrome/common/app_group/app_group_constants.h
@@ -146,6 +146,10 @@
 // The value of the key for the sharedDefaults used by the Content Widget.
 extern NSString* const kSuggestedItems;
 
+// The value of the key for the sharedDefaults last modification date used by
+// the Shortcuts Widget.
+extern NSString* const kSuggestedItemsLastModificationDate;
+
 // The current epoch time, on the first run of chrome on this machine. It is set
 // once and must be attached to metrics reports forever thereafter.
 extern const char kInstallDate[];
diff --git a/ios/chrome/common/app_group/app_group_constants.mm b/ios/chrome/common/app_group/app_group_constants.mm
index e77118d..0cb14840cf 100644
--- a/ios/chrome/common/app_group/app_group_constants.mm
+++ b/ios/chrome/common/app_group/app_group_constants.mm
@@ -71,6 +71,9 @@
 
 NSString* const kSuggestedItems = @"SuggestedItems";
 
+NSString* const kSuggestedItemsLastModificationDate =
+    @"SuggestedItemsLastModificationDate";
+
 NSString* ApplicationGroup() {
   return [AppGroupHelper applicationGroup];
 }
diff --git a/ios/chrome/common/intents/BUILD.gn b/ios/chrome/common/intents/BUILD.gn
index ba84807..7566368 100644
--- a/ios/chrome/common/intents/BUILD.gn
+++ b/ios/chrome/common/intents/BUILD.gn
@@ -12,5 +12,7 @@
     "SearchInChromeIntent",
     "OpenReadingListIntent",
     "OpenBookmarksIntent",
+    "OpenRecentTabsIntent",
+    "OpenTabGridIntent",
   ]
 }
diff --git a/ios/chrome/common/intents/Intents.intentdefinition b/ios/chrome/common/intents/Intents.intentdefinition
index 967e436a..4fdbb7f 100644
--- a/ios/chrome/common/intents/Intents.intentdefinition
+++ b/ios/chrome/common/intents/Intents.intentdefinition
@@ -435,6 +435,134 @@
 			<key>INIntentVerb</key>
 			<string>Open</string>
 		</dict>
+		<dict>
+			<key>INIntentCategory</key>
+			<string>information</string>
+			<key>INIntentConfigurable</key>
+			<true/>
+			<key>INIntentDescriptionID</key>
+			<string>Dnbiji</string>
+			<key>INIntentEligibleForWidgets</key>
+			<true/>
+			<key>INIntentManagedParameterCombinations</key>
+			<dict>
+				<key></key>
+				<dict>
+					<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
+					<true/>
+					<key>INIntentParameterCombinationTitle</key>
+					<string>See Recent Tabs In Chrome</string>
+					<key>INIntentParameterCombinationTitleID</key>
+					<string>h5ylvP</string>
+					<key>INIntentParameterCombinationUpdatesLinked</key>
+					<true/>
+				</dict>
+			</dict>
+			<key>INIntentName</key>
+			<string>OpenRecentTabs</string>
+			<key>INIntentParameterCombinations</key>
+			<dict>
+				<key></key>
+				<dict>
+					<key>INIntentParameterCombinationIsPrimary</key>
+					<true/>
+					<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
+					<true/>
+					<key>INIntentParameterCombinationTitle</key>
+					<string>See Recent Tabs In Chrome</string>
+					<key>INIntentParameterCombinationTitleID</key>
+					<string>vp7qIi</string>
+				</dict>
+			</dict>
+			<key>INIntentResponse</key>
+			<dict>
+				<key>INIntentResponseCodes</key>
+				<array>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>success</string>
+						<key>INIntentResponseCodeSuccess</key>
+						<true/>
+					</dict>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>failure</string>
+					</dict>
+				</array>
+			</dict>
+			<key>INIntentTitle</key>
+			<string>See Recent Tabs In Chrome</string>
+			<key>INIntentTitleID</key>
+			<string>Lx9GhK</string>
+			<key>INIntentType</key>
+			<string>Custom</string>
+			<key>INIntentVerb</key>
+			<string>Open</string>
+		</dict>
+		<dict>
+			<key>INIntentCategory</key>
+			<string>information</string>
+			<key>INIntentConfigurable</key>
+			<true/>
+			<key>INIntentDescriptionID</key>
+			<string>j61w32</string>
+			<key>INIntentEligibleForWidgets</key>
+			<true/>
+			<key>INIntentManagedParameterCombinations</key>
+			<dict>
+				<key></key>
+				<dict>
+					<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
+					<true/>
+					<key>INIntentParameterCombinationTitle</key>
+					<string>Visit The Tab Grid In Chrome</string>
+					<key>INIntentParameterCombinationTitleID</key>
+					<string>0wmLKV</string>
+					<key>INIntentParameterCombinationUpdatesLinked</key>
+					<true/>
+				</dict>
+			</dict>
+			<key>INIntentName</key>
+			<string>OpenTabGrid</string>
+			<key>INIntentParameterCombinations</key>
+			<dict>
+				<key></key>
+				<dict>
+					<key>INIntentParameterCombinationIsPrimary</key>
+					<true/>
+					<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
+					<true/>
+					<key>INIntentParameterCombinationTitle</key>
+					<string>Visit The Tab Grid In Chrome</string>
+					<key>INIntentParameterCombinationTitleID</key>
+					<string>hB4zxD</string>
+				</dict>
+			</dict>
+			<key>INIntentResponse</key>
+			<dict>
+				<key>INIntentResponseCodes</key>
+				<array>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>success</string>
+						<key>INIntentResponseCodeSuccess</key>
+						<true/>
+					</dict>
+					<dict>
+						<key>INIntentResponseCodeName</key>
+						<string>failure</string>
+					</dict>
+				</array>
+			</dict>
+			<key>INIntentTitle</key>
+			<string>Visit The Tab Grid In Chrome</string>
+			<key>INIntentTitleID</key>
+			<string>t9NbV2</string>
+			<key>INIntentType</key>
+			<string>Custom</string>
+			<key>INIntentVerb</key>
+			<string>Open</string>
+		</dict>
 	</array>
 	<key>INTypes</key>
 	<array/>
diff --git a/ios/chrome/intents_extension/chrome_intents_handler.mm b/ios/chrome/intents_extension/chrome_intents_handler.mm
index ec0abb8a..d6d91a9a 100644
--- a/ios/chrome/intents_extension/chrome_intents_handler.mm
+++ b/ios/chrome/intents_extension/chrome_intents_handler.mm
@@ -10,13 +10,17 @@
 #import "ios/chrome/common/intents/OpenInChromeIncognitoIntent.h"
 #import "ios/chrome/common/intents/OpenInChromeIntent.h"
 #import "ios/chrome/common/intents/OpenReadingListIntent.h"
+#import "ios/chrome/common/intents/OpenRecentTabsIntent.h"
+#import "ios/chrome/common/intents/OpenTabGridIntent.h"
 #import "ios/chrome/common/intents/SearchInChromeIntent.h"
 
 @interface ChromeIntentsHandler () <OpenInChromeIncognitoIntentHandling,
                                     OpenInChromeIntentHandling,
                                     SearchInChromeIntentHandling,
                                     OpenReadingListIntentHandling,
-                                    OpenBookmarksIntentHandling>
+                                    OpenBookmarksIntentHandling,
+                                    OpenRecentTabsIntentHandling,
+                                    OpenTabGridIntentHandling>
 @end
 
 @implementation ChromeIntentsHandler
@@ -141,4 +145,33 @@
   completion(response);
 }
 
+#pragma mark - OpenRecentTabsIntentHandling
+
+- (void)handleOpenRecentTabs:(OpenRecentTabsIntent*)intent
+                  completion:
+                      (void (^)(OpenRecentTabsIntentResponse*))completion {
+  NSUserActivity* activity = [[NSUserActivity alloc]
+      initWithActivityType:NSStringFromClass([OpenRecentTabsIntent class])];
+
+  OpenRecentTabsIntentResponse* response = [[OpenRecentTabsIntentResponse alloc]
+      initWithCode:OpenRecentTabsIntentResponseCodeContinueInApp
+      userActivity:activity];
+
+  completion(response);
+}
+
+#pragma mark - OpenTabGridIntentHandling
+
+- (void)handleOpenTabGrid:(OpenTabGridIntent*)intent
+               completion:(void (^)(OpenTabGridIntentResponse*))completion {
+  NSUserActivity* activity = [[NSUserActivity alloc]
+      initWithActivityType:NSStringFromClass([OpenTabGridIntent class])];
+
+  OpenTabGridIntentResponse* response = [[OpenTabGridIntentResponse alloc]
+      initWithCode:OpenTabGridIntentResponseCodeContinueInApp
+      userActivity:activity];
+
+  completion(response);
+}
+
 @end
diff --git a/ios/chrome/widget_kit_extension/shortcuts_widget.swift b/ios/chrome/widget_kit_extension/shortcuts_widget.swift
index 223d266..04bc967e 100644
--- a/ios/chrome/widget_kit_extension/shortcuts_widget.swift
+++ b/ios/chrome/widget_kit_extension/shortcuts_widget.swift
@@ -6,15 +6,27 @@
 import SwiftUI
 import WidgetKit
 
+enum Constants {
+  //A constant variable to count the number of seconds in a month
+  static let secondsInFourWeeks: TimeInterval = 4 * 7 * 24 * 60 * 60
+
+  //A constant variable to count the number of seconds in a month
+  static let secondsInFiveMinutes: TimeInterval = 5 * 60
+}
+
 // Specifies the date of the current widget and indicates the widget's content.
 struct ConfigureShortcutsWidgetEntry: TimelineEntry {
-  // Date and time to update the widget’s content.
+  // Date and time to update the widget’s shortcuts.
   let date: Date
   // A dictionary containing the most visited URLs
   // and their NTPTiles from the UserDefaults.
   let mostVisitedSites: [NSURL: NTPTile]
   // A Boolean value that indicates when the widget appears in the widget gallery.
-  var isPreview: Bool = false
+  let isPreview: Bool
+  // A Boolean value that indicates when the user didn't opened Chrome for the more than one month.
+  let isExpired: Bool
+  // Expiration date of the widget if it hasn't expired.
+  let expirationDate: Date?
 }
 
 // Advises WidgetKit when to update a widget’s display.
@@ -25,18 +37,66 @@
 
   // Provides a timeline entry representing a placeholder version of the widget.
   func placeholder(in context: TimelineProviderContext) -> Entry {
-    return Entry(date: Date(), mostVisitedSites: [NSURL: NTPTile]())
+    return Entry(
+      date: Date(), mostVisitedSites: [:], isPreview: true, isExpired: false, expirationDate: nil)
   }
 
-  // This function is to load the most visited websites
-  // from NTPTiles from the UserDefaults.
-  func loadMostVisitedSites() -> [NSURL: NTPTile] {
-    let sharedDefaults: UserDefaults = AppGroupHelper.groupUserDefaults()
+  // Return an Entry with the most visited sites
+  func loadMostVisitedSitesEntry(isPreview: Bool) -> Entry {
+
+    // A constant of an empty entry
+    let emptyEntry = Entry(
+      date: Date(),
+      mostVisitedSites: [:],
+      isPreview: isPreview,
+      isExpired: false,
+      expirationDate: nil
+    )
+    // A constant of an expired entry
+    let expiredEntry = Entry(
+      date: Date(),
+      mostVisitedSites: [:],
+      isPreview: isPreview,
+      isExpired: true,
+      expirationDate: nil
+    )
+    // Returns an empty entry if the Shortcuts Widget is in the Widgets Gallery
+    if isPreview {
+      return emptyEntry
+    }
+
+    guard let sharedDefaults: UserDefaults = AppGroupHelper.groupUserDefaults(),
+      let lastModificationDate = sharedDefaults.object(forKey: "SuggestedItemsLastModificationDate")
+        as? Date
+    else {
+      return emptyEntry
+    }
+
+    let extensionsFlags =
+      sharedDefaults.object(forKey: "Extension.FieldTrial") as? [String: Any] ?? [:]
+    let fiveMinutestoRefreshTestFlag =
+      extensionsFlags["WidgetKitRefreshFiveMinutes"] as? [String: Any] ?? [:]
+    // A constant to know the status of WidgetKitRefreshFiveMinutes Test Flag
+    let fiveMinutestoRefreshTestValue =
+      fiveMinutestoRefreshTestFlag["FieldTrialValue"] as? Bool ?? false
+
+    // A constant to get the number of seconds of the last modification date of the installed widget
+    let numberOfSecondsSinceLastModification = Date.now.timeIntervalSince(lastModificationDate)
+    // A constant to get the number of seconds to refresh the widget after it has been closed
+    let numberOfSecondsFromLastModificationToExpiration =
+      fiveMinutestoRefreshTestValue ? Constants.secondsInFiveMinutes : Constants.secondsInFourWeeks
+
+    let expirationDate = lastModificationDate.advanced(
+      by: numberOfSecondsFromLastModificationToExpiration)
+
+    // Return an Expired entry in the case of passing the limit of refreshing seconds
+    if numberOfSecondsFromLastModificationToExpiration < numberOfSecondsSinceLastModification {
+      return expiredEntry
+    }
+
     guard let data = sharedDefaults.object(forKey: "SuggestedItems") as? Data,
       let unarchiver = try? NSKeyedUnarchiver(forReadingFrom: data)
-    else {
-      return [:]
-    }
+    else { return emptyEntry }
 
     unarchiver.requiresSecureCoding = false
 
@@ -44,19 +104,16 @@
       let mostVisitedSites = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey)
         as? [NSURL: NTPTile]
     else {
-      return [:]
+      return emptyEntry
     }
-    return mostVisitedSites
-  }
 
-  // Return an empty list if the user check from the widget gallery and not the home page.
-  func initializeMostVisitedSites(isPreview: Bool) -> Entry {
-    var entry = Entry(
+    return Entry(
       date: Date(),
-      mostVisitedSites: (isPreview ? [:] : loadMostVisitedSites())
+      mostVisitedSites: mostVisitedSites,
+      isPreview: isPreview,
+      isExpired: false,
+      expirationDate: expirationDate
     )
-    entry.isPreview = isPreview
-    return entry
   }
 
   // Provides a timeline entry that represents the current time and state of a widget.
@@ -64,7 +121,7 @@
     in context: TimelineProviderContext,
     completion: @escaping (Entry) -> Void
   ) {
-    let entry = initializeMostVisitedSites(isPreview: context.isPreview)
+    let entry = loadMostVisitedSitesEntry(isPreview: context.isPreview)
     completion(entry)
   }
 
@@ -73,9 +130,10 @@
     in context: TimelineProviderContext,
     completion: @escaping (Timeline<Entry>) -> Void
   ) {
-    let entry = initializeMostVisitedSites(isPreview: context.isPreview)
+    let entry = loadMostVisitedSitesEntry(isPreview: context.isPreview)
     let entries = [entry]
-    let timeline = Timeline(entries: entries, policy: .never)
+    let timeline = Timeline(
+      entries: entries, policy: entry.expirationDate.map { .after($0) } ?? .never)
     completion(timeline)
   }
 }
@@ -130,6 +188,8 @@
       localized: "IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_OPEN_SHORTCUT_LABEL")
     static let noShortcutsAvailableTitle = String(
       localized: "IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_NO_SHORTCUTS_AVAILABLE_LABEL")
+    static let expiredShortcutsTitle = String(
+      localized: "IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME")
   }
 
   enum Colors {
@@ -193,13 +253,20 @@
     .frame(minWidth: 0, maxWidth: .infinity)
   }
 
-  // Shows the "No shortcuts available" text when the user's delete
-  // all his most visited websites from Chrome App.
+  // Shows the "No shortcuts available" text when the user deletes
+  // all their most visited websites from Chrome App.
   private var zeroVisitedSitesView: some View {
     WebsiteLabel(websiteTitle: Strings.noShortcutsAvailableTitle).padding(.leading, 10)
       .accessibilityLabel(Strings.noShortcutsAvailableTitle)
   }
 
+  // Shows the "Open Chrome to see your most visited sites" text
+  // if Chrome has not been opened for a long time.
+  private var expiredMostVisitedSitesView: some View {
+    WebsiteLabel(websiteTitle: Strings.expiredShortcutsTitle).padding(.leading, 10)
+      .accessibilityLabel(Strings.expiredShortcutsTitle)
+  }
+
   // Shows the shortcut's icon with website's title on the left.
   @ViewBuilder
   private func oneVisitedSitesView(ntpTile: NTPTile) -> some View {
@@ -252,6 +319,8 @@
 
           if entry.isPreview {
             websitesPlaceholder
+          } else if entry.isExpired {
+            expiredMostVisitedSitesView
           } else {
             switch ntpTiles.count {
             case 0:
diff --git a/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings.grd b/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings.grd
index 25c3343..98cee73 100644
--- a/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings.grd
+++ b/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings.grd
@@ -293,6 +293,9 @@
       <message name="IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_NO_SHORTCUTS_AVAILABLE_LABEL" desc="No shortcuts available label for the shortcuts widget [CHAR_LIMIT=70]" meaning="No shortcuts available label for the shortcuts widget [CHAR_LIMIT=70][iOS only]">
           Your most visited sites will show up here.
       </message>
+      <message name="IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME" desc="Message shown in the Shortcuts Widget if Chrome has not been opened for a long time. It invites the user to open Chrome so up-to-date information about most visited sites can be displayed in the widget." meaning="shortcuts expires after some time of not using chrome[iOS only]">
+          Open Chrome to see your most visited sites here.
+      </message>
       <message name="IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_PASSWORDS_DISPLAY_NAME" desc="Name for the Search Passwords widget. [CHAR_LIMIT=30][iOS only]" meaning="String that appears as title in the installation window for the Search Passwords widget. Title-cased.">
         Password Manager
       </message>
diff --git a/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings_grd/IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME.png.sha1 b/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings_grd/IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME.png.sha1
new file mode 100644
index 0000000..6a2df07c
--- /dev/null
+++ b/ios/chrome/widget_kit_extension/strings/ios_widget_kit_extension_strings_grd/IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME.png.sha1
@@ -0,0 +1 @@
+96ed35011ced6dff39e601f3ab74564f74c97480
\ No newline at end of file
diff --git a/ios/chrome/widget_kit_extension/widget_kit_extension_localize_strings_config.plist b/ios/chrome/widget_kit_extension/widget_kit_extension_localize_strings_config.plist
index 343a4c9..6e4fbfc 100644
--- a/ios/chrome/widget_kit_extension/widget_kit_extension_localize_strings_config.plist
+++ b/ios/chrome/widget_kit_extension/widget_kit_extension_localize_strings_config.plist
@@ -47,6 +47,7 @@
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_SEARCH_A11Y_LABEL</string>
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_OPEN_SHORTCUT_LABEL</string>
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_NO_SHORTCUTS_AVAILABLE_LABEL</string>
+				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SHORTCUTS_EXPIRED_OPEN_CHROME</string>
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_PASSWORDS_A11Y_LABEL</string>
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_PASSWORDS_DESCRIPTION</string>
 				<string>IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_PASSWORDS_DISPLAY_NAME</string>
diff --git a/ios_internal b/ios_internal
index 5365862..7d687f5 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 5365862f786acddba08a3b38bee6b278569f086b
+Subproject commit 7d687f5d436610c2d0959561d1a720d72754637c
diff --git a/printing/printing_context_chromeos.h b/printing/printing_context_chromeos.h
index 40940114..67bc0026 100644
--- a/printing/printing_context_chromeos.h
+++ b/printing/printing_context_chromeos.h
@@ -64,8 +64,6 @@
   std::string username_;
 };
 
-// This has the side effect of recording UMA for advanced attributes usage,
-// so only call once per job.
 COMPONENT_EXPORT(PRINTING)
 ScopedIppPtr SettingsToIPPOptions(const PrintSettings& settings,
                                   const gfx::Rect& printable_area_um);
diff --git a/services/video_capture/video_capture_service_impl.cc b/services/video_capture/video_capture_service_impl.cc
index c10dcae..33de526 100644
--- a/services/video_capture/video_capture_service_impl.cc
+++ b/services/video_capture/video_capture_service_impl.cc
@@ -178,9 +178,8 @@
 
     scoped_refptr<viz::ContextProvider> context_provider =
         base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-            std::move(gpu_channel_host), viz_gpu_->GetGpuMemoryBufferManager(),
-            0 /* stream ID */, gpu::SchedulingPriority::kNormal,
-            gpu::kNullSurfaceHandle,
+            std::move(gpu_channel_host), 0 /* stream ID */,
+            gpu::SchedulingPriority::kNormal, gpu::kNullSurfaceHandle,
             GURL(std::string("chrome://gpu/VideoCapture")),
             false /* automatic flushes */, false /* support locking */,
             false /* support grcontext */,
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
index f5d42e16..4d516f5 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -58,7 +58,6 @@
 
 ContextProviderCommandBuffer::ContextProviderCommandBuffer(
     scoped_refptr<gpu::GpuChannelHost> channel,
-    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     int32_t stream_id,
     gpu::SchedulingPriority stream_priority,
     gpu::SurfaceHandle surface_handle,
@@ -81,7 +80,6 @@
       attributes_(attributes),
       context_type_(type),
       channel_(std::move(channel)),
-      gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
       impl_(nullptr),
       buffer_mapper_(buffer_mapper) {
   DCHECK(main_thread_checker_.CalledOnValidThread());
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index 93fd2db..c5fdc66 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -70,7 +70,6 @@
  public:
   ContextProviderCommandBuffer(
       scoped_refptr<gpu::GpuChannelHost> channel,
-      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       int32_t stream_id,
       gpu::SchedulingPriority stream_priority,
       gpu::SurfaceHandle surface_handle,
@@ -150,8 +149,6 @@
   const command_buffer_metrics::ContextType context_type_;
 
   scoped_refptr<gpu::GpuChannelHost> channel_;
-  raw_ptr<gpu::GpuMemoryBufferManager, DanglingUntriaged>
-      gpu_memory_buffer_manager_;
   scoped_refptr<base::SequencedTaskRunner> default_task_runner_;
 
   // |shared_image_interface_| must be torn down after |command_buffer_| to
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e0c6e2042..8e0ff93 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -7628,21 +7628,6 @@
             ]
         }
     ],
-    "HideSettingsSyncPromo": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "HideSettingsSyncPromo"
-                    ]
-                }
-            ]
-        }
-    ],
     "HlsBuiltinPlayer": [
         {
             "platforms": [
@@ -9322,6 +9307,28 @@
             ]
         }
     ],
+    "LayoutNewStickyLogic": [
+        {
+            "platforms": [
+                "android",
+                "android_weblayer",
+                "android_webview",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "LayoutNewStickyLogic"
+                    ]
+                }
+            ]
+        }
+    ],
     "LeakSkiaEventTracerAtExit": [
         {
             "platforms": [
@@ -12378,7 +12385,7 @@
             ]
         }
     ],
-    "PrivacyGuideClank": [
+    "PrivacyGuideAndroid": [
         {
             "platforms": [
                 "android"
diff --git a/third_party/abseil-cpp/BUILD.gn b/third_party/abseil-cpp/BUILD.gn
index cad6a67..03647460 100644
--- a/third_party/abseil-cpp/BUILD.gn
+++ b/third_party/abseil-cpp/BUILD.gn
@@ -237,6 +237,7 @@
         "absl/status:statusor_test",
         "absl/strings:ascii_test",
         "absl/strings:char_formatting_test",
+        "absl/strings:charset_test",
         "absl/strings:cord_buffer_test",
         "absl/strings:cord_data_edge_test",
         "absl/strings:cord_rep_btree_navigator_test",
diff --git a/third_party/abseil-cpp/CMake/AbseilDll.cmake b/third_party/abseil-cpp/CMake/AbseilDll.cmake
index 2ea625c..99973087 100644
--- a/third_party/abseil-cpp/CMake/AbseilDll.cmake
+++ b/third_party/abseil-cpp/CMake/AbseilDll.cmake
@@ -261,6 +261,7 @@
   "strings/ascii.h"
   "strings/charconv.cc"
   "strings/charconv.h"
+  "strings/charset.h"
   "strings/cord.cc"
   "strings/cord.h"
   "strings/cord_analysis.cc"
@@ -325,7 +326,6 @@
   "strings/strip.h"
   "strings/substitute.cc"
   "strings/substitute.h"
-  "strings/internal/char_map.h"
   "strings/internal/escaping.h"
   "strings/internal/escaping.cc"
   "strings/internal/memutil.cc"
@@ -421,11 +421,6 @@
   "types/bad_variant_access.cc"
   "types/bad_variant_access.h"
   "types/compare.h"
-  "types/internal/conformance_aliases.h"
-  "types/internal/conformance_archetype.h"
-  "types/internal/conformance_profile.h"
-  "types/internal/parentheses.h"
-  "types/internal/transform_args.h"
   "types/internal/variant.h"
   "types/optional.h"
   "types/internal/optional.h"
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index f88d92e..8cf5470 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: 7aef7808d6dbe46ab95b37e6c67d1350c1da016b
+Revision: b06ab1f3554eee58fa0eac046ea79f4b572fa502
 Security Critical: yes
 Shipped: yes
 
diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel
index c8f5cdc..7d29d69 100644
--- a/third_party/abseil-cpp/absl/base/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -157,6 +157,8 @@
 
 cc_library(
     name = "core_headers",
+    srcs = [
+    ],
     hdrs = [
         "attributes.h",
         "const_init.h",
diff --git a/third_party/abseil-cpp/absl/base/attributes.h b/third_party/abseil-cpp/absl/base/attributes.h
index a7f279a0..61b79f4 100644
--- a/third_party/abseil-cpp/absl/base/attributes.h
+++ b/third_party/abseil-cpp/absl/base/attributes.h
@@ -747,9 +747,52 @@
 #define ABSL_CONST_INIT
 #endif
 
-// These annotations are not available yet due to fear of breaking code.
-#define ABSL_ATTRIBUTE_PURE_FUNCTION
-#define ABSL_ATTRIBUTE_CONST_FUNCTION
+// ABSL_ATTRIBUTE_PURE_FUNCTION
+//
+// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
+// functions. A function is pure if its return value is only a function of its
+// arguments. The pure attribute prohibits a function from modifying the state
+// of the program that is observable by means other than inspecting the
+// function's return value. Declaring such functions with the pure attribute
+// allows the compiler to avoid emitting some calls in repeated invocations of
+// the function with the same argument values.
+//
+// Example:
+//
+//  ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);
+#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
+#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
+#elif ABSL_HAVE_ATTRIBUTE(pure)
+#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
+#else
+// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since
+// pure functions are useless if its return is ignored.
+#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT
+#endif
+
+// ABSL_ATTRIBUTE_CONST_FUNCTION
+//
+// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const"
+// functions. A const function is similar to a pure function, with one
+// exception: Pure functions may return value that depend on a non-volatile
+// object that isn't provided as a function argument, while the const function
+// is guaranteed to return the same result given the same arguments.
+//
+// Example:
+//
+//  ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);
+#if defined(_MSC_VER) && !defined(__clang__)
+// Put the MSVC case first since MSVC seems to parse const as a C++ keyword.
+#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
+#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const)
+#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]]
+#elif ABSL_HAVE_ATTRIBUTE(const)
+#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const))
+#else
+// Since const functions are more restrictive pure function, we'll fallback to a
+// pure function if the const attribute is not handled.
+#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
+#endif
 
 // ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
 // parameter or implicit object parameter is retained by the return value of the
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
index f4cf836..4bbb85f 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -1990,17 +1990,6 @@
     common().set_reservation_size(0);
   }
 
-  inline void destroy_slots() {
-    const size_t cap = capacity();
-    const ctrl_t* ctrl = control();
-    slot_type* slot = slot_array();
-    for (size_t i = 0; i != cap; ++i) {
-      if (IsFull(ctrl[i])) {
-        PolicyTraits::destroy(&alloc_ref(), slot + i);
-      }
-    }
-  }
-
   // This overload kicks in when the argument is an rvalue of insertable and
   // decomposable type other than init_type.
   //
@@ -2538,6 +2527,17 @@
     slot_type&& slot;
   };
 
+  inline void destroy_slots() {
+    const size_t cap = capacity();
+    const ctrl_t* ctrl = control();
+    slot_type* slot = slot_array();
+    for (size_t i = 0; i != cap; ++i) {
+      if (IsFull(ctrl[i])) {
+        PolicyTraits::destroy(&alloc_ref(), slot + i);
+      }
+    }
+  }
+
   // Erases, but does not destroy, the value pointed to by `it`.
   //
   // This merely updates the pertinent control byte. This can be used in
diff --git a/third_party/abseil-cpp/absl/crc/internal/cpu_detect.cc b/third_party/abseil-cpp/absl/crc/internal/cpu_detect.cc
index 83838085..8f668e3 100644
--- a/third_party/abseil-cpp/absl/crc/internal/cpu_detect.cc
+++ b/third_party/abseil-cpp/absl/crc/internal/cpu_detect.cc
@@ -189,8 +189,14 @@
       break;
     case 0x19:
       switch (model_num) {
+        case 0x0:  // Stepping Ax
         case 0x1:  // Stepping B0
           return CpuType::kAmdMilan;
+        case 0x10:  // Stepping A0
+        case 0x11:  // Stepping B0
+          return CpuType::kAmdGenoa;
+        case 0x44:  // Stepping A0
+          return CpuType::kAmdRyzenV3000;
         default:
           return CpuType::kUnknown;
       }
diff --git a/third_party/abseil-cpp/absl/crc/internal/cpu_detect.h b/third_party/abseil-cpp/absl/crc/internal/cpu_detect.h
index 6054f69..945379f51 100644
--- a/third_party/abseil-cpp/absl/crc/internal/cpu_detect.h
+++ b/third_party/abseil-cpp/absl/crc/internal/cpu_detect.h
@@ -29,6 +29,8 @@
   kAmdRome,
   kAmdNaples,
   kAmdMilan,
+  kAmdGenoa,
+  kAmdRyzenV3000,
   kIntelCascadelakeXeon,
   kIntelSkylakeXeon,
   kIntelBroadwell,
diff --git a/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc b/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
index c39b061..c984cf9 100644
--- a/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
+++ b/third_party/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
@@ -348,9 +348,11 @@
   // Get the underlying architecture.
   CpuType cpu_type = GetCpuType();
   switch (cpu_type) {
-    case CpuType::kUnknown:
     case CpuType::kAmdRome:
     case CpuType::kAmdNaples:
+    case CpuType::kAmdMilan:
+    case CpuType::kAmdGenoa:
+    case CpuType::kAmdRyzenV3000:
     case CpuType::kIntelCascadelakeXeon:
     case CpuType::kIntelSkylakeXeon:
     case CpuType::kIntelSkylake:
@@ -386,6 +388,9 @@
     // strided access to each region, and do the right thing.
     case CpuType::kAmdRome:
     case CpuType::kAmdNaples:
+    case CpuType::kAmdMilan:
+    case CpuType::kAmdGenoa:
+    case CpuType::kAmdRyzenV3000:
       return {
           /*.temporal=*/new AcceleratedCrcMemcpyEngine<1, 2>(),
           /*.non_temporal=*/new CrcNonTemporalMemcpyAVXEngine(),
diff --git a/third_party/abseil-cpp/absl/strings/BUILD.bazel b/third_party/abseil-cpp/absl/strings/BUILD.bazel
index e3b8af4..a858d0b2 100644
--- a/third_party/abseil-cpp/absl/strings/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/strings/BUILD.bazel
@@ -92,6 +92,7 @@
         "string_view.h",
     ],
     deps = [
+        ":charset",
         ":internal",
         ":string_view",
         "//absl/base",
@@ -115,7 +116,6 @@
         "internal/utf8.cc",
     ],
     hdrs = [
-        "internal/char_map.h",
         "internal/escaping.h",
         "internal/ostringstream.h",
         "internal/resize_uninitialized.h",
@@ -307,6 +307,50 @@
     ],
 )
 
+cc_test(
+    name = "charset_benchmark",
+    size = "small",
+    srcs = [
+        "charset_benchmark.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    tags = [
+        "benchmark",
+    ],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":charset",
+        "//absl/log:check",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_library(
+    name = "charset",
+    hdrs = [
+        "charset.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":string_view",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_test(
+    name = "charset_test",
+    size = "small",
+    srcs = ["charset_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":charset",
+        ":strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 cc_library(
     name = "cord_internal",
     srcs = [
@@ -1087,27 +1131,6 @@
 )
 
 cc_test(
-    name = "char_map_test",
-    srcs = ["internal/char_map_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    deps = [
-        ":internal",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "char_map_benchmark",
-    srcs = ["internal/char_map_benchmark.cc"],
-    copts = ABSL_TEST_COPTS,
-    tags = ["benchmark"],
-    deps = [
-        ":internal",
-        "@com_github_google_benchmark//:benchmark_main",
-    ],
-)
-
-cc_test(
     name = "charconv_test",
     srcs = ["charconv_test.cc"],
     copts = ABSL_TEST_COPTS,
diff --git a/third_party/abseil-cpp/absl/strings/BUILD.gn b/third_party/abseil-cpp/absl/strings/BUILD.gn
index 7519c8e..99b7c5a 100644
--- a/third_party/abseil-cpp/absl/strings/BUILD.gn
+++ b/third_party/abseil-cpp/absl/strings/BUILD.gn
@@ -6,12 +6,8 @@
 import("//third_party/abseil-cpp/absl.gni")
 
 absl_source_set("string_view") {
-  sources = [
-    "string_view.cc",
-  ]
-  public = [
-    "string_view.h",
-  ]
+  sources = [ "string_view.cc" ]
+  public = [ "string_view.h" ]
   deps = [
     "//third_party/abseil-cpp/absl/base",
     "//third_party/abseil-cpp/absl/base:config",
@@ -69,6 +65,7 @@
     ":string_view",
   ]
   deps = [
+    ":charset",
     ":internal",
     ":string_view",
     "//third_party/abseil-cpp/absl/base",
@@ -91,7 +88,6 @@
     "internal/utf8.cc",
   ]
   public = [
-    "internal/char_map.h",
     "internal/escaping.h",
     "internal/ostringstream.h",
     "internal/resize_uninitialized.h",
@@ -132,8 +128,8 @@
   ]
   visibility = [ ":*" ]
   deps = [
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
     "//third_party/abseil-cpp/absl/container:inlined_vector",
@@ -148,6 +144,22 @@
   ]
 }
 
+absl_source_set("charset") {
+  public = [ "charset.h" ]
+  deps = [
+    ":string_view",
+    "//third_party/abseil-cpp/absl/base:core_headers",
+  ]
+}
+
+absl_test("charset_test") {
+  sources = [ "charset_test.cc" ]
+  deps = [
+    ":charset",
+    ":strings",
+  ]
+}
+
 absl_source_set("cord_internal") {
   sources = [
     "internal/cord_internal.cc",
@@ -172,8 +184,8 @@
   ]
   visibility = [ ":*" ]
   deps = [
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base:base_internal",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
@@ -206,8 +218,8 @@
   deps = [
     ":cord_internal",
     ":cord_rep_test_util",
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
     "//third_party/abseil-cpp/absl/cleanup",
@@ -271,8 +283,8 @@
     ":cordz_update_scope",
     ":cordz_update_tracker",
     ":internal",
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
@@ -544,8 +556,8 @@
     ":cordz_statistics",
     ":cordz_test_helpers",
     ":cordz_update_tracker",
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
@@ -598,8 +610,8 @@
   deps = [
     ":cord_internal",
     ":cord_rep_test_util",
-    ":strings",
     ":string_view",
+    ":strings",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
   ]
diff --git a/third_party/abseil-cpp/absl/strings/CMakeLists.txt b/third_party/abseil-cpp/absl/strings/CMakeLists.txt
index 0e58867..27e7ce4f 100644
--- a/third_party/abseil-cpp/absl/strings/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/strings/CMakeLists.txt
@@ -78,6 +78,7 @@
     absl::strings_internal
     absl::base
     absl::bits
+    absl::charset
     absl::config
     absl::core_headers
     absl::endian
@@ -89,12 +90,24 @@
   PUBLIC
 )
 
+absl_cc_library(
+  NAME
+    charset
+  HDRS
+    charset.h
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::string_view
+  PUBLIC
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
     strings_internal
   HDRS
-    "internal/char_map.h"
     "internal/escaping.cc"
     "internal/escaping.h"
     "internal/ostringstream.h"
@@ -357,13 +370,13 @@
 
 absl_cc_test(
   NAME
-    char_map_test
+    charset_test
   SRCS
-    "internal/char_map_test.cc"
+    "charset_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
-    absl::strings_internal
+    absl::strings
     GTest::gmock_main
 )
 
diff --git a/third_party/abseil-cpp/absl/strings/charset.h b/third_party/abseil-cpp/absl/strings/charset.h
new file mode 100644
index 0000000..ff4e81a
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/charset.h
@@ -0,0 +1,164 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: charset.h
+// -----------------------------------------------------------------------------
+//
+// This file contains absl::CharSet, a fast, bit-vector set of 8-bit unsigned
+// characters.
+//
+// Instances can be initialized as constexpr constants. For example:
+//
+//   constexpr absl::CharSet kJustX = absl::CharSet::Char('x');
+//   constexpr absl::CharSet kMySymbols = absl::CharSet("$@!");
+//   constexpr absl::CharSet kLetters = absl::CharSet::Range('a', 'z');
+//
+// Multiple instances can be combined that still forms a constexpr expression.
+// For example:
+//
+//   constexpr absl::CharSet kLettersAndNumbers =
+//       absl::CharSet::Range('a', 'z') | absl::CharSet::Range('0', '9');
+//
+// Several pre-defined character classes are available that mirror the methods
+// from <cctype>. For example:
+//
+//   constexpr absl::CharSet kLettersAndWhitespace =
+//       absl::CharSet::AsciiAlphabet() | absl::CharSet::AsciiWhitespace();
+//
+// To check membership, use the .contains method, e.g.
+//
+//   absl::CharSet hex_letters("abcdef");
+//   hex_letters.contains('a');  // true
+//   hex_letters.contains('g');  // false
+
+#ifndef ABSL_STRINGS_CHARSET_H_
+#define ABSL_STRINGS_CHARSET_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+
+class CharSet {
+ public:
+  constexpr CharSet() : m_() {}
+
+  // Initializes with a given string_view.
+  constexpr explicit CharSet(absl::string_view str) : m_() {
+    for (char c : str) {
+      SetChar(static_cast<unsigned char>(c));
+    }
+  }
+
+  constexpr bool contains(char c) const {
+    return ((m_[static_cast<unsigned char>(c) / 64] >>
+             (static_cast<unsigned char>(c) % 64)) &
+            0x1) == 0x1;
+  }
+
+  constexpr bool empty() const {
+    for (uint64_t c : m_) {
+      if (c != 0) return false;
+    }
+    return true;
+  }
+
+  // Containing only a single specified char.
+  static constexpr CharSet Char(char x) {
+    return CharSet(CharMaskForWord(x, 0), CharMaskForWord(x, 1),
+                   CharMaskForWord(x, 2), CharMaskForWord(x, 3));
+  }
+
+  // Containing all the chars in the closed interval [lo,hi].
+  static constexpr CharSet Range(char lo, char hi) {
+    return CharSet(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1),
+                   RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3));
+  }
+
+  friend constexpr CharSet operator&(const CharSet& a, const CharSet& b) {
+    return CharSet(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2],
+                   a.m_[3] & b.m_[3]);
+  }
+
+  friend constexpr CharSet operator|(const CharSet& a, const CharSet& b) {
+    return CharSet(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2],
+                   a.m_[3] | b.m_[3]);
+  }
+
+  friend constexpr CharSet operator~(const CharSet& a) {
+    return CharSet(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]);
+  }
+
+  // Mirrors the char-classifying predicates in <cctype>.
+  static constexpr CharSet AsciiUppercase() { return CharSet::Range('A', 'Z'); }
+  static constexpr CharSet AsciiLowercase() { return CharSet::Range('a', 'z'); }
+  static constexpr CharSet AsciiDigits() { return CharSet::Range('0', '9'); }
+  static constexpr CharSet AsciiAlphabet() {
+    return AsciiLowercase() | AsciiUppercase();
+  }
+  static constexpr CharSet AsciiAlphanumerics() {
+    return AsciiDigits() | AsciiAlphabet();
+  }
+  static constexpr CharSet AsciiHexDigits() {
+    return AsciiDigits() | CharSet::Range('A', 'F') | CharSet::Range('a', 'f');
+  }
+  static constexpr CharSet AsciiPrintable() {
+    return CharSet::Range(0x20, 0x7e);
+  }
+  static constexpr CharSet AsciiWhitespace() { return CharSet("\t\n\v\f\r "); }
+  static constexpr CharSet AsciiPunctuation() {
+    return AsciiPrintable() & ~AsciiWhitespace() & ~AsciiAlphanumerics();
+  }
+
+ private:
+  constexpr CharSet(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)
+      : m_{b0, b1, b2, b3} {}
+
+  static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) {
+    return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) &
+           ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word);
+  }
+
+  // All the chars in the specified word of the range [0, upper).
+  static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper,
+                                                     uint64_t word) {
+    return (upper <= 64 * word) ? 0
+           : (upper >= 64 * (word + 1))
+               ? ~static_cast<uint64_t>(0)
+               : (~static_cast<uint64_t>(0) >> (64 - upper % 64));
+  }
+
+  static constexpr uint64_t CharMaskForWord(char x, uint64_t word) {
+    return (static_cast<unsigned char>(x) / 64 == word)
+               ? (static_cast<uint64_t>(1)
+                  << (static_cast<unsigned char>(x) % 64))
+               : 0;
+  }
+
+  constexpr void SetChar(unsigned char c) {
+    m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64);
+  }
+
+  uint64_t m_[4];
+};
+
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_CHARSET_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/char_map_benchmark.cc b/third_party/abseil-cpp/absl/strings/charset_benchmark.cc
similarity index 71%
rename from third_party/abseil-cpp/absl/strings/internal/char_map_benchmark.cc
rename to third_party/abseil-cpp/absl/strings/charset_benchmark.cc
index 5cef967..bf7ae56 100644
--- a/third_party/abseil-cpp/absl/strings/internal/char_map_benchmark.cc
+++ b/third_party/abseil-cpp/absl/strings/charset_benchmark.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,30 +12,30 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/internal/char_map.h"
-
 #include <cstdint>
 
 #include "benchmark/benchmark.h"
+#include "absl/log/check.h"
+#include "absl/strings/charset.h"
 
 namespace {
 
-absl::strings_internal::Charmap MakeBenchmarkMap() {
-  absl::strings_internal::Charmap m;
+absl::CharSet MakeBenchmarkMap() {
+  absl::CharSet m;
   uint32_t x[] = {0x0, 0x1, 0x2, 0x3, 0xf, 0xe, 0xd, 0xc};
   for (uint32_t& t : x) t *= static_cast<uint32_t>(0x11111111UL);
   for (uint32_t i = 0; i < 256; ++i) {
-    if ((x[i / 32] >> (i % 32)) & 1)
-      m = m | absl::strings_internal::Charmap::Char(i);
+    if ((x[i / 32] >> (i % 32)) & 1) m = m | absl::CharSet::Char(i);
   }
   return m;
 }
 
 // Micro-benchmark for Charmap::contains.
-void BM_Contains(benchmark::State& state) {
+static void BM_Contains(benchmark::State& state) {
   // Loop-body replicated 10 times to increase time per iteration.
   // Argument continuously changed to avoid generating common subexpressions.
-  const absl::strings_internal::Charmap benchmark_map = MakeBenchmarkMap();
+  // Final CHECK used to discourage unwanted optimization.
+  const absl::CharSet benchmark_map = MakeBenchmarkMap();
   unsigned char c = 0;
   int ops = 0;
   for (auto _ : state) {
@@ -50,12 +50,8 @@
     ops += benchmark_map.contains(c++);
     ops += benchmark_map.contains(c++);
   }
-  benchmark::DoNotOptimize(ops);
+  CHECK_NE(ops, -1);
 }
 BENCHMARK(BM_Contains);
 
-// We don't bother benchmarking Charmap::IsZero or Charmap::IntersectsWith;
-// their running time is data-dependent and it is not worth characterizing
-// "typical" data.
-
 }  // namespace
diff --git a/third_party/abseil-cpp/absl/strings/charset_test.cc b/third_party/abseil-cpp/absl/strings/charset_test.cc
new file mode 100644
index 0000000..fff943ae
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/charset_test.cc
@@ -0,0 +1,181 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/charset.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+
+constexpr absl::CharSet everything_map = ~absl::CharSet();
+constexpr absl::CharSet nothing_map = absl::CharSet();
+
+TEST(Charmap, AllTests) {
+  const absl::CharSet also_nothing_map("");
+  EXPECT_TRUE(everything_map.contains('\0'));
+  EXPECT_FALSE(nothing_map.contains('\0'));
+  EXPECT_FALSE(also_nothing_map.contains('\0'));
+  for (unsigned char ch = 1; ch != 0; ++ch) {
+    SCOPED_TRACE(ch);
+    EXPECT_TRUE(everything_map.contains(ch));
+    EXPECT_FALSE(nothing_map.contains(ch));
+    EXPECT_FALSE(also_nothing_map.contains(ch));
+  }
+
+  const absl::CharSet symbols(absl::string_view("&@#@^!@?", 5));
+  EXPECT_TRUE(symbols.contains('&'));
+  EXPECT_TRUE(symbols.contains('@'));
+  EXPECT_TRUE(symbols.contains('#'));
+  EXPECT_TRUE(symbols.contains('^'));
+  EXPECT_FALSE(symbols.contains('!'));
+  EXPECT_FALSE(symbols.contains('?'));
+  int cnt = 0;
+  for (unsigned char ch = 1; ch != 0; ++ch) cnt += symbols.contains(ch);
+  EXPECT_EQ(cnt, 4);
+
+  const absl::CharSet lets(absl::string_view("^abcde", 3));
+  const absl::CharSet lets2(absl::string_view("fghij\0klmnop", 10));
+  const absl::CharSet lets3("fghij\0klmnop");
+  EXPECT_TRUE(lets2.contains('k'));
+  EXPECT_FALSE(lets3.contains('k'));
+
+  EXPECT_FALSE((symbols & lets).empty());
+  EXPECT_TRUE((lets2 & lets).empty());
+  EXPECT_FALSE((lets & symbols).empty());
+  EXPECT_TRUE((lets & lets2).empty());
+
+  EXPECT_TRUE(nothing_map.empty());
+  EXPECT_FALSE(lets.empty());
+}
+
+std::string Members(const absl::CharSet& m) {
+  std::string r;
+  for (size_t i = 0; i < 256; ++i)
+    if (m.contains(i)) r.push_back(i);
+  return r;
+}
+
+std::string ClosedRangeString(unsigned char lo, unsigned char hi) {
+  // Don't depend on lo<hi. Just increment until lo==hi.
+  std::string s;
+  while (true) {
+    s.push_back(lo);
+    if (lo == hi) break;
+    ++lo;
+  }
+  return s;
+}
+
+TEST(Charmap, Constexpr) {
+  constexpr absl::CharSet kEmpty = absl::CharSet();
+  EXPECT_EQ(Members(kEmpty), "");
+  constexpr absl::CharSet kA = absl::CharSet::Char('A');
+  EXPECT_EQ(Members(kA), "A");
+  constexpr absl::CharSet kAZ = absl::CharSet::Range('A', 'Z');
+  EXPECT_EQ(Members(kAZ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+  constexpr absl::CharSet kIdentifier =
+      absl::CharSet::Range('0', '9') | absl::CharSet::Range('A', 'Z') |
+      absl::CharSet::Range('a', 'z') | absl::CharSet::Char('_');
+  EXPECT_EQ(Members(kIdentifier),
+            "0123456789"
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+            "_"
+            "abcdefghijklmnopqrstuvwxyz");
+  constexpr absl::CharSet kAll = ~absl::CharSet();
+  for (size_t i = 0; i < 256; ++i) {
+    SCOPED_TRACE(i);
+    EXPECT_TRUE(kAll.contains(i));
+  }
+  constexpr absl::CharSet kHello = absl::CharSet("Hello, world!");
+  EXPECT_EQ(Members(kHello), " !,Hdelorw");
+
+  // test negation and intersection
+  constexpr absl::CharSet kABC =
+      absl::CharSet::Range('A', 'Z') & ~absl::CharSet::Range('D', 'Z');
+  EXPECT_EQ(Members(kABC), "ABC");
+
+  // contains
+  constexpr bool kContainsA = absl::CharSet("abc").contains('a');
+  EXPECT_TRUE(kContainsA);
+  constexpr bool kContainsD = absl::CharSet("abc").contains('d');
+  EXPECT_FALSE(kContainsD);
+
+  // empty
+  constexpr bool kEmptyIsEmpty = absl::CharSet().empty();
+  EXPECT_TRUE(kEmptyIsEmpty);
+  constexpr bool kNotEmptyIsEmpty = absl::CharSet("abc").empty();
+  EXPECT_FALSE(kNotEmptyIsEmpty);
+}
+
+TEST(Charmap, Range) {
+  // Exhaustive testing takes too long, so test some of the boundaries that
+  // are perhaps going to cause trouble.
+  std::vector<size_t> poi = {0,   1,   2,   3,   4,   7,   8,   9,  15,
+                             16,  17,  30,  31,  32,  33,  63,  64, 65,
+                             127, 128, 129, 223, 224, 225, 254, 255};
+  for (auto lo = poi.begin(); lo != poi.end(); ++lo) {
+    SCOPED_TRACE(*lo);
+    for (auto hi = lo; hi != poi.end(); ++hi) {
+      SCOPED_TRACE(*hi);
+      EXPECT_EQ(Members(absl::CharSet::Range(*lo, *hi)),
+                ClosedRangeString(*lo, *hi));
+    }
+  }
+}
+
+TEST(Charmap, NullByteWithStringView) {
+  char characters[5] = {'a', 'b', '\0', 'd', 'x'};
+  absl::string_view view(characters, 5);
+  absl::CharSet tester(view);
+  EXPECT_TRUE(tester.contains('a'));
+  EXPECT_TRUE(tester.contains('b'));
+  EXPECT_TRUE(tester.contains('\0'));
+  EXPECT_TRUE(tester.contains('d'));
+  EXPECT_TRUE(tester.contains('x'));
+  EXPECT_FALSE(tester.contains('c'));
+}
+
+TEST(CharmapCtype, Match) {
+  for (int c = 0; c < 256; ++c) {
+    SCOPED_TRACE(c);
+    SCOPED_TRACE(static_cast<char>(c));
+    EXPECT_EQ(absl::ascii_isupper(c),
+              absl::CharSet::AsciiUppercase().contains(c));
+    EXPECT_EQ(absl::ascii_islower(c),
+              absl::CharSet::AsciiLowercase().contains(c));
+    EXPECT_EQ(absl::ascii_isdigit(c), absl::CharSet::AsciiDigits().contains(c));
+    EXPECT_EQ(absl::ascii_isalpha(c),
+              absl::CharSet::AsciiAlphabet().contains(c));
+    EXPECT_EQ(absl::ascii_isalnum(c),
+              absl::CharSet::AsciiAlphanumerics().contains(c));
+    EXPECT_EQ(absl::ascii_isxdigit(c),
+              absl::CharSet::AsciiHexDigits().contains(c));
+    EXPECT_EQ(absl::ascii_isprint(c),
+              absl::CharSet::AsciiPrintable().contains(c));
+    EXPECT_EQ(absl::ascii_isspace(c),
+              absl::CharSet::AsciiWhitespace().contains(c));
+    EXPECT_EQ(absl::ascii_ispunct(c),
+              absl::CharSet::AsciiPunctuation().contains(c));
+  }
+}
+
+}  // namespace
diff --git a/third_party/abseil-cpp/absl/strings/escaping.cc b/third_party/abseil-cpp/absl/strings/escaping.cc
index 5bf0223..1c0eac4 100644
--- a/third_party/abseil-cpp/absl/strings/escaping.cc
+++ b/third_party/abseil-cpp/absl/strings/escaping.cc
@@ -26,7 +26,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/unaligned_access.h"
 #include "absl/strings/ascii.h"
-#include "absl/strings/internal/char_map.h"
+#include "absl/strings/charset.h"
 #include "absl/strings/internal/escaping.h"
 #include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/internal/utf8.h"
diff --git a/third_party/abseil-cpp/absl/strings/internal/char_map.h b/third_party/abseil-cpp/absl/strings/internal/char_map.h
deleted file mode 100644
index 70a90343..0000000
--- a/third_party/abseil-cpp/absl/strings/internal/char_map.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// Character Map Class
-//
-// A fast, bit-vector map for 8-bit unsigned characters.
-// This class is useful for non-character purposes as well.
-
-#ifndef ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
-#define ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace strings_internal {
-
-class Charmap {
- public:
-  constexpr Charmap() : m_() {}
-
-  // Initializes with a given char*.  Note that NUL is not treated as
-  // a terminator, but rather a char to be flicked.
-  Charmap(const char* str, int len) : m_() {
-    while (len--) SetChar(*str++);
-  }
-
-  // Initializes with a given char*.  NUL is treated as a terminator
-  // and will not be in the charmap.
-  explicit Charmap(const char* str) : m_() {
-    while (*str) SetChar(*str++);
-  }
-
-  constexpr bool contains(unsigned char c) const {
-    return (m_[c / 64] >> (c % 64)) & 0x1;
-  }
-
-  // Returns true if and only if a character exists in both maps.
-  bool IntersectsWith(const Charmap& c) const {
-    for (size_t i = 0; i < ABSL_ARRAYSIZE(m_); ++i) {
-      if ((m_[i] & c.m_[i]) != 0) return true;
-    }
-    return false;
-  }
-
-  bool IsZero() const {
-    for (uint64_t c : m_) {
-      if (c != 0) return false;
-    }
-    return true;
-  }
-
-  // Containing only a single specified char.
-  static constexpr Charmap Char(char x) {
-    return Charmap(CharMaskForWord(x, 0), CharMaskForWord(x, 1),
-                   CharMaskForWord(x, 2), CharMaskForWord(x, 3));
-  }
-
-  // Containing all the chars in the C-string 's'.
-  static constexpr Charmap FromString(const char* s) {
-    Charmap ret;
-    while (*s) ret = ret | Char(*s++);
-    return ret;
-  }
-
-  // Containing all the chars in the closed interval [lo,hi].
-  static constexpr Charmap Range(char lo, char hi) {
-    return Charmap(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1),
-                   RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3));
-  }
-
-  friend constexpr Charmap operator&(const Charmap& a, const Charmap& b) {
-    return Charmap(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2],
-                   a.m_[3] & b.m_[3]);
-  }
-
-  friend constexpr Charmap operator|(const Charmap& a, const Charmap& b) {
-    return Charmap(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2],
-                   a.m_[3] | b.m_[3]);
-  }
-
-  friend constexpr Charmap operator~(const Charmap& a) {
-    return Charmap(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]);
-  }
-
- private:
-  constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)
-      : m_{b0, b1, b2, b3} {}
-
-  static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) {
-    return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) &
-           ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word);
-  }
-
-  // All the chars in the specified word of the range [0, upper).
-  static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper,
-                                                     uint64_t word) {
-    return (upper <= 64 * word)
-               ? 0
-               : (upper >= 64 * (word + 1))
-                     ? ~static_cast<uint64_t>(0)
-                     : (~static_cast<uint64_t>(0) >> (64 - upper % 64));
-  }
-
-  static constexpr uint64_t CharMaskForWord(char x, uint64_t word) {
-    const auto unsigned_x = static_cast<unsigned char>(x);
-    return (unsigned_x / 64 == word)
-               ? (static_cast<uint64_t>(1) << (unsigned_x % 64))
-               : 0;
-  }
-
-  void SetChar(char c) {
-    const auto unsigned_c = static_cast<unsigned char>(c);
-    m_[unsigned_c / 64] |= static_cast<uint64_t>(1) << (unsigned_c % 64);
-  }
-
-  uint64_t m_[4];
-};
-
-// Mirror the char-classifying predicates in <cctype>
-constexpr Charmap UpperCharmap() { return Charmap::Range('A', 'Z'); }
-constexpr Charmap LowerCharmap() { return Charmap::Range('a', 'z'); }
-constexpr Charmap DigitCharmap() { return Charmap::Range('0', '9'); }
-constexpr Charmap AlphaCharmap() { return LowerCharmap() | UpperCharmap(); }
-constexpr Charmap AlnumCharmap() { return DigitCharmap() | AlphaCharmap(); }
-constexpr Charmap XDigitCharmap() {
-  return DigitCharmap() | Charmap::Range('A', 'F') | Charmap::Range('a', 'f');
-}
-constexpr Charmap PrintCharmap() { return Charmap::Range(0x20, 0x7e); }
-constexpr Charmap SpaceCharmap() { return Charmap::FromString("\t\n\v\f\r "); }
-constexpr Charmap CntrlCharmap() {
-  return Charmap::Range(0, 0x7f) & ~PrintCharmap();
-}
-constexpr Charmap BlankCharmap() { return Charmap::FromString("\t "); }
-constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); }
-constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
-
-}  // namespace strings_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/char_map_test.cc b/third_party/abseil-cpp/absl/strings/internal/char_map_test.cc
deleted file mode 100644
index d3306241..0000000
--- a/third_party/abseil-cpp/absl/strings/internal/char_map_test.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/strings/internal/char_map.h"
-
-#include <cctype>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace {
-
-constexpr absl::strings_internal::Charmap everything_map =
-    ~absl::strings_internal::Charmap();
-constexpr absl::strings_internal::Charmap nothing_map{};
-
-TEST(Charmap, AllTests) {
-  const absl::strings_internal::Charmap also_nothing_map("", 0);
-  ASSERT_TRUE(everything_map.contains('\0'));
-  ASSERT_TRUE(!nothing_map.contains('\0'));
-  ASSERT_TRUE(!also_nothing_map.contains('\0'));
-  for (unsigned char ch = 1; ch != 0; ++ch) {
-    ASSERT_TRUE(everything_map.contains(ch));
-    ASSERT_TRUE(!nothing_map.contains(ch));
-    ASSERT_TRUE(!also_nothing_map.contains(ch));
-  }
-
-  const absl::strings_internal::Charmap symbols("&@#@^!@?", 5);
-  ASSERT_TRUE(symbols.contains('&'));
-  ASSERT_TRUE(symbols.contains('@'));
-  ASSERT_TRUE(symbols.contains('#'));
-  ASSERT_TRUE(symbols.contains('^'));
-  ASSERT_TRUE(!symbols.contains('!'));
-  ASSERT_TRUE(!symbols.contains('?'));
-  int cnt = 0;
-  for (unsigned char ch = 1; ch != 0; ++ch)
-    cnt += symbols.contains(ch);
-  ASSERT_EQ(cnt, 4);
-
-  const absl::strings_internal::Charmap lets("^abcde", 3);
-  const absl::strings_internal::Charmap lets2("fghij\0klmnop", 10);
-  const absl::strings_internal::Charmap lets3("fghij\0klmnop");
-  ASSERT_TRUE(lets2.contains('k'));
-  ASSERT_TRUE(!lets3.contains('k'));
-
-  ASSERT_TRUE(symbols.IntersectsWith(lets));
-  ASSERT_TRUE(!lets2.IntersectsWith(lets));
-  ASSERT_TRUE(lets.IntersectsWith(symbols));
-  ASSERT_TRUE(!lets.IntersectsWith(lets2));
-
-  ASSERT_TRUE(nothing_map.IsZero());
-  ASSERT_TRUE(!lets.IsZero());
-}
-
-namespace {
-std::string Members(const absl::strings_internal::Charmap& m) {
-  std::string r;
-  for (size_t i = 0; i < 256; ++i)
-    if (m.contains(i)) r.push_back(i);
-  return r;
-}
-
-std::string ClosedRangeString(unsigned char lo, unsigned char hi) {
-  // Don't depend on lo<hi. Just increment until lo==hi.
-  std::string s;
-  while (true) {
-    s.push_back(lo);
-    if (lo == hi) break;
-    ++lo;
-  }
-  return s;
-}
-
-}  // namespace
-
-TEST(Charmap, Constexpr) {
-  constexpr absl::strings_internal::Charmap kEmpty = nothing_map;
-  EXPECT_THAT(Members(kEmpty), "");
-  constexpr absl::strings_internal::Charmap kA =
-      absl::strings_internal::Charmap::Char('A');
-  EXPECT_THAT(Members(kA), "A");
-  constexpr absl::strings_internal::Charmap kAZ =
-      absl::strings_internal::Charmap::Range('A', 'Z');
-  EXPECT_THAT(Members(kAZ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-  constexpr absl::strings_internal::Charmap kIdentifier =
-      absl::strings_internal::Charmap::Range('0', '9') |
-      absl::strings_internal::Charmap::Range('A', 'Z') |
-      absl::strings_internal::Charmap::Range('a', 'z') |
-      absl::strings_internal::Charmap::Char('_');
-  EXPECT_THAT(Members(kIdentifier),
-              "0123456789"
-              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-              "_"
-              "abcdefghijklmnopqrstuvwxyz");
-  constexpr absl::strings_internal::Charmap kAll = everything_map;
-  for (size_t i = 0; i < 256; ++i) {
-    EXPECT_TRUE(kAll.contains(i)) << i;
-  }
-  constexpr absl::strings_internal::Charmap kHello =
-      absl::strings_internal::Charmap::FromString("Hello, world!");
-  EXPECT_THAT(Members(kHello), " !,Hdelorw");
-
-  // test negation and intersection
-  constexpr absl::strings_internal::Charmap kABC =
-      absl::strings_internal::Charmap::Range('A', 'Z') &
-      ~absl::strings_internal::Charmap::Range('D', 'Z');
-  EXPECT_THAT(Members(kABC), "ABC");
-}
-
-TEST(Charmap, Range) {
-  // Exhaustive testing takes too long, so test some of the boundaries that
-  // are perhaps going to cause trouble.
-  std::vector<size_t> poi = {0,   1,   2,   3,   4,   7,   8,   9,  15,
-                             16,  17,  30,  31,  32,  33,  63,  64, 65,
-                             127, 128, 129, 223, 224, 225, 254, 255};
-  for (auto lo = poi.begin(); lo != poi.end(); ++lo) {
-    SCOPED_TRACE(*lo);
-    for (auto hi = lo; hi != poi.end(); ++hi) {
-      SCOPED_TRACE(*hi);
-      EXPECT_THAT(Members(absl::strings_internal::Charmap::Range(*lo, *hi)),
-                  ClosedRangeString(*lo, *hi));
-    }
-  }
-}
-
-bool AsBool(int x) { return static_cast<bool>(x); }
-
-TEST(CharmapCtype, Match) {
-  for (int c = 0; c < 256; ++c) {
-    SCOPED_TRACE(c);
-    SCOPED_TRACE(static_cast<char>(c));
-    EXPECT_EQ(AsBool(std::isupper(c)),
-              absl::strings_internal::UpperCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::islower(c)),
-              absl::strings_internal::LowerCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isdigit(c)),
-              absl::strings_internal::DigitCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isalpha(c)),
-              absl::strings_internal::AlphaCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isalnum(c)),
-              absl::strings_internal::AlnumCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isxdigit(c)),
-              absl::strings_internal::XDigitCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isprint(c)),
-              absl::strings_internal::PrintCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isspace(c)),
-              absl::strings_internal::SpaceCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::iscntrl(c)),
-              absl::strings_internal::CntrlCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isblank(c)),
-              absl::strings_internal::BlankCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::isgraph(c)),
-              absl::strings_internal::GraphCharmap().contains(c));
-    EXPECT_EQ(AsBool(std::ispunct(c)),
-              absl::strings_internal::PunctCharmap().contains(c));
-  }
-}
-
-}  // namespace
diff --git a/third_party/abseil-cpp/absl/strings/numbers.cc b/third_party/abseil-cpp/absl/strings/numbers.cc
index 5d13f10..c4f21030 100644
--- a/third_party/abseil-cpp/absl/strings/numbers.cc
+++ b/third_party/abseil-cpp/absl/strings/numbers.cc
@@ -168,10 +168,9 @@
 // Encode functions write the ASCII output of input `n` to `out_str`.
 inline char* EncodeHundred(uint32_t n, char* out_str) {
   int num_digits = static_cast<int>(n - 10) >> 8;
-  uint32_t base = kTwoZeroBytes;
   uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div;
   uint32_t mod10 = n - 10u * div10;
-  base += div10 + (mod10 << 8);
+  uint32_t base = kTwoZeroBytes + div10 + (mod10 << 8);
   base >>= num_digits & 8;
   little_endian::Store16(out_str, static_cast<uint16_t>(base));
   return out_str + 2 + num_digits;
@@ -196,19 +195,33 @@
   // to a multiple to 8 to strip zero bytes, not all zero bits.
   // countr_zero to help.
   // 0 minus 8 to make MSVC happy.
-  uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(tens)) & (0 - 8ull);
+  uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(tens)) & (0 - 8u);
   tens += kFourZeroBytes;
   tens >>= zeroes;
   little_endian::Store32(out_str, tens);
   return out_str + sizeof(tens) - zeroes / 8;
 }
 
-// Prepare functions return an integer that should be written to out_str
-// (but possibly include trailing zeros).
-// For hi < 10000, lo < 10000 returns uint64_t as encoded in ASCII with
-// possibly trailing zeroes of the number hi * 10000 + lo.
-inline uint64_t PrepareTenThousands(uint64_t hi, uint64_t lo) {
-  uint64_t merged = hi | (lo << 32);
+// Helper function to produce an ASCII representation of `i`.
+//
+// Function returns an 8-byte integer which when summed with `kEightZeroBytes`,
+// can be treated as a printable buffer with ascii representation of `i`,
+// possibly with leading zeros.
+//
+// Example:
+//
+//  uint64_t buffer = PrepareEightDigits(102030) + kEightZeroBytes;
+//  char* ascii = reinterpret_cast<char*>(&buffer);
+//  // Note two leading zeros:
+//  EXPECT_EQ(absl::string_view(ascii, 8), "00102030");
+//
+// Pre-condition: `i` must be less than 100000000.
+inline uint64_t PrepareEightDigits(uint32_t i) {
+  ABSL_ASSUME(i < 10000'0000);
+  // Prepare 2 blocks of 4 digits "in parallel".
+  uint32_t hi = i / 10000;
+  uint32_t lo = i % 10000;
+  uint64_t merged = hi | (uint64_t{lo} << 32);
   uint64_t div100 = ((merged * kDivisionBy100Mul) / kDivisionBy100Div) &
                     ((0x7Full << 32) | 0x7Full);
   uint64_t mod100 = merged - 100ull * div100;
@@ -219,27 +232,54 @@
   return tens;
 }
 
-inline char* EncodeFullU32(uint32_t n, char* out_str) {
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU32(uint32_t n,
+                                                        char* out_str) {
+  if (n < 10) {
+    *out_str = static_cast<char>('0' + n);
+    return out_str + 1;
+  }
   if (n < 100'000'000) {
-    uint64_t bottom = PrepareTenThousands(n / 10000, n % 10000);
+    uint64_t bottom = PrepareEightDigits(n);
     ABSL_ASSUME(bottom != 0);
     // 0 minus 8 to make MSVC happy.
-    uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(bottom))
-        & (0 - 8ull);
-    uint64_t bottom_res = bottom + kEightZeroBytes;
-    bottom_res >>= zeroes;
-    little_endian::Store64(out_str, bottom_res);
+    uint32_t zeroes =
+        static_cast<uint32_t>(absl::countr_zero(bottom)) & (0 - 8u);
+    little_endian::Store64(out_str, (bottom + kEightZeroBytes) >> zeroes);
     return out_str + sizeof(bottom) - zeroes / 8;
   }
-  uint32_t top = n / 100'000'000;
-  n %= 100'000'000;
-  uint64_t bottom = PrepareTenThousands(n / 10000, n % 10000);
-  uint64_t bottom_res = bottom + kEightZeroBytes;
-  out_str = EncodeHundred(top, out_str);
-  little_endian::Store64(out_str, bottom_res);
+  uint32_t div08 = n / 100'000'000;
+  uint32_t mod08 = n % 100'000'000;
+  uint64_t bottom = PrepareEightDigits(mod08) + kEightZeroBytes;
+  out_str = EncodeHundred(div08, out_str);
+  little_endian::Store64(out_str, bottom);
   return out_str + sizeof(bottom);
 }
 
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU64(uint64_t i,
+                                                        char* buffer) {
+  if (i <= std::numeric_limits<uint32_t>::max()) {
+    return EncodeFullU32(static_cast<uint32_t>(i), buffer);
+  }
+  uint32_t mod08;
+  if (i < 1'0000'0000'0000'0000ull) {
+    uint32_t div08 = static_cast<uint32_t>(i / 100'000'000ull);
+    mod08 =  static_cast<uint32_t>(i % 100'000'000ull);
+    buffer = EncodeFullU32(div08, buffer);
+  } else {
+    uint64_t div08 = i / 100'000'000ull;
+    mod08 =  static_cast<uint32_t>(i % 100'000'000ull);
+    uint32_t div016 = static_cast<uint32_t>(div08 / 100'000'000ull);
+    uint32_t div08mod08 = static_cast<uint32_t>(div08 % 100'000'000ull);
+    uint64_t mid_result = PrepareEightDigits(div08mod08) + kEightZeroBytes;
+    buffer = EncodeTenThousand(div016, buffer);
+    little_endian::Store64(buffer, mid_result);
+    buffer += sizeof(mid_result);
+  }
+  uint64_t mod_result = PrepareEightDigits(mod08) + kEightZeroBytes;
+  little_endian::Store64(buffer, mod_result);
+  return buffer + sizeof(mod_result);
+}
+
 }  // namespace
 
 void numbers_internal::PutTwoDigits(uint32_t i, char* buf) {
@@ -252,16 +292,7 @@
 }
 
 char* numbers_internal::FastIntToBuffer(uint32_t n, char* out_str) {
-  if (n < 100) {
-    out_str = EncodeHundred(n, out_str);
-    goto set_last_zero;
-  }
-  if (n < 10000) {
-    out_str = EncodeTenThousand(n, out_str);
-    goto set_last_zero;
-  }
   out_str = EncodeFullU32(n, out_str);
-set_last_zero:
   *out_str = '\0';
   return out_str;
 }
@@ -275,45 +306,13 @@
     // we write the equivalent expression "0 - u" instead.
     u = 0 - u;
   }
-  return numbers_internal::FastIntToBuffer(u, buffer);
+  buffer = EncodeFullU32(u, buffer);
+  *buffer = '\0';
+  return buffer;
 }
 
 char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) {
-  uint32_t u32 = static_cast<uint32_t>(i);
-  if (u32 == i) return numbers_internal::FastIntToBuffer(u32, buffer);
-
-  // 10**9 < 2**32 <= i < 10**10, we can do 2+8
-  uint64_t div08 = i / 100'000'000ull;
-  uint64_t mod08 = i % 100'000'000ull;
-  uint64_t mod_result =
-      PrepareTenThousands(mod08 / 10000, mod08 % 10000) + kEightZeroBytes;
-  if (i < 10'000'000'000ull) {
-    buffer = EncodeHundred(static_cast<uint32_t>(div08), buffer);
-    little_endian::Store64(buffer, mod_result);
-    buffer += 8;
-    goto set_last_zero;
-  }
-
-  // i < 10**16, in this case 8+8
-  if (i < 10'000'000'000'000'000ull) {
-    buffer = EncodeFullU32(static_cast<uint32_t>(div08), buffer);
-    little_endian::Store64(buffer, mod_result);
-    buffer += 8;
-    goto set_last_zero;
-  } else {
-    // 4 + 8 + 8
-    uint64_t div016 = i / 10'000'000'000'000'000ull;
-    buffer = EncodeTenThousand(static_cast<uint32_t>(div016), buffer);
-    uint64_t mid_result = div08 - div016 * 100'000'000ull;
-    mid_result = PrepareTenThousands(mid_result / 10000, mid_result % 10000) +
-                 kEightZeroBytes;
-    little_endian::Store64(buffer, mid_result);
-    buffer += 8;
-    little_endian::Store64(buffer, mod_result);
-    buffer += 8;
-    goto set_last_zero;
-  }
-set_last_zero:
+  buffer = EncodeFullU64(i, buffer);
   *buffer = '\0';
   return buffer;
 }
@@ -322,9 +321,14 @@
   uint64_t u = static_cast<uint64_t>(i);
   if (i < 0) {
     *buffer++ = '-';
+    // We need to do the negation in modular (i.e., "unsigned")
+    // arithmetic; MSVC++ apparently warns for plain "-u", so
+    // we write the equivalent expression "0 - u" instead.
     u = 0 - u;
   }
-  return numbers_internal::FastIntToBuffer(u, buffer);
+  buffer = EncodeFullU64(u, buffer);
+  *buffer = '\0';
+  return buffer;
 }
 
 // Given a 128-bit number expressed as a pair of uint64_t, high half first,
diff --git a/third_party/abseil-cpp/absl/strings/numbers_test.cc b/third_party/abseil-cpp/absl/strings/numbers_test.cc
index a450b99e..75c2dcf 100644
--- a/third_party/abseil-cpp/absl/strings/numbers_test.cc
+++ b/third_party/abseil-cpp/absl/strings/numbers_test.cc
@@ -63,6 +63,7 @@
 using absl::strings_internal::strtouint64_test_cases;
 using testing::Eq;
 using testing::MatchesRegex;
+using testing::Pointee;
 
 // Number of floats to test with.
 // 5,000,000 is a reasonable default for a test that only takes a few seconds.
@@ -1715,4 +1716,25 @@
   }
 }
 
+template <typename Int>
+void ExpectWritesNull() {
+  {
+    char buf[absl::numbers_internal::kFastToBufferSize];
+    Int x = std::numeric_limits<Int>::min();
+    EXPECT_THAT(absl::numbers_internal::FastIntToBuffer(x, buf), Pointee('\0'));
+  }
+  {
+    char buf[absl::numbers_internal::kFastToBufferSize];
+    Int x = std::numeric_limits<Int>::max();
+    EXPECT_THAT(absl::numbers_internal::FastIntToBuffer(x, buf), Pointee('\0'));
+  }
+}
+
+TEST(FastIntToBuffer, WritesNull) {
+  ExpectWritesNull<int32_t>();
+  ExpectWritesNull<uint32_t>();
+  ExpectWritesNull<int64_t>();
+  ExpectWritesNull<uint32_t>();
+}
+
 }  // namespace
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.cc b/third_party/abseil-cpp/absl/synchronization/mutex.cc
index 3aa5560..353a828 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.cc
@@ -682,6 +682,7 @@
 // flags passed to Enqueue and LockSlow{,WithTimeout,Loop}
 static const int kMuHasBlocked = 0x01;  // already blocked (MUST == 1)
 static const int kMuIsCond = 0x02;      // conditional waiter (CV or Condition)
+static const int kMuIsFer = 0x04;       // wait morphing from a CondVar
 
 static_assert(PerThreadSynch::kAlignment > kMuLow,
               "PerThreadSynch::kAlignment must be greater than kMuLow");
@@ -920,20 +921,23 @@
   s->wake = false;     // not being woken
   s->cond_waiter = ((flags & kMuIsCond) != 0);
 #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
-  int64_t now_cycles = CycleClock::Now();
-  if (s->next_priority_read_cycles < now_cycles) {
-    // Every so often, update our idea of the thread's priority.
-    // pthread_getschedparam() is 5% of the block/wakeup time;
-    // CycleClock::Now() is 0.5%.
-    int policy;
-    struct sched_param param;
-    const int err = pthread_getschedparam(pthread_self(), &policy, &param);
-    if (err != 0) {
-      ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err);
-    } else {
-      s->priority = param.sched_priority;
-      s->next_priority_read_cycles =
-          now_cycles + static_cast<int64_t>(CycleClock::Frequency());
+  if ((flags & kMuIsFer) == 0) {
+    assert(s == Synch_GetPerThread());
+    int64_t now_cycles = CycleClock::Now();
+    if (s->next_priority_read_cycles < now_cycles) {
+      // Every so often, update our idea of the thread's priority.
+      // pthread_getschedparam() is 5% of the block/wakeup time;
+      // CycleClock::Now() is 0.5%.
+      int policy;
+      struct sched_param param;
+      const int err = pthread_getschedparam(pthread_self(), &policy, &param);
+      if (err != 0) {
+        ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err);
+      } else {
+        s->priority = param.sched_priority;
+        s->next_priority_read_cycles =
+            now_cycles + static_cast<int64_t>(CycleClock::Frequency());
+      }
     }
   }
 #endif
@@ -2436,7 +2440,8 @@
     } else {
       if ((v & (kMuSpin | kMuWait)) == 0) {  // no waiters
         // This thread tries to become the one and only waiter.
-        PerThreadSynch* new_h = Enqueue(nullptr, w->waitp, v, kMuIsCond);
+        PerThreadSynch* new_h =
+            Enqueue(nullptr, w->waitp, v, kMuIsCond | kMuIsFer);
         ABSL_RAW_CHECK(new_h != nullptr,
                        "Enqueue failed");  // we must queue ourselves
         if (mu_.compare_exchange_strong(
@@ -2447,7 +2452,7 @@
       } else if ((v & kMuSpin) == 0 &&
                  mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) {
         PerThreadSynch* h = GetPerThreadSynch(v);
-        PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond);
+        PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond | kMuIsFer);
         ABSL_RAW_CHECK(new_h != nullptr,
                        "Enqueue failed");  // we must queue ourselves
         do {
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
index b585c34..0bca46c 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
@@ -36,10 +36,16 @@
 #include "absl/log/check.h"
 #include "absl/log/log.h"
 #include "absl/memory/memory.h"
+#include "absl/synchronization/internal/create_thread_identity.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
+#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
+#include <pthread.h>
+#include <string.h>
+#endif
+
 namespace {
 
 // TODO(dmauro): Replace with a commandline flag.
@@ -1868,6 +1874,60 @@
   EXPECT_TRUE(saw_wrote.load());
 }
 
+#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
+TEST(Mutex, CondVarPriority) {
+  // A regression test for a bug in condition variable wait morphing,
+  // which resulted in the waiting thread getting priority of the waking thread.
+  int err = 0;
+  sched_param param;
+  param.sched_priority = 7;
+  std::thread test([&]() {
+    err = pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+  });
+  test.join();
+  if (err) {
+    // Setting priority usually requires special privileges.
+    GTEST_SKIP() << "failed to set priority: " << strerror(err);
+  }
+  absl::Mutex mu;
+  absl::CondVar cv;
+  bool locked = false;
+  bool notified = false;
+  bool waiting = false;
+  bool morph = false;
+  std::thread th([&]() {
+    EXPECT_EQ(0, pthread_setschedparam(pthread_self(), SCHED_FIFO, &param));
+    mu.Lock();
+    locked = true;
+    mu.Await(absl::Condition(&notified));
+    mu.Unlock();
+    EXPECT_EQ(absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()
+                  ->per_thread_synch.priority,
+              param.sched_priority);
+    mu.Lock();
+    mu.Await(absl::Condition(&waiting));
+    morph = true;
+    absl::SleepFor(absl::Seconds(1));
+    cv.Signal();
+    mu.Unlock();
+  });
+  mu.Lock();
+  mu.Await(absl::Condition(&locked));
+  notified = true;
+  mu.Unlock();
+  mu.Lock();
+  waiting = true;
+  while (!morph) {
+    cv.Wait(&mu);
+  }
+  mu.Unlock();
+  th.join();
+  EXPECT_NE(absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()
+                ->per_thread_synch.priority,
+            param.sched_priority);
+}
+#endif
+
 TEST(Mutex, LockWhenWithTimeoutResult) {
   // Check various corner cases for Await/LockWhen return value
   // with always true/always false conditions.
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
index 9b91f61..e7e30a2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
@@ -19,7 +19,7 @@
 #endif
 
 #if defined(HAS_STRPTIME) && HAS_STRPTIME
-#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__)
+#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
 #define _XOPEN_SOURCE 500  // Exposes definitions for SUSv2 (UNIX 98).
 #endif
 #endif
diff --git a/third_party/abseil-cpp/absl/types/BUILD.bazel b/third_party/abseil-cpp/absl/types/BUILD.bazel
index b57d3b9..34f398bb 100644
--- a/third_party/abseil-cpp/absl/types/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/types/BUILD.bazel
@@ -208,44 +208,6 @@
 )
 
 cc_library(
-    name = "conformance_testing",
-    testonly = 1,
-    hdrs = [
-        "internal/conformance_aliases.h",
-        "internal/conformance_archetype.h",
-        "internal/conformance_profile.h",
-        "internal/conformance_testing.h",
-        "internal/conformance_testing_helpers.h",
-        "internal/parentheses.h",
-        "internal/transform_args.h",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        "//absl/algorithm:container",
-        "//absl/meta:type_traits",
-        "//absl/strings",
-        "//absl/utility",
-        "@com_google_googletest//:gtest",
-    ],
-)
-
-cc_test(
-    name = "conformance_testing_test",
-    size = "small",
-    srcs = [
-        "internal/conformance_testing_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":conformance_testing",
-        "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_library(
     name = "variant",
     srcs = ["internal/variant.h"],
     hdrs = ["variant.h"],
diff --git a/third_party/abseil-cpp/absl/types/CMakeLists.txt b/third_party/abseil-cpp/absl/types/CMakeLists.txt
index c0dcee7..1adf3c72 100644
--- a/third_party/abseil-cpp/absl/types/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/types/CMakeLists.txt
@@ -240,59 +240,6 @@
     GTest::gmock_main
 )
 
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    conformance_testing
-  HDRS
-    "internal/conformance_aliases.h"
-    "internal/conformance_archetype.h"
-    "internal/conformance_profile.h"
-    "internal/conformance_testing.h"
-    "internal/conformance_testing_helpers.h"
-    "internal/parentheses.h"
-    "internal/transform_args.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::algorithm
-    absl::debugging
-    absl::type_traits
-    absl::strings
-    absl::utility
-    GTest::gmock_main
-  TESTONLY
-)
-
-absl_cc_test(
-  NAME
-    conformance_testing_test
-  SRCS
-    "internal/conformance_testing_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-    ${ABSL_EXCEPTIONS_FLAG}
-  LINKOPTS
-    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
-  DEPS
-    absl::conformance_testing
-    absl::type_traits
-    GTest::gmock_main
-)
-
-absl_cc_test(
-  NAME
-    conformance_testing_test_no_exceptions
-  SRCS
-    "internal/conformance_testing_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::conformance_testing
-    absl::type_traits
-    GTest::gmock_main
-)
-
 absl_cc_library(
   NAME
     variant
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_aliases.h b/third_party/abseil-cpp/absl/types/internal/conformance_aliases.h
deleted file mode 100644
index 0cc6884..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_aliases.h
+++ /dev/null
@@ -1,447 +0,0 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// regularity_aliases.h
-// -----------------------------------------------------------------------------
-//
-// This file contains type aliases of common ConformanceProfiles and Archetypes
-// so that they can be directly used by name without creating them from scratch.
-
-#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
-#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
-
-#include "absl/types/internal/conformance_archetype.h"
-#include "absl/types/internal/conformance_profile.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-
-// Creates both a Profile and a corresponding Archetype with root name "name".
-#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...)                \
-  struct name##Profile : __VA_ARGS__ {};                                    \
-                                                                            \
-  using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \
-                                                                            \
-  template <class AbslInternalProfileTag>                                   \
-  using name##Archetype##_ = ::absl::types_internal::Archetype<             \
-      ::absl::types_internal::StrongProfileTypedef<name##Profile,           \
-                                                   AbslInternalProfileTag>>
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialDefaultConstructor,
-    ConformanceProfile<default_constructible::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowDefaultConstructor,
-    ConformanceProfile<default_constructible::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasDefaultConstructor, ConformanceProfile<default_constructible::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe,
-                                                  move_constructible::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe,
-                                                  move_constructible::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasMoveConstructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialCopyConstructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowCopyConstructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasCopyConstructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialMoveAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowMoveAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasMoveAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialCopyAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowCopyAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasCopyAssign,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasTrivialDestructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::trivial>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowDestructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasDestructor,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowEquality,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasEquality,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowInequality,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe,
-                       inequality_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasInequality,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe, inequality_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowLessThan,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe, inequality_comparable::maybe,
-                       less_than_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasLessThan,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe, inequality_comparable::maybe,
-                       less_than_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowLessEqual,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe, inequality_comparable::maybe,
-                       less_than_comparable::maybe,
-                       less_equal_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasLessEqual,
-    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
-                       copy_constructible::maybe, move_assignable::maybe,
-                       copy_assignable::maybe, destructible::maybe,
-                       equality_comparable::maybe, inequality_comparable::maybe,
-                       less_than_comparable::maybe,
-                       less_equal_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowGreaterEqual,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasGreaterEqual,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowGreaterThan,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::maybe,
-        greater_than_comparable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasGreaterThan,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::maybe,
-        greater_than_comparable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasNothrowSwap,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::maybe,
-        greater_than_comparable::maybe, swappable::nothrow>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasSwap,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::maybe,
-        greater_than_comparable::maybe, swappable::yes>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HasStdHashSpecialization,
-    ConformanceProfile<
-        default_constructible::maybe, move_constructible::maybe,
-        copy_constructible::maybe, move_assignable::maybe,
-        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
-        inequality_comparable::maybe, less_than_comparable::maybe,
-        less_equal_comparable::maybe, greater_equal_comparable::maybe,
-        greater_than_comparable::maybe, swappable::maybe, hashable::yes>);
-
-////////////////////////////////////////////////////////////////////////////////
-////     The remaining aliases are combinations of the previous aliases.    ////
-////////////////////////////////////////////////////////////////////////////////
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    Comparable,
-    CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile,
-                    HasGreaterEqualProfile, HasGreaterThanProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    NothrowEquatable,
-    CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    NothrowComparable,
-    CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile,
-                    HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile,
-                    HasNothrowGreaterThanProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    Value,
-    CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
-                    HasNothrowMoveAssignProfile, HasCopyAssignProfile,
-                    HasNothrowDestructorProfile, HasNothrowSwapProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    DefaultConstructibleValue,
-    CombineProfiles<HasDefaultConstructorProfile, ValueProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile,
-                                              HasNothrowDestructorProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    EquatableNothrowMoveConstructible,
-    CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    ComparableNothrowMoveConstructible,
-    CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    DefaultConstructibleNothrowMoveConstructible,
-    CombineProfiles<HasDefaultConstructorProfile,
-                    NothrowMoveConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    CopyConstructible,
-    CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
-                    HasNothrowDestructorProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    EquatableCopyConstructible,
-    CombineProfiles<EquatableProfile, CopyConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    ComparableCopyConstructible,
-    CombineProfiles<ComparableProfile, CopyConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    DefaultConstructibleCopyConstructible,
-    CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    NothrowMovable,
-    CombineProfiles<HasNothrowMoveConstructorProfile,
-                    HasNothrowMoveAssignProfile, HasNothrowDestructorProfile,
-                    HasNothrowSwapProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    EquatableNothrowMovable,
-    CombineProfiles<EquatableProfile, NothrowMovableProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    ComparableNothrowMovable,
-    CombineProfiles<ComparableProfile, NothrowMovableProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    DefaultConstructibleNothrowMovable,
-    CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    TrivialSpecialMemberFunctions,
-    CombineProfiles<HasTrivialDefaultConstructorProfile,
-                    HasTrivialMoveConstructorProfile,
-                    HasTrivialCopyConstructorProfile,
-                    HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile,
-                    HasTrivialDestructorProfile, HasNothrowSwapProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    TriviallyComplete,
-    CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile,
-                    HasStdHashSpecializationProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HashableNothrowMoveConstructible,
-    CombineProfiles<HasStdHashSpecializationProfile,
-                    NothrowMoveConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HashableCopyConstructible,
-    CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HashableNothrowMovable,
-    CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    HashableValue,
-    CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>);
-
-ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
-    ComparableHashableValue,
-    CombineProfiles<HashableValueProfile, ComparableProfile>);
-
-// The "preferred" profiles that we support in Abseil.
-template <template <class...> class Receiver>
-using ExpandBasicProfiles =
-    Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile,
-             NothrowMovableProfile, ValueProfile>;
-
-// The basic profiles except that they are also all Equatable.
-template <template <class...> class Receiver>
-using ExpandBasicEquatableProfiles =
-    Receiver<EquatableNothrowMoveConstructibleProfile,
-             EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile,
-             EquatableValueProfile>;
-
-// The basic profiles except that they are also all Comparable.
-template <template <class...> class Receiver>
-using ExpandBasicComparableProfiles =
-    Receiver<ComparableNothrowMoveConstructibleProfile,
-             ComparableCopyConstructibleProfile,
-             ComparableNothrowMovableProfile, ComparableValueProfile>;
-
-// The basic profiles except that they are also all Hashable.
-template <template <class...> class Receiver>
-using ExpandBasicHashableProfiles =
-    Receiver<HashableNothrowMoveConstructibleProfile,
-             HashableCopyConstructibleProfile, HashableNothrowMovableProfile,
-             HashableValueProfile>;
-
-// The basic profiles except that they are also all DefaultConstructible.
-template <template <class...> class Receiver>
-using ExpandBasicDefaultConstructibleProfiles =
-    Receiver<DefaultConstructibleNothrowMoveConstructibleProfile,
-             DefaultConstructibleCopyConstructibleProfile,
-             DefaultConstructibleNothrowMovableProfile,
-             DefaultConstructibleValueProfile>;
-
-// The type profiles that we support in Abseil (all of the previous lists).
-template <template <class...> class Receiver>
-using ExpandSupportedProfiles = Receiver<
-    NothrowMoveConstructibleProfile, CopyConstructibleProfile,
-    NothrowMovableProfile, ValueProfile,
-    EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile,
-    EquatableNothrowMovableProfile, EquatableValueProfile,
-    ComparableNothrowMoveConstructibleProfile,
-    ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile,
-    ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile,
-    DefaultConstructibleCopyConstructibleProfile,
-    DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile,
-    HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile,
-    HashableNothrowMovableProfile, HashableValueProfile>;
-
-// TODO(calabrese) Include types that have throwing move constructors, since in
-// practice we still need to support them because of standard library types with
-// (potentially) non-noexcept moves.
-
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS
-
-#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_archetype.h b/third_party/abseil-cpp/absl/types/internal/conformance_archetype.h
deleted file mode 100644
index 2349e0f..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_archetype.h
+++ /dev/null
@@ -1,978 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// conformance_archetype.h
-// -----------------------------------------------------------------------------
-//
-// This file contains a facility for generating "archetypes" of out of
-// "Conformance Profiles" (see "conformance_profiles.h" for more information
-// about Conformance Profiles). An archetype is a type that aims to support the
-// bare minimum requirements of a given Conformance Profile. For instance, an
-// archetype that corresponds to an ImmutableProfile has exactly a nothrow
-// move-constructor, a potentially-throwing copy constructor, a nothrow
-// destructor, with all other special-member-functions deleted. These archetypes
-// are useful for testing to make sure that templates are able to work with the
-// kinds of types that they claim to support (i.e. that they do not accidentally
-// under-constrain),
-//
-// The main type template in this file is the Archetype template, which takes
-// a Conformance Profile as a template argument and its instantiations are a
-// minimum-conforming model of that profile.
-
-#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
-#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
-
-#include <cstddef>
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-#include "absl/meta/type_traits.h"
-#include "absl/types/internal/conformance_profile.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-
-// A minimum-conforming implementation of a type with properties specified in
-// `Prof`, where `Prof` is a valid Conformance Profile.
-template <class Prof, class /*Enabler*/ = void>
-class Archetype;
-
-// Given an Archetype, obtain the properties of the profile associated with that
-// archetype.
-template <class Archetype>
-struct PropertiesOfArchetype;
-
-template <class Prof>
-struct PropertiesOfArchetype<Archetype<Prof>> {
-  using type = PropertiesOfT<Prof>;
-};
-
-template <class Archetype>
-using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type;
-
-// A metafunction to determine if a type is an `Archetype`.
-template <class T>
-struct IsArchetype : std::false_type {};
-
-template <class Prof>
-struct IsArchetype<Archetype<Prof>> : std::true_type {};
-
-// A constructor tag type used when creating an Archetype with internal state.
-struct MakeArchetypeState {};
-
-// Data stored within an archetype that is copied/compared/hashed when the
-// corresponding operations are used.
-using ArchetypeState = std::size_t;
-
-////////////////////////////////////////////////////////////////////////////////
-//   This section of the file defines a chain of base classes for Archetype,  //
-//   where each base defines a specific special member function with the      //
-//   appropriate properties (deleted, noexcept(false), noexcept, or trivial). //
-////////////////////////////////////////////////////////////////////////////////
-
-// The bottom-most base, which contains the state and the default constructor.
-template <default_constructible DefaultConstructibleValue>
-struct ArchetypeStateBase {
-  static_assert(DefaultConstructibleValue == default_constructible::yes ||
-                    DefaultConstructibleValue == default_constructible::nothrow,
-                "");
-
-  ArchetypeStateBase() noexcept(
-      DefaultConstructibleValue ==
-      default_constructible::
-          nothrow) /*Vacuous archetype_state initialization*/ {}
-  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
-      : archetype_state(state) {}
-
-  ArchetypeState archetype_state;
-};
-
-template <>
-struct ArchetypeStateBase<default_constructible::maybe> {
-  explicit ArchetypeStateBase() = delete;
-  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
-      : archetype_state(state) {}
-
-  ArchetypeState archetype_state;
-};
-
-template <>
-struct ArchetypeStateBase<default_constructible::trivial> {
-  ArchetypeStateBase() = default;
-  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
-      : archetype_state(state) {}
-
-  ArchetypeState archetype_state;
-};
-
-// The move-constructor base
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue>
-struct ArchetypeMoveConstructor
-    : ArchetypeStateBase<DefaultConstructibleValue> {
-  static_assert(MoveConstructibleValue == move_constructible::yes ||
-                    MoveConstructibleValue == move_constructible::nothrow,
-                "");
-
-  explicit ArchetypeMoveConstructor(MakeArchetypeState,
-                                    ArchetypeState state) noexcept
-      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
-                                                      state) {}
-
-  ArchetypeMoveConstructor() = default;
-  ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept(
-      MoveConstructibleValue == move_constructible::nothrow)
-      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
-                                                      other.archetype_state) {}
-  ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default;
-  ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default;
-  ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) =
-      default;
-};
-
-template <default_constructible DefaultConstructibleValue>
-struct ArchetypeMoveConstructor<DefaultConstructibleValue,
-                                move_constructible::trivial>
-    : ArchetypeStateBase<DefaultConstructibleValue> {
-  explicit ArchetypeMoveConstructor(MakeArchetypeState,
-                                    ArchetypeState state) noexcept
-      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
-                                                      state) {}
-
-  ArchetypeMoveConstructor() = default;
-};
-
-// The copy-constructor base
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue>
-struct ArchetypeCopyConstructor
-    : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                               MoveConstructibleValue> {
-  static_assert(CopyConstructibleValue == copy_constructible::yes ||
-                    CopyConstructibleValue == copy_constructible::nothrow,
-                "");
-  explicit ArchetypeCopyConstructor(MakeArchetypeState,
-                                    ArchetypeState state) noexcept
-      : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue>(MakeArchetypeState(),
-                                                         state) {}
-
-  ArchetypeCopyConstructor() = default;
-  ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
-  ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept(
-      CopyConstructibleValue == copy_constructible::nothrow)
-      : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue>(
-            MakeArchetypeState(), other.archetype_state) {}
-  ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
-  ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
-      default;
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue>
-struct ArchetypeCopyConstructor<DefaultConstructibleValue,
-                                MoveConstructibleValue,
-                                copy_constructible::maybe>
-    : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                               MoveConstructibleValue> {
-  explicit ArchetypeCopyConstructor(MakeArchetypeState,
-                                    ArchetypeState state) noexcept
-      : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue>(MakeArchetypeState(),
-                                                         state) {}
-
-  ArchetypeCopyConstructor() = default;
-  ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
-  ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete;
-  ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
-  ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
-      default;
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue>
-struct ArchetypeCopyConstructor<DefaultConstructibleValue,
-                                MoveConstructibleValue,
-                                copy_constructible::trivial>
-    : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                               MoveConstructibleValue> {
-  explicit ArchetypeCopyConstructor(MakeArchetypeState,
-                                    ArchetypeState state) noexcept
-      : ArchetypeMoveConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue>(MakeArchetypeState(),
-                                                         state) {}
-
-  ArchetypeCopyConstructor() = default;
-};
-
-// The move-assign base
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue>
-struct ArchetypeMoveAssign
-    : ArchetypeCopyConstructor<DefaultConstructibleValue,
-                               MoveConstructibleValue, CopyConstructibleValue> {
-  static_assert(MoveAssignableValue == move_assignable::yes ||
-                    MoveAssignableValue == move_assignable::nothrow,
-                "");
-  explicit ArchetypeMoveAssign(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeCopyConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue,
-                                 CopyConstructibleValue>(MakeArchetypeState(),
-                                                         state) {}
-
-  ArchetypeMoveAssign() = default;
-  ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default;
-  ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default;
-  ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept(
-      MoveAssignableValue == move_assignable::nothrow) {
-    this->archetype_state = other.archetype_state;
-    return *this;
-  }
-
-  ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default;
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue>
-struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                           CopyConstructibleValue, move_assignable::trivial>
-    : ArchetypeCopyConstructor<DefaultConstructibleValue,
-                               MoveConstructibleValue, CopyConstructibleValue> {
-  explicit ArchetypeMoveAssign(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeCopyConstructor<DefaultConstructibleValue,
-                                 MoveConstructibleValue,
-                                 CopyConstructibleValue>(MakeArchetypeState(),
-                                                         state) {}
-
-  ArchetypeMoveAssign() = default;
-};
-
-// The copy-assign base
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue,
-          copy_assignable CopyAssignableValue>
-struct ArchetypeCopyAssign
-    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                          CopyConstructibleValue, MoveAssignableValue> {
-  static_assert(CopyAssignableValue == copy_assignable::yes ||
-                    CopyAssignableValue == copy_assignable::nothrow,
-                "");
-  explicit ArchetypeCopyAssign(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                            CopyConstructibleValue, MoveAssignableValue>(
-            MakeArchetypeState(), state) {}
-
-  ArchetypeCopyAssign() = default;
-  ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
-  ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
-  ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
-
-  ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept(
-      CopyAssignableValue == copy_assignable::nothrow) {
-    this->archetype_state = other.archetype_state;
-    return *this;
-  }
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue>
-struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                           CopyConstructibleValue, MoveAssignableValue,
-                           copy_assignable::maybe>
-    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                          CopyConstructibleValue, MoveAssignableValue> {
-  explicit ArchetypeCopyAssign(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                            CopyConstructibleValue, MoveAssignableValue>(
-            MakeArchetypeState(), state) {}
-
-  ArchetypeCopyAssign() = default;
-  ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
-  ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
-  ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
-  ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete;
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue>
-struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                           CopyConstructibleValue, MoveAssignableValue,
-                           copy_assignable::trivial>
-    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                          CopyConstructibleValue, MoveAssignableValue> {
-  explicit ArchetypeCopyAssign(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                            CopyConstructibleValue, MoveAssignableValue>(
-            MakeArchetypeState(), state) {}
-
-  ArchetypeCopyAssign() = default;
-};
-
-// The destructor base
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue,
-          copy_assignable CopyAssignableValue, destructible DestructibleValue>
-struct ArchetypeDestructor
-    : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                          CopyConstructibleValue, MoveAssignableValue,
-                          CopyAssignableValue> {
-  static_assert(DestructibleValue == destructible::yes ||
-                    DestructibleValue == destructible::nothrow,
-                "");
-
-  explicit ArchetypeDestructor(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                            CopyConstructibleValue, MoveAssignableValue,
-                            CopyAssignableValue>(MakeArchetypeState(), state) {}
-
-  ArchetypeDestructor() = default;
-  ArchetypeDestructor(ArchetypeDestructor&&) = default;
-  ArchetypeDestructor(const ArchetypeDestructor&) = default;
-  ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default;
-  ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default;
-  ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {}
-};
-
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue,
-          copy_assignable CopyAssignableValue>
-struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue,
-                           CopyConstructibleValue, MoveAssignableValue,
-                           CopyAssignableValue, destructible::trivial>
-    : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                          CopyConstructibleValue, MoveAssignableValue,
-                          CopyAssignableValue> {
-  explicit ArchetypeDestructor(MakeArchetypeState,
-                               ArchetypeState state) noexcept
-      : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
-                            CopyConstructibleValue, MoveAssignableValue,
-                            CopyAssignableValue>(MakeArchetypeState(), state) {}
-
-  ArchetypeDestructor() = default;
-};
-
-// An alias to the top of the chain of bases for special-member functions.
-// NOTE: move_constructible::maybe, move_assignable::maybe, and
-// destructible::maybe are handled in the top-level type by way of SFINAE.
-// Because of this, we never instantiate the base classes with
-// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so
-// that we minimize the number of different possible type-template
-// instantiations.
-template <default_constructible DefaultConstructibleValue,
-          move_constructible MoveConstructibleValue,
-          copy_constructible CopyConstructibleValue,
-          move_assignable MoveAssignableValue,
-          copy_assignable CopyAssignableValue, destructible DestructibleValue>
-using ArchetypeSpecialMembersBase = ArchetypeDestructor<
-    DefaultConstructibleValue,
-    MoveConstructibleValue != move_constructible::maybe
-        ? MoveConstructibleValue
-        : move_constructible::nothrow,
-    CopyConstructibleValue,
-    MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue
-                                                  : move_assignable::nothrow,
-    CopyAssignableValue,
-    DestructibleValue != destructible::maybe ? DestructibleValue
-                                             : destructible::nothrow>;
-
-// A function that is used to create an archetype with some associated state.
-template <class Arch>
-Arch MakeArchetype(ArchetypeState state) noexcept {
-  static_assert(IsArchetype<Arch>::value,
-                "The explicit template argument to MakeArchetype is required "
-                "to be an Archetype.");
-  return Arch(MakeArchetypeState(), state);
-}
-
-// This is used to conditionally delete "copy" and "move" constructors in a way
-// that is consistent with what the ConformanceProfile requires and that also
-// strictly enforces the arguments to the copy/move to not come from implicit
-// conversions when dealing with the Archetype.
-template <class Prof, class T>
-constexpr bool ShouldDeleteConstructor() {
-  return !((PropertiesOfT<Prof>::move_constructible_support !=
-                move_constructible::maybe &&
-            std::is_same<T, Archetype<Prof>>::value) ||
-           (PropertiesOfT<Prof>::copy_constructible_support !=
-                copy_constructible::maybe &&
-            (std::is_same<T, const Archetype<Prof>&>::value ||
-             std::is_same<T, Archetype<Prof>&>::value ||
-             std::is_same<T, const Archetype<Prof>>::value)));
-}
-
-// This is used to conditionally delete "copy" and "move" assigns in a way
-// that is consistent with what the ConformanceProfile requires and that also
-// strictly enforces the arguments to the copy/move to not come from implicit
-// conversions when dealing with the Archetype.
-template <class Prof, class T>
-constexpr bool ShouldDeleteAssign() {
-  return !(
-      (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe &&
-       std::is_same<T, Archetype<Prof>>::value) ||
-      (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe &&
-       (std::is_same<T, const Archetype<Prof>&>::value ||
-        std::is_same<T, Archetype<Prof>&>::value ||
-        std::is_same<T, const Archetype<Prof>>::value)));
-}
-
-// TODO(calabrese) Inherit from a chain of secondary bases to pull in the
-// associated functions of other concepts.
-template <class Prof, class Enabler>
-class Archetype : ArchetypeSpecialMembersBase<
-                      PropertiesOfT<Prof>::default_constructible_support,
-                      PropertiesOfT<Prof>::move_constructible_support,
-                      PropertiesOfT<Prof>::copy_constructible_support,
-                      PropertiesOfT<Prof>::move_assignable_support,
-                      PropertiesOfT<Prof>::copy_assignable_support,
-                      PropertiesOfT<Prof>::destructible_support> {
-  static_assert(std::is_same<Enabler, void>::value,
-                "An explicit type must not be passed as the second template "
-                "argument to 'Archetype`.");
-
-  // The cases mentioned in these static_asserts are expected to be handled in
-  // the partial template specializations of Archetype that follow this
-  // definition.
-  static_assert(PropertiesOfT<Prof>::destructible_support !=
-                    destructible::maybe,
-                "");
-  static_assert(PropertiesOfT<Prof>::move_constructible_support !=
-                        move_constructible::maybe ||
-                    PropertiesOfT<Prof>::copy_constructible_support ==
-                        copy_constructible::maybe,
-                "");
-  static_assert(PropertiesOfT<Prof>::move_assignable_support !=
-                        move_assignable::maybe ||
-                    PropertiesOfT<Prof>::copy_assignable_support ==
-                        copy_assignable::maybe,
-                "");
-
- public:
-  Archetype() = default;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support !=
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support ==
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support !=
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = default;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = delete;
-  Archetype& operator=(const Archetype&) = default;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support ==
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support ==
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support !=
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = delete;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = delete;
-  Archetype& operator=(const Archetype&) = default;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support ==
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support !=
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support !=
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = delete;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = default;
-  Archetype& operator=(const Archetype&) = default;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support !=
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support ==
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support ==
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = default;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = delete;
-  Archetype& operator=(const Archetype&) = default;
-  ~Archetype() = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support ==
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support ==
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support ==
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = delete;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = delete;
-  Archetype& operator=(const Archetype&) = default;
-  ~Archetype() = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-template <class Prof>
-class Archetype<Prof, typename std::enable_if<
-                          PropertiesOfT<Prof>::move_constructible_support ==
-                              move_constructible::maybe &&
-                          PropertiesOfT<Prof>::move_assignable_support !=
-                              move_assignable::maybe &&
-                          PropertiesOfT<Prof>::destructible_support ==
-                              destructible::maybe>::type>
-    : ArchetypeSpecialMembersBase<
-          PropertiesOfT<Prof>::default_constructible_support,
-          PropertiesOfT<Prof>::move_constructible_support,
-          PropertiesOfT<Prof>::copy_constructible_support,
-          PropertiesOfT<Prof>::move_assignable_support,
-          PropertiesOfT<Prof>::copy_assignable_support,
-          PropertiesOfT<Prof>::destructible_support> {
- public:
-  Archetype() = default;
-  Archetype(Archetype&&) = delete;
-  Archetype(const Archetype&) = default;
-  Archetype& operator=(Archetype&&) = default;
-  Archetype& operator=(const Archetype&) = default;
-  ~Archetype() = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
-  Archetype(T&&) = delete;
-
-  // Disallow moves when requested, and disallow implicit conversions.
-  template <class T, typename std::enable_if<
-                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
-  Archetype& operator=(T&&) = delete;
-
-  using ArchetypeSpecialMembersBase<
-      PropertiesOfT<Prof>::default_constructible_support,
-      PropertiesOfT<Prof>::move_constructible_support,
-      PropertiesOfT<Prof>::copy_constructible_support,
-      PropertiesOfT<Prof>::move_assignable_support,
-      PropertiesOfT<Prof>::copy_assignable_support,
-      PropertiesOfT<Prof>::destructible_support>::archetype_state;
-
- private:
-  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
-      : ArchetypeSpecialMembersBase<
-            PropertiesOfT<Prof>::default_constructible_support,
-            PropertiesOfT<Prof>::move_constructible_support,
-            PropertiesOfT<Prof>::copy_constructible_support,
-            PropertiesOfT<Prof>::move_assignable_support,
-            PropertiesOfT<Prof>::copy_assignable_support,
-            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
-                                                       state) {}
-
-  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
-};
-
-// Explicitly deleted swap for Archetype if the profile does not require swap.
-// It is important to delete it rather than simply leave it out so that the
-// "using std::swap;" idiom will result in this deleted overload being picked.
-template <class Prof,
-          absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0>
-void swap(Archetype<Prof>&, Archetype<Prof>&) = delete;  // NOLINT
-
-// A conditionally-noexcept swap implementation for Archetype when the profile
-// supports swap.
-template <class Prof,
-          absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0>
-void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs)  // NOLINT
-    noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) {
-  std::swap(lhs.archetype_state, rhs.archetype_state);
-}
-
-// A convertible-to-bool type that is used as the return type of comparison
-// operators since the standard doesn't always require exactly bool.
-struct NothrowBool {
-  explicit NothrowBool() = delete;
-  ~NothrowBool() = default;
-
-  // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
-  // elision makes it not required when returning from a function.
-  // NothrowBool(NothrowBool const&) = delete;
-
-  NothrowBool& operator=(NothrowBool const&) = delete;
-
-  explicit operator bool() const noexcept { return value; }
-
-  static NothrowBool make(bool const value) noexcept {
-    return NothrowBool(value);
-  }
-
- private:
-  explicit NothrowBool(bool const value) noexcept : value(value) {}
-
-  bool value;
-};
-
-// A convertible-to-bool type that is used as the return type of comparison
-// operators since the standard doesn't always require exactly bool.
-// Note: ExceptionalBool has a conversion operator that is not noexcept, so
-// that even when a comparison operator is noexcept, that operation may still
-// potentially throw when converted to bool.
-struct ExceptionalBool {
-  explicit ExceptionalBool() = delete;
-  ~ExceptionalBool() = default;
-
-  // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
-  // elision makes it not required when returning from a function.
-  // ExceptionalBool(ExceptionalBool const&) = delete;
-
-  ExceptionalBool& operator=(ExceptionalBool const&) = delete;
-
-  explicit operator bool() const { return value; }  // NOLINT
-
-  static ExceptionalBool make(bool const value) noexcept {
-    return ExceptionalBool(value);
-  }
-
- private:
-  explicit ExceptionalBool(bool const value) noexcept : value(value) {}
-
-  bool value;
-};
-
-// The following macro is only used as a helper in this file to stamp out
-// comparison operator definitions. It is undefined after usage.
-//
-// NOTE: Non-nothrow operators throw via their result's conversion to bool even
-// though the operation itself is noexcept.
-#define ABSL_TYPES_INTERNAL_OP(enum_name, op)                                \
-  template <class Prof>                                                      \
-  absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \
-      const Archetype<Prof>&, const Archetype<Prof>&) = delete;              \
-                                                                             \
-  template <class Prof>                                                      \
-  typename absl::enable_if_t<                                                \
-      PropertiesOfT<Prof>::is_##enum_name,                                   \
-      std::conditional<PropertiesOfT<Prof>::enum_name##_support ==           \
-                           enum_name::nothrow,                               \
-                       NothrowBool, ExceptionalBool>>::type                  \
-  operator op(const Archetype<Prof>& lhs,                                    \
-              const Archetype<Prof>& rhs) noexcept {                         \
-    return absl::conditional_t<                                              \
-        PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow,      \
-        NothrowBool, ExceptionalBool>::make(lhs.archetype_state op           \
-                                                rhs.archetype_state);        \
-  }
-
-ABSL_TYPES_INTERNAL_OP(equality_comparable, ==);
-ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=);
-ABSL_TYPES_INTERNAL_OP(less_than_comparable, <);
-ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=);
-ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=);
-ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >);
-
-#undef ABSL_TYPES_INTERNAL_OP
-
-// Base class for std::hash specializations when an Archetype doesn't support
-// hashing.
-struct PoisonedHash {
-  PoisonedHash() = delete;
-  PoisonedHash(const PoisonedHash&) = delete;
-  PoisonedHash& operator=(const PoisonedHash&) = delete;
-};
-
-// Base class for std::hash specializations when an Archetype supports hashing.
-template <class Prof>
-struct EnabledHash {
-  using argument_type = Archetype<Prof>;
-  using result_type = std::size_t;
-  result_type operator()(const argument_type& arg) const {
-    return std::hash<ArchetypeState>()(arg.archetype_state);
-  }
-};
-
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-namespace std {
-
-template <class Prof>  // NOLINT
-struct hash<::absl::types_internal::Archetype<Prof>>
-    : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable,
-                  ::absl::types_internal::EnabledHash<Prof>,
-                  ::absl::types_internal::PoisonedHash>::type {};
-
-}  // namespace std
-
-#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_profile.h b/third_party/abseil-cpp/absl/types/internal/conformance_profile.h
deleted file mode 100644
index 37b017db..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_profile.h
+++ /dev/null
@@ -1,933 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// conformance_profiles.h
-// -----------------------------------------------------------------------------
-//
-// This file contains templates for representing "Regularity Profiles" and
-// concisely-named versions of commonly used Regularity Profiles.
-//
-// A Regularity Profile is a compile-time description of the types of operations
-// that a given type supports, along with properties of those operations when
-// they do exist. For instance, a Regularity Profile may describe a type that
-// has a move-constructor that is noexcept and a copy constructor that is not
-// noexcept. This description can then be examined and passed around to other
-// templates for the purposes of asserting expectations on user-defined types
-// via a series trait checks, or for determining what kinds of run-time tests
-// are able to be performed.
-//
-// Regularity Profiles are also used when creating "archetypes," which are
-// minimum-conforming types that meet all of the requirements of a given
-// Regularity Profile. For more information regarding archetypes, see
-// "conformance_archetypes.h".
-
-#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
-#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
-
-#include <set>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "absl/algorithm/container.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/ascii.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/internal/conformance_testing_helpers.h"
-#include "absl/utility/utility.h"
-
-// TODO(calabrese) Add support for extending profiles.
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-
-// Converts an enum to its underlying integral value.
-template <typename Enum>
-constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) {
-  return static_cast<absl::underlying_type_t<Enum>>(value);
-}
-
-// A tag type used in place of a matcher when checking that an assertion result
-// does not actually contain any errors.
-struct NoError {};
-
-// -----------------------------------------------------------------------------
-// ConformanceErrors
-// -----------------------------------------------------------------------------
-class ConformanceErrors {
- public:
-  // Setup the error reporting mechanism by seeding it with the name of the type
-  // that is being tested.
-  explicit ConformanceErrors(std::string type_name)
-      : assertion_result_(false), type_name_(std::move(type_name)) {
-    assertion_result_ << "\n\n"
-                         "Assuming the following type alias:\n"
-                         "\n"
-                         "  using _T = "
-                      << type_name_ << ";\n\n";
-    outputDivider();
-  }
-
-  // Adds the test name to the list of successfully run tests iff it was not
-  // previously reported as failing. This behavior is useful for tests that
-  // have multiple parts, where failures and successes are reported individually
-  // with the same test name.
-  void addTestSuccess(absl::string_view test_name) {
-    auto normalized_test_name = absl::AsciiStrToLower(test_name);
-
-    // If the test is already reported as failing, do not add it to the list of
-    // successes.
-    if (test_failures_.find(normalized_test_name) == test_failures_.end()) {
-      test_successes_.insert(std::move(normalized_test_name));
-    }
-  }
-
-  // Streams a single error description into the internal buffer (a visual
-  // divider is automatically inserted after the error so that multiple errors
-  // are visibly distinct).
-  //
-  // This function increases the error count by 1.
-  //
-  // TODO(calabrese) Determine desired behavior when if this function throws.
-  template <class... P>
-  void addTestFailure(absl::string_view test_name, const P&... args) {
-    // Output a message related to the test failure.
-    assertion_result_ << "\n\n"
-                         "Failed test: "
-                      << test_name << "\n\n";
-    addTestFailureImpl(args...);
-    assertion_result_ << "\n\n";
-    outputDivider();
-
-    auto normalized_test_name = absl::AsciiStrToLower(test_name);
-
-    // If previous parts of this test succeeded, remove it from that set.
-    test_successes_.erase(normalized_test_name);
-
-    // Add the test name to the list of failed tests.
-    test_failures_.insert(std::move(normalized_test_name));
-
-    has_error_ = true;
-  }
-
-  // Convert this object into a testing::AssertionResult instance such that it
-  // can be used with gtest.
-  ::testing::AssertionResult assertionResult() const {
-    return has_error_ ? assertion_result_ : ::testing::AssertionSuccess();
-  }
-
-  // Convert this object into a testing::AssertionResult instance such that it
-  // can be used with gtest. This overload expects errors, using the specified
-  // matcher.
-  ::testing::AssertionResult expectFailedTests(
-      const std::set<std::string>& test_names) const {
-    // Since we are expecting nonconformance, output an error message when the
-    // type actually conformed to the specified profile.
-    if (!has_error_) {
-      return ::testing::AssertionFailure()
-             << "Unexpected conformance of type:\n"
-                "    "
-             << type_name_ << "\n\n";
-    }
-
-    // Get a list of all expected failures that did not actually fail
-    // (or that were not run).
-    std::vector<std::string> nonfailing_tests;
-    absl::c_set_difference(test_names, test_failures_,
-                           std::back_inserter(nonfailing_tests));
-
-    // Get a list of all "expected failures" that were never actually run.
-    std::vector<std::string> unrun_tests;
-    absl::c_set_difference(nonfailing_tests, test_successes_,
-                           std::back_inserter(unrun_tests));
-
-    // Report when the user specified tests that were not run.
-    if (!unrun_tests.empty()) {
-      const bool tests_were_run =
-          !(test_failures_.empty() && test_successes_.empty());
-
-      // Prepare an assertion result used in the case that tests pass that were
-      // expected to fail.
-      ::testing::AssertionResult result = ::testing::AssertionFailure();
-      result << "When testing type:\n    " << type_name_
-             << "\n\nThe following tests were expected to fail but were not "
-                "run";
-
-      if (tests_were_run) result << " (was the test name spelled correctly?)";
-
-      result << ":\n\n";
-
-      // List all of the tests that unexpectedly passed.
-      for (const auto& test_name : unrun_tests) {
-        result << "    " << test_name << "\n";
-      }
-
-      if (!tests_were_run) result << "\nNo tests were run.";
-
-      if (!test_failures_.empty()) {
-        // List test failures
-        result << "\nThe tests that were run and failed are:\n\n";
-        for (const auto& test_name : test_failures_) {
-          result << "    " << test_name << "\n";
-        }
-      }
-
-      if (!test_successes_.empty()) {
-        // List test successes
-        result << "\nThe tests that were run and succeeded are:\n\n";
-        for (const auto& test_name : test_successes_) {
-          result << "    " << test_name << "\n";
-        }
-      }
-
-      return result;
-    }
-
-    // If some tests passed when they were expected to fail, alert the caller.
-    if (nonfailing_tests.empty()) return ::testing::AssertionSuccess();
-
-    // Prepare an assertion result used in the case that tests pass that were
-    // expected to fail.
-    ::testing::AssertionResult unexpected_successes =
-        ::testing::AssertionFailure();
-    unexpected_successes << "When testing type:\n    " << type_name_
-                         << "\n\nThe following tests passed when they were "
-                            "expected to fail:\n\n";
-
-    // List all of the tests that unexpectedly passed.
-    for (const auto& test_name : nonfailing_tests) {
-      unexpected_successes << "    " << test_name << "\n";
-    }
-
-    return unexpected_successes;
-  }
-
- private:
-  void outputDivider() {
-    assertion_result_ << "========================================";
-  }
-
-  void addTestFailureImpl() {}
-
-  template <class H, class... T>
-  void addTestFailureImpl(const H& head, const T&... tail) {
-    assertion_result_ << head;
-    addTestFailureImpl(tail...);
-  }
-
-  ::testing::AssertionResult assertion_result_;
-  std::set<std::string> test_failures_;
-  std::set<std::string> test_successes_;
-  std::string type_name_;
-  bool has_error_ = false;
-};
-
-template <class T, class /*Enabler*/ = void>
-struct PropertiesOfImpl {};
-
-template <class T>
-struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> {
-  using type = typename T::properties;
-};
-
-template <class T>
-struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> {
-  using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type;
-};
-
-template <class T>
-struct PropertiesOf : PropertiesOfImpl<T> {};
-
-template <class T>
-using PropertiesOfT = typename PropertiesOf<T>::type;
-
-// NOTE: These enums use this naming convention to be consistent with the
-// standard trait names, which is useful since it allows us to match up each
-// enum name with a corresponding trait name in macro definitions.
-
-// An enum that describes the various expectations on an operations existence.
-enum class function_support { maybe, yes, nothrow, trivial };
-
-constexpr const char* PessimisticPropertyDescription(function_support v) {
-  return v == function_support::maybe
-             ? "no"
-             : v == function_support::yes
-                   ? "yes, potentially throwing"
-                   : v == function_support::nothrow ? "yes, nothrow"
-                                                    : "yes, trivial";
-}
-
-// Return a string that describes the kind of property support that was
-// expected.
-inline std::string ExpectedFunctionKindList(function_support min,
-                                            function_support max) {
-  if (min == max) {
-    std::string result =
-        absl::StrCat("Expected:\n  ",
-                     PessimisticPropertyDescription(
-                         static_cast<function_support>(UnderlyingValue(min))),
-                     "\n");
-    return result;
-  }
-
-  std::string result = "Expected one of:\n";
-  for (auto curr_support = UnderlyingValue(min);
-       curr_support <= UnderlyingValue(max); ++curr_support) {
-    absl::StrAppend(&result, "  ",
-                    PessimisticPropertyDescription(
-                        static_cast<function_support>(curr_support)),
-                    "\n");
-  }
-
-  return result;
-}
-
-template <class Enum>
-void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support,
-                       Enum max_support, Enum kind) {
-  const auto kind_value = UnderlyingValue(kind);
-  const auto min_support_value = UnderlyingValue(min_support);
-  const auto max_support_value = UnderlyingValue(max_support);
-
-  if (!(kind_value >= min_support_value && kind_value <= max_support_value)) {
-    errors->addTestFailure(
-        PropertyName(kind), "**Failed property expectation**\n\n",
-        ExpectedFunctionKindList(
-            static_cast<function_support>(min_support_value),
-            static_cast<function_support>(max_support_value)),
-        '\n', "Actual:\n  ",
-        PessimisticPropertyDescription(
-            static_cast<function_support>(kind_value)));
-  } else {
-    errors->addTestSuccess(PropertyName(kind));
-  }
-}
-
-#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \
-  enum class name { maybe, yes, nothrow, trivial };                   \
-                                                                      \
-  constexpr const char* PropertyName(name v) { return description; }  \
-  static_assert(true, "")  // Force a semicolon when using this macro.
-
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction",
-                                           default_constructible);
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction",
-                                           move_constructible);
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction",
-                                           copy_constructible);
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment",
-                                           move_assignable);
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment",
-                                           copy_assignable);
-ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction",
-                                           destructible);
-
-#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM
-
-#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name)     \
-  enum class name { maybe, yes, nothrow };                           \
-                                                                     \
-  constexpr const char* PropertyName(name v) { return description; } \
-  static_assert(true, "")  // Force a semicolon when using this macro.
-
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=",
-                                      greater_equal_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable);
-
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable);
-
-#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM
-
-enum class hashable { maybe, yes };
-
-constexpr const char* PropertyName(hashable v) {
-  return "support for std::hash";
-}
-
-template <class T>
-using AlwaysFalse = std::false_type;
-
-#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property)   \
-  template <class T>                                                        \
-  constexpr property property##_support_of() {                              \
-    return std::is_##property<T>::value                                     \
-               ? std::is_nothrow_##property<T>::value                       \
-                     ? absl::is_trivially_##property<T>::value              \
-                           ? property::trivial                              \
-                           : property::nothrow                              \
-                     : property::yes                                        \
-               : property::maybe;                                           \
-  }                                                                         \
-                                                                            \
-  template <class T, class MinProf, class MaxProf>                          \
-  void ExpectModelOf##name(ConformanceErrors* errors) {                     \
-    (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \
-                        PropertiesOfT<MaxProf>::property##_support,         \
-                        property##_support_of<T>());                        \
-  }
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible,
-                                                  default_constructible);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible,
-                                                  move_constructible);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible,
-                                                  copy_constructible);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable,
-                                                  move_assignable);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable,
-                                                  copy_assignable);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible);
-
-#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER
-
-void BoolFunction(bool) noexcept;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction for checking if an operation exists through SFINAE.
-//
-// `T` is the type to test and Op is an alias containing the expression to test.
-template <class T, template <class...> class Op, class = void>
-struct IsOpableImpl : std::false_type {};
-
-template <class T, template <class...> class Op>
-struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {};
-
-template <template <class...> class Op>
-struct IsOpable {
-  template <class T>
-  using apply = typename IsOpableImpl<T, Op>::type;
-};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction for checking if an operation exists and is also noexcept
-// through SFINAE and the noexcept operator.
-///
-// `T` is the type to test and Op is an alias containing the expression to test.
-template <class T, template <class...> class Op, class = void>
-struct IsNothrowOpableImpl : std::false_type {};
-
-template <class T, template <class...> class Op>
-struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>>
-    : std::true_type {};
-
-template <template <class...> class Op>
-struct IsNothrowOpable {
-  template <class T>
-  using apply = typename IsNothrowOpableImpl<T, Op>::type;
-};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A macro that produces the necessary function for reporting what kind of
-// support a specific comparison operation has and a function for reporting an
-// error if a given type's support for that operation does not meet the expected
-// requirements.
-#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op)      \
-  template <class T,                                                           \
-            class Result = std::integral_constant<                             \
-                bool, noexcept((BoolFunction)(std::declval<const T&>() op      \
-                                                  std::declval<const T&>()))>> \
-  using name = Result;                                                         \
-                                                                               \
-  template <class T>                                                           \
-  constexpr property property##_support_of() {                                 \
-    return IsOpable<name>::apply<T>::value                                     \
-               ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow    \
-                                                        : property::yes        \
-               : property::maybe;                                              \
-  }                                                                            \
-                                                                               \
-  template <class T, class MinProf, class MaxProf>                             \
-  void ExpectModelOf##name(ConformanceErrors* errors) {                        \
-    (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support,    \
-                        PropertiesOfT<MaxProf>::property##_support,            \
-                        property##_support_of<T>());                           \
-  }
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Generate the necessary support-checking and error reporting functions for
-// each of the comparison operators.
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable,
-                                              equality_comparable, ==);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable,
-                                              inequality_comparable, !=);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable,
-                                              less_than_comparable, <);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable,
-                                              less_equal_comparable, <=);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable,
-                                              greater_equal_comparable, >=);
-
-ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable,
-                                              greater_than_comparable, >);
-
-#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// The necessary support-checking and error-reporting functions for swap.
-template <class T>
-constexpr swappable swappable_support_of() {
-  return type_traits_internal::IsSwappable<T>::value
-             ? type_traits_internal::IsNothrowSwappable<T>::value
-                   ? swappable::nothrow
-                   : swappable::yes
-             : swappable::maybe;
-}
-
-template <class T, class MinProf, class MaxProf>
-void ExpectModelOfSwappable(ConformanceErrors* errors) {
-  (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support,
-                      PropertiesOfT<MaxProf>::swappable_support,
-                      swappable_support_of<T>());
-}
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// The necessary support-checking and error-reporting functions for std::hash.
-template <class T>
-constexpr hashable hashable_support_of() {
-  return type_traits_internal::IsHashable<T>::value ? hashable::yes
-                                                    : hashable::maybe;
-}
-
-template <class T, class MinProf, class MaxProf>
-void ExpectModelOfHashable(ConformanceErrors* errors) {
-  (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support,
-                      PropertiesOfT<MaxProf>::hashable_support,
-                      hashable_support_of<T>());
-}
-//
-////////////////////////////////////////////////////////////////////////////////
-
-template <
-    default_constructible DefaultConstructibleValue =
-        default_constructible::maybe,
-    move_constructible MoveConstructibleValue = move_constructible::maybe,
-    copy_constructible CopyConstructibleValue = copy_constructible::maybe,
-    move_assignable MoveAssignableValue = move_assignable::maybe,
-    copy_assignable CopyAssignableValue = copy_assignable::maybe,
-    destructible DestructibleValue = destructible::maybe,
-    equality_comparable EqualityComparableValue = equality_comparable::maybe,
-    inequality_comparable InequalityComparableValue =
-        inequality_comparable::maybe,
-    less_than_comparable LessThanComparableValue = less_than_comparable::maybe,
-    less_equal_comparable LessEqualComparableValue =
-        less_equal_comparable::maybe,
-    greater_equal_comparable GreaterEqualComparableValue =
-        greater_equal_comparable::maybe,
-    greater_than_comparable GreaterThanComparableValue =
-        greater_than_comparable::maybe,
-    swappable SwappableValue = swappable::maybe,
-    hashable HashableValue = hashable::maybe>
-struct ConformanceProfile {
-  using properties = ConformanceProfile;
-
-  static constexpr default_constructible
-      default_constructible_support =  // NOLINT
-      DefaultConstructibleValue;
-
-  static constexpr move_constructible move_constructible_support =  // NOLINT
-      MoveConstructibleValue;
-
-  static constexpr copy_constructible copy_constructible_support =  // NOLINT
-      CopyConstructibleValue;
-
-  static constexpr move_assignable move_assignable_support =  // NOLINT
-      MoveAssignableValue;
-
-  static constexpr copy_assignable copy_assignable_support =  // NOLINT
-      CopyAssignableValue;
-
-  static constexpr destructible destructible_support =  // NOLINT
-      DestructibleValue;
-
-  static constexpr equality_comparable equality_comparable_support =  // NOLINT
-      EqualityComparableValue;
-
-  static constexpr inequality_comparable
-      inequality_comparable_support =  // NOLINT
-      InequalityComparableValue;
-
-  static constexpr less_than_comparable
-      less_than_comparable_support =  // NOLINT
-      LessThanComparableValue;
-
-  static constexpr less_equal_comparable
-      less_equal_comparable_support =  // NOLINT
-      LessEqualComparableValue;
-
-  static constexpr greater_equal_comparable
-      greater_equal_comparable_support =  // NOLINT
-      GreaterEqualComparableValue;
-
-  static constexpr greater_than_comparable
-      greater_than_comparable_support =  // NOLINT
-      GreaterThanComparableValue;
-
-  static constexpr swappable swappable_support = SwappableValue;  // NOLINT
-
-  static constexpr hashable hashable_support = HashableValue;  // NOLINT
-
-  static constexpr bool is_default_constructible =  // NOLINT
-      DefaultConstructibleValue != default_constructible::maybe;
-
-  static constexpr bool is_move_constructible =  // NOLINT
-      MoveConstructibleValue != move_constructible::maybe;
-
-  static constexpr bool is_copy_constructible =  // NOLINT
-      CopyConstructibleValue != copy_constructible::maybe;
-
-  static constexpr bool is_move_assignable =  // NOLINT
-      MoveAssignableValue != move_assignable::maybe;
-
-  static constexpr bool is_copy_assignable =  // NOLINT
-      CopyAssignableValue != copy_assignable::maybe;
-
-  static constexpr bool is_destructible =  // NOLINT
-      DestructibleValue != destructible::maybe;
-
-  static constexpr bool is_equality_comparable =  // NOLINT
-      EqualityComparableValue != equality_comparable::maybe;
-
-  static constexpr bool is_inequality_comparable =  // NOLINT
-      InequalityComparableValue != inequality_comparable::maybe;
-
-  static constexpr bool is_less_than_comparable =  // NOLINT
-      LessThanComparableValue != less_than_comparable::maybe;
-
-  static constexpr bool is_less_equal_comparable =  // NOLINT
-      LessEqualComparableValue != less_equal_comparable::maybe;
-
-  static constexpr bool is_greater_equal_comparable =  // NOLINT
-      GreaterEqualComparableValue != greater_equal_comparable::maybe;
-
-  static constexpr bool is_greater_than_comparable =  // NOLINT
-      GreaterThanComparableValue != greater_than_comparable::maybe;
-
-  static constexpr bool is_swappable =  // NOLINT
-      SwappableValue != swappable::maybe;
-
-  static constexpr bool is_hashable =  // NOLINT
-      HashableValue != hashable::maybe;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Compliant SFINAE-friendliness is not always present on the standard library
-// implementations that we support. This helper-struct (and associated enum) is
-// used as a means to conditionally check the hashability support of a type.
-enum class CheckHashability { no, yes };
-
-template <class T, CheckHashability ShouldCheckHashability>
-struct conservative_hashable_support_of;
-
-template <class T>
-struct conservative_hashable_support_of<T, CheckHashability::no> {
-  static constexpr hashable Invoke() { return hashable::maybe; }
-};
-
-template <class T>
-struct conservative_hashable_support_of<T, CheckHashability::yes> {
-  static constexpr hashable Invoke() { return hashable_support_of<T>(); }
-};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// The ConformanceProfile that is expected based on introspection into the type
-// by way of trait checks.
-template <class T, CheckHashability ShouldCheckHashability>
-struct SyntacticConformanceProfileOf {
-  using properties = ConformanceProfile<
-      default_constructible_support_of<T>(), move_constructible_support_of<T>(),
-      copy_constructible_support_of<T>(), move_assignable_support_of<T>(),
-      copy_assignable_support_of<T>(), destructible_support_of<T>(),
-      equality_comparable_support_of<T>(),
-      inequality_comparable_support_of<T>(),
-      less_than_comparable_support_of<T>(),
-      less_equal_comparable_support_of<T>(),
-      greater_equal_comparable_support_of<T>(),
-      greater_than_comparable_support_of<T>(), swappable_support_of<T>(),
-      conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>;
-};
-
-#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name)     \
-  template <default_constructible DefaultConstructibleValue,                   \
-            move_constructible MoveConstructibleValue,                         \
-            copy_constructible CopyConstructibleValue,                         \
-            move_assignable MoveAssignableValue,                               \
-            copy_assignable CopyAssignableValue,                               \
-            destructible DestructibleValue,                                    \
-            equality_comparable EqualityComparableValue,                       \
-            inequality_comparable InequalityComparableValue,                   \
-            less_than_comparable LessThanComparableValue,                      \
-            less_equal_comparable LessEqualComparableValue,                    \
-            greater_equal_comparable GreaterEqualComparableValue,              \
-            greater_than_comparable GreaterThanComparableValue,                \
-            swappable SwappableValue, hashable HashableValue>                  \
-  constexpr type ConformanceProfile<                                           \
-      DefaultConstructibleValue, MoveConstructibleValue,                       \
-      CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue,        \
-      DestructibleValue, EqualityComparableValue, InequalityComparableValue,   \
-      LessThanComparableValue, LessEqualComparableValue,                       \
-      GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \
-      HashableValue>::name
-
-#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type)           \
-  ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type,            \
-                                                         type##_support); \
-  ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type)
-
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable);
-ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable);
-#endif
-
-#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF
-#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL
-
-// Retrieve the enum with the minimum underlying value.
-// Note: std::min is not constexpr in C++11, which is why this is necessary.
-template <class H>
-constexpr H MinEnum(H head) {
-  return head;
-}
-
-template <class H, class N, class... T>
-constexpr H MinEnum(H head, N next, T... tail) {
-  return (UnderlyingValue)(head) < (UnderlyingValue)(next)
-             ? (MinEnum)(head, tail...)
-             : (MinEnum)(next, tail...);
-}
-
-template <class... Profs>
-struct MinimalProfiles {
-  static constexpr default_constructible
-      default_constructible_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...);
-
-  static constexpr move_constructible move_constructible_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...);
-
-  static constexpr copy_constructible copy_constructible_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
-
-  static constexpr move_assignable move_assignable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...);
-
-  static constexpr copy_assignable copy_assignable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
-
-  static constexpr destructible destructible_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::destructible_support...);
-
-  static constexpr equality_comparable equality_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
-
-  static constexpr inequality_comparable
-      inequality_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
-
-  static constexpr less_than_comparable
-      less_than_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
-
-  static constexpr less_equal_comparable
-      less_equal_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
-
-  static constexpr greater_equal_comparable
-      greater_equal_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
-
-  static constexpr greater_than_comparable
-      greater_than_comparable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
-
-  static constexpr swappable swappable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::swappable_support...);
-
-  static constexpr hashable hashable_support =  // NOLINT
-      (MinEnum)(PropertiesOfT<Profs>::hashable_support...);
-
-  using properties = ConformanceProfile<
-      default_constructible_support, move_constructible_support,
-      copy_constructible_support, move_assignable_support,
-      copy_assignable_support, destructible_support,
-      equality_comparable_support, inequality_comparable_support,
-      less_than_comparable_support, less_equal_comparable_support,
-      greater_equal_comparable_support, greater_than_comparable_support,
-      swappable_support, hashable_support>;
-};
-
-// Retrieve the enum with the greatest underlying value.
-// Note: std::max is not constexpr in C++11, which is why this is necessary.
-template <class H>
-constexpr H MaxEnum(H head) {
-  return head;
-}
-
-template <class H, class N, class... T>
-constexpr H MaxEnum(H head, N next, T... tail) {
-  return (UnderlyingValue)(next) < (UnderlyingValue)(head)
-             ? (MaxEnum)(head, tail...)
-             : (MaxEnum)(next, tail...);
-}
-
-template <class... Profs>
-struct CombineProfilesImpl {
-  static constexpr default_constructible
-      default_constructible_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...);
-
-  static constexpr move_constructible move_constructible_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...);
-
-  static constexpr copy_constructible copy_constructible_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
-
-  static constexpr move_assignable move_assignable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...);
-
-  static constexpr copy_assignable copy_assignable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
-
-  static constexpr destructible destructible_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::destructible_support...);
-
-  static constexpr equality_comparable equality_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
-
-  static constexpr inequality_comparable
-      inequality_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
-
-  static constexpr less_than_comparable
-      less_than_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
-
-  static constexpr less_equal_comparable
-      less_equal_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
-
-  static constexpr greater_equal_comparable
-      greater_equal_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
-
-  static constexpr greater_than_comparable
-      greater_than_comparable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
-
-  static constexpr swappable swappable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::swappable_support...);
-
-  static constexpr hashable hashable_support =  // NOLINT
-      (MaxEnum)(PropertiesOfT<Profs>::hashable_support...);
-
-  using properties = ConformanceProfile<
-      default_constructible_support, move_constructible_support,
-      copy_constructible_support, move_assignable_support,
-      copy_assignable_support, destructible_support,
-      equality_comparable_support, inequality_comparable_support,
-      less_than_comparable_support, less_equal_comparable_support,
-      greater_equal_comparable_support, greater_than_comparable_support,
-      swappable_support, hashable_support>;
-};
-
-// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that
-// when named aliases of CombineProfiles are created (such as in
-// conformance_aliases.h), we only pay for the combination algorithm on the
-// profiles that are actually used.
-template <class... Profs>
-struct CombineProfiles {
-  using profile_alias_of = CombineProfilesImpl<Profs...>;
-};
-
-template <>
-struct CombineProfiles<> {
-  using properties = ConformanceProfile<>;
-};
-
-template <class Profile, class Tag>
-struct StrongProfileTypedef {
-  using properties = PropertiesOfT<Profile>;
-};
-
-template <class T, class /*Enabler*/ = void>
-struct IsProfileImpl : std::false_type {};
-
-template <class T>
-struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {};
-
-template <class T>
-struct IsProfile : IsProfileImpl<T>::type {};
-
-// A tag that describes which set of properties we will check when the user
-// requires a strict match in conformance (as opposed to a loose match which
-// allows more-refined support of any given operation).
-//
-// Currently only the RegularityDomain exists and it includes all operations
-// that the conformance testing suite knows about. The intent is that if the
-// suite is expanded to support extension, such as for checking conformance of
-// concepts like Iterators or Containers, additional corresponding domains can
-// be created.
-struct RegularityDomain {};
-
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_testing.h b/third_party/abseil-cpp/absl/types/internal/conformance_testing.h
deleted file mode 100644
index 487b0f78..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing.h
+++ /dev/null
@@ -1,1386 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// conformance_testing.h
-// -----------------------------------------------------------------------------
-//
-
-#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
-#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
-
-////////////////////////////////////////////////////////////////////////////////
-//                                                                            //
-// Many templates in this file take a `T` and a `Prof` type as explicit       //
-// template arguments. These are a type to be checked and a                   //
-// "Regularity Profile" that describes what operations that type `T` is       //
-// expected to support. See "regularity_profiles.h" for more details          //
-// regarding Regularity Profiles.                                             //
-//                                                                            //
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cstddef>
-#include <set>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-#include "gtest/gtest.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/ascii.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/internal/conformance_aliases.h"
-#include "absl/types/internal/conformance_archetype.h"
-#include "absl/types/internal/conformance_profile.h"
-#include "absl/types/internal/conformance_testing_helpers.h"
-#include "absl/types/internal/parentheses.h"
-#include "absl/types/internal/transform_args.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-
-// Returns true if the compiler incorrectly greedily instantiates constexpr
-// templates in any unevaluated context.
-constexpr bool constexpr_instantiation_when_unevaluated() {
-#if defined(__apple_build_version__)  // TODO(calabrese) Make more specific
-  return true;
-#elif defined(__clang__)
-  return __clang_major__ < 4;
-#elif defined(__GNUC__)
-  // TODO(calabrese) Figure out why gcc 7 fails (seems like a different bug)
-  return __GNUC__ < 5 || (__GNUC__ == 5 && __GNUC_MINOR__ < 2) || __GNUC__ >= 7;
-#else
-  return false;
-#endif
-}
-
-// Returns true if the standard library being used incorrectly produces an error
-// when instantiating the definition of a poisoned std::hash specialization.
-constexpr bool poisoned_hash_fails_instantiation() {
-#if defined(_MSC_VER) && !defined(_LIBCPP_VERSION)
-  return _MSC_VER < 1914;
-#else
-  return false;
-#endif
-}
-
-template <class Fun>
-struct GeneratorType {
-  decltype(std::declval<const Fun&>()()) operator()() const
-      noexcept(noexcept(std::declval<const Fun&>()())) {
-    return fun();
-  }
-
-  Fun fun;
-  const char* description;
-};
-
-// A "make" function for the GeneratorType template that deduces the function
-// object type.
-template <class Fun,
-          absl::enable_if_t<IsNullaryCallable<Fun>::value>** = nullptr>
-GeneratorType<Fun> Generator(Fun fun, const char* description) {
-  return GeneratorType<Fun>{absl::move(fun), description};
-}
-
-// A type that contains a set of nullary function objects that each return an
-// instance of the same type and value (though possibly different
-// representations, such as +0 and -0 or two vectors with the same elements but
-// with different capacities).
-template <class... Funs>
-struct EquivalenceClassType {
-  std::tuple<GeneratorType<Funs>...> generators;
-};
-
-// A "make" function for the EquivalenceClassType template that deduces the
-// function object types and is constrained such that a user can only pass in
-// function objects that all have the same return type.
-template <class... Funs, absl::enable_if_t<AreGeneratorsWithTheSameReturnType<
-                             Funs...>::value>** = nullptr>
-EquivalenceClassType<Funs...> EquivalenceClass(GeneratorType<Funs>... funs) {
-  return {std::make_tuple(absl::move(funs)...)};
-}
-
-// A type that contains an ordered series of EquivalenceClassTypes, from
-// smallest value to largest value.
-template <class... EqClasses>
-struct OrderedEquivalenceClasses {
-  std::tuple<EqClasses...> eq_classes;
-};
-
-// An object containing the parts of a given (name, initialization expression),
-// and is capable of generating a string that describes the given.
-struct GivenDeclaration {
-  std::string outputDeclaration(std::size_t width) const {
-    const std::size_t indent_size = 2;
-    std::string result = absl::StrCat("  ", name);
-
-    if (!expression.empty()) {
-      // Indent
-      result.resize(indent_size + width, ' ');
-      absl::StrAppend(&result, " = ", expression, ";\n");
-    } else {
-      absl::StrAppend(&result, ";\n");
-    }
-
-    return result;
-  }
-
-  std::string name;
-  std::string expression;
-};
-
-// Produce a string that contains all of the givens of an error report.
-template <class... Decls>
-std::string PrepareGivenContext(const Decls&... decls) {
-  const std::size_t width = (std::max)({decls.name.size()...});
-  return absl::StrCat("Given:\n", decls.outputDeclaration(width)..., "\n");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Function objects that perform a check for each comparison operator         //
-////////////////////////////////////////////////////////////////////////////////
-
-#define ABSL_INTERNAL_EXPECT_OP(name, op)                                   \
-  struct Expect##name {                                                     \
-    template <class T>                                                      \
-    void operator()(absl::string_view test_name, absl::string_view context, \
-                    const T& lhs, const T& rhs, absl::string_view lhs_name, \
-                    absl::string_view rhs_name) const {                     \
-      if (!static_cast<bool>(lhs op rhs)) {                                 \
-        errors->addTestFailure(                                             \
-            test_name, absl::StrCat(context,                                \
-                                    "**Unexpected comparison result**\n"    \
-                                    "\n"                                    \
-                                    "Expression:\n"                         \
-                                    "  ",                                   \
-                                    lhs_name, " " #op " ", rhs_name,        \
-                                    "\n"                                    \
-                                    "\n"                                    \
-                                    "Expected: true\n"                      \
-                                    "  Actual: false"));                    \
-      } else {                                                              \
-        errors->addTestSuccess(test_name);                                  \
-      }                                                                     \
-    }                                                                       \
-                                                                            \
-    ConformanceErrors* errors;                                              \
-  };                                                                        \
-                                                                            \
-  struct ExpectNot##name {                                                  \
-    template <class T>                                                      \
-    void operator()(absl::string_view test_name, absl::string_view context, \
-                    const T& lhs, const T& rhs, absl::string_view lhs_name, \
-                    absl::string_view rhs_name) const {                     \
-      if (lhs op rhs) {                                                     \
-        errors->addTestFailure(                                             \
-            test_name, absl::StrCat(context,                                \
-                                    "**Unexpected comparison result**\n"    \
-                                    "\n"                                    \
-                                    "Expression:\n"                         \
-                                    "  ",                                   \
-                                    lhs_name, " " #op " ", rhs_name,        \
-                                    "\n"                                    \
-                                    "\n"                                    \
-                                    "Expected: false\n"                     \
-                                    "  Actual: true"));                     \
-      } else {                                                              \
-        errors->addTestSuccess(test_name);                                  \
-      }                                                                     \
-    }                                                                       \
-                                                                            \
-    ConformanceErrors* errors;                                              \
-  }
-
-ABSL_INTERNAL_EXPECT_OP(Eq, ==);
-ABSL_INTERNAL_EXPECT_OP(Ne, !=);
-ABSL_INTERNAL_EXPECT_OP(Lt, <);
-ABSL_INTERNAL_EXPECT_OP(Le, <=);
-ABSL_INTERNAL_EXPECT_OP(Ge, >=);
-ABSL_INTERNAL_EXPECT_OP(Gt, >);
-
-#undef ABSL_INTERNAL_EXPECT_OP
-
-// A function object that verifies that two objects hash to the same value by
-// way of the std::hash specialization.
-struct ExpectSameHash {
-  template <class T>
-  void operator()(absl::string_view test_name, absl::string_view context,
-                  const T& lhs, const T& rhs, absl::string_view lhs_name,
-                  absl::string_view rhs_name) const {
-    if (std::hash<T>()(lhs) != std::hash<T>()(rhs)) {
-      errors->addTestFailure(
-          test_name, absl::StrCat(context,
-                                  "**Unexpected hash result**\n"
-                                  "\n"
-                                  "Expression:\n"
-                                  "  std::hash<T>()(",
-                                  lhs_name, ") == std::hash<T>()(", rhs_name,
-                                  ")\n"
-                                  "\n"
-                                  "Expected: true\n"
-                                  "  Actual: false"));
-    } else {
-      errors->addTestSuccess(test_name);
-    }
-  }
-
-  ConformanceErrors* errors;
-};
-
-// A function template that takes two objects and verifies that each comparison
-// operator behaves in a way that is consistent with equality. It has "OneWay"
-// in the name because the first argument will always be the left-hand operand
-// of the corresponding comparison operator and the second argument will
-// always be the right-hand operand. It will never switch that order.
-// At a higher level in the test suite, the one-way form is called once for each
-// of the two possible orders whenever lhs and rhs are not the same initializer.
-template <class T, class Prof>
-void ExpectOneWayEquality(ConformanceErrors* errors,
-                          absl::string_view test_name,
-                          absl::string_view context, const T& lhs, const T& rhs,
-                          absl::string_view lhs_name,
-                          absl::string_view rhs_name) {
-  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
-      ExpectEq{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
-      ExpectNotNe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
-      ExpectNotLt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
-      ExpectLe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
-      ExpectGe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
-      ExpectNotGt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-
-  If<PropertiesOfT<Prof>::is_hashable>::Invoke(
-      ExpectSameHash{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
-}
-
-// A function template that takes two objects and verifies that each comparison
-// operator behaves in a way that is consistent with equality. This function
-// differs from ExpectOneWayEquality in that this will do checks with argument
-// order reversed in addition to in-order.
-template <class T, class Prof>
-void ExpectEquality(ConformanceErrors* errors, absl::string_view test_name,
-                    absl::string_view context, const T& lhs, const T& rhs,
-                    absl::string_view lhs_name, absl::string_view rhs_name) {
-  (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, lhs, rhs,
-                                  lhs_name, rhs_name);
-  (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, rhs, lhs,
-                                  rhs_name, lhs_name);
-}
-
-// Given a generator, makes sure that a generated value and a moved-from
-// generated value are equal.
-template <class T, class Prof>
-struct ExpectMoveConstructOneGenerator {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T object = generator();
-    const T moved_object = absl::move(generator());  // Force no elision.
-
-    (ExpectEquality<T, Prof>)(errors, "Move construction",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T object",
-                                                   generator.description},
-                                  GivenDeclaration{"const _T moved_object",
-                                                   std::string("std::move(") +
-                                                       generator.description +
-                                                       ")"}),
-                              object, moved_object, "object", "moved_object");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Given a generator, makes sure that a generated value and a copied-from
-// generated value are equal.
-template <class T, class Prof>
-struct ExpectCopyConstructOneGenerator {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T object = generator();
-    const T copied_object = static_cast<const T&>(generator());
-
-    (ExpectEquality<T, Prof>)(errors, "Copy construction",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T object",
-                                                   generator.description},
-                                  GivenDeclaration{
-                                      "const _T copied_object",
-                                      std::string("static_cast<const _T&>(") +
-                                          generator.description + ")"}),
-                              object, copied_object, "object", "copied_object");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Default-construct and do nothing before destruction.
-//
-// This is useful in exercising the codepath of default construction followed by
-// destruction, but does not explicitly test anything. An example of where this
-// might fail is a default destructor that default-initializes a scalar and a
-// destructor reads the value of that member. Sanitizers can catch this as long
-// as our test attempts to execute such a case.
-template <class T>
-struct ExpectDefaultConstructWithDestruct {
-  void operator()() const {
-    // Scoped so that destructor gets called before reporting success.
-    {
-      T object;
-      static_cast<void>(object);
-    }
-
-    errors->addTestSuccess("Default construction");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Check move-assign into a default-constructed object.
-template <class T, class Prof>
-struct ExpectDefaultConstructWithMoveAssign {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T source_of_truth = generator();
-    T object;
-    object = generator();
-
-    (ExpectEquality<T, Prof>)(errors, "Move assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T object",
-                                                   generator.description},
-                                  GivenDeclaration{"_T object", ""},
-                                  GivenDeclaration{"object",
-                                                   generator.description}),
-                              object, source_of_truth, "std::as_const(object)",
-                              "source_of_truth");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Check copy-assign into a default-constructed object.
-template <class T, class Prof>
-struct ExpectDefaultConstructWithCopyAssign {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T source_of_truth = generator();
-    T object;
-    object = static_cast<const T&>(generator());
-
-    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T source_of_truth",
-                                                   generator.description},
-                                  GivenDeclaration{"_T object", ""},
-                                  GivenDeclaration{
-                                      "object",
-                                      std::string("static_cast<const _T&>(") +
-                                          generator.description + ")"}),
-                              object, source_of_truth, "std::as_const(object)",
-                              "source_of_truth");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Perform a self move-assign.
-template <class T, class Prof>
-struct ExpectSelfMoveAssign {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    T object = generator();
-    object = absl::move(object);
-
-    // NOTE: Self move-assign results in a valid-but-unspecified state.
-
-    (ExpectEquality<T, Prof>)(errors, "Move assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"_T object",
-                                                   generator.description},
-                                  GivenDeclaration{"object",
-                                                   "std::move(object)"}),
-                              object, object, "object", "object");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Perform a self copy-assign.
-template <class T, class Prof>
-struct ExpectSelfCopyAssign {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T source_of_truth = generator();
-    T object = generator();
-    const T& const_object = object;
-    object = const_object;
-
-    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T source_of_truth",
-                                                   generator.description},
-                                  GivenDeclaration{"_T object",
-                                                   generator.description},
-                                  GivenDeclaration{"object",
-                                                   "std::as_const(object)"}),
-                              const_object, source_of_truth,
-                              "std::as_const(object)", "source_of_truth");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Perform a self-swap.
-template <class T, class Prof>
-struct ExpectSelfSwap {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T source_of_truth = generator();
-    T object = generator();
-
-    type_traits_internal::Swap(object, object);
-
-    std::string preliminary_info = absl::StrCat(
-        PrepareGivenContext(
-            GivenDeclaration{"const _T source_of_truth", generator.description},
-            GivenDeclaration{"_T object", generator.description}),
-        "After performing a self-swap:\n"
-        "  using std::swap;\n"
-        "  swap(object, object);\n"
-        "\n");
-
-    (ExpectEquality<T, Prof>)(errors, "Swap", std::move(preliminary_info),
-                              object, source_of_truth, "std::as_const(object)",
-                              "source_of_truth");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Perform each of the single-generator checks when necessary operations are
-// supported.
-template <class T, class Prof>
-struct ExpectSelfComparison {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    const T object = generator();
-    (ExpectOneWayEquality<T, Prof>)(errors, "Comparison",
-                                    PrepareGivenContext(GivenDeclaration{
-                                        "const _T object",
-                                        generator.description}),
-                                    object, object, "object", "object");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Perform each of the single-generator checks when necessary operations are
-// supported.
-template <class T, class Prof>
-struct ExpectConsistency {
-  template <class Fun>
-  void operator()(const Fun& generator) const {
-    If<PropertiesOfT<Prof>::is_move_constructible>::Invoke(
-        ExpectMoveConstructOneGenerator<T, Prof>{errors}, generator);
-
-    If<PropertiesOfT<Prof>::is_copy_constructible>::Invoke(
-        ExpectCopyConstructOneGenerator<T, Prof>{errors}, generator);
-
-    If<PropertiesOfT<Prof>::is_default_constructible &&
-       PropertiesOfT<Prof>::is_move_assignable>::
-        Invoke(ExpectDefaultConstructWithMoveAssign<T, Prof>{errors},
-               generator);
-
-    If<PropertiesOfT<Prof>::is_default_constructible &&
-       PropertiesOfT<Prof>::is_copy_assignable>::
-        Invoke(ExpectDefaultConstructWithCopyAssign<T, Prof>{errors},
-               generator);
-
-    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
-        ExpectSelfMoveAssign<T, Prof>{errors}, generator);
-
-    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
-        ExpectSelfCopyAssign<T, Prof>{errors}, generator);
-
-    If<PropertiesOfT<Prof>::is_swappable>::Invoke(
-        ExpectSelfSwap<T, Prof>{errors}, generator);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Check move-assign with two different values.
-template <class T, class Prof>
-struct ExpectMoveAssign {
-  template <class Fun0, class Fun1>
-  void operator()(const Fun0& generator0, const Fun1& generator1) const {
-    const T source_of_truth1 = generator1();
-    T object = generator0();
-    object = generator1();
-
-    (ExpectEquality<T, Prof>)(errors, "Move assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T source_of_truth1",
-                                                   generator1.description},
-                                  GivenDeclaration{"_T object",
-                                                   generator0.description},
-                                  GivenDeclaration{"object",
-                                                   generator1.description}),
-                              object, source_of_truth1, "std::as_const(object)",
-                              "source_of_truth1");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Check copy-assign with two different values.
-template <class T, class Prof>
-struct ExpectCopyAssign {
-  template <class Fun0, class Fun1>
-  void operator()(const Fun0& generator0, const Fun1& generator1) const {
-    const T source_of_truth1 = generator1();
-    T object = generator0();
-    object = static_cast<const T&>(generator1());
-
-    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T source_of_truth1",
-                                                   generator1.description},
-                                  GivenDeclaration{"_T object",
-                                                   generator0.description},
-                                  GivenDeclaration{
-                                      "object",
-                                      std::string("static_cast<const _T&>(") +
-                                          generator1.description + ")"}),
-                              object, source_of_truth1, "std::as_const(object)",
-                              "source_of_truth1");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Check swap with two different values.
-template <class T, class Prof>
-struct ExpectSwap {
-  template <class Fun0, class Fun1>
-  void operator()(const Fun0& generator0, const Fun1& generator1) const {
-    const T source_of_truth0 = generator0();
-    const T source_of_truth1 = generator1();
-    T object0 = generator0();
-    T object1 = generator1();
-
-    type_traits_internal::Swap(object0, object1);
-
-    const std::string context =
-        PrepareGivenContext(
-            GivenDeclaration{"const _T source_of_truth0",
-                             generator0.description},
-            GivenDeclaration{"const _T source_of_truth1",
-                             generator1.description},
-            GivenDeclaration{"_T object0", generator0.description},
-            GivenDeclaration{"_T object1", generator1.description}) +
-        "After performing a swap:\n"
-        "  using std::swap;\n"
-        "  swap(object0, object1);\n"
-        "\n";
-
-    (ExpectEquality<T, Prof>)(errors, "Swap", context, object0,
-                              source_of_truth1, "std::as_const(object0)",
-                              "source_of_truth1");
-    (ExpectEquality<T, Prof>)(errors, "Swap", context, object1,
-                              source_of_truth0, "std::as_const(object1)",
-                              "source_of_truth0");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Validate that `generator0` and `generator1` produce values that are equal.
-template <class T, class Prof>
-struct ExpectEquivalenceClassComparison {
-  template <class Fun0, class Fun1>
-  void operator()(const Fun0& generator0, const Fun1& generator1) const {
-    const T object0 = generator0();
-    const T object1 = generator1();
-
-    (ExpectEquality<T, Prof>)(errors, "Comparison",
-                              PrepareGivenContext(
-                                  GivenDeclaration{"const _T object0",
-                                                   generator0.description},
-                                  GivenDeclaration{"const _T object1",
-                                                   generator1.description}),
-                              object0, object1, "object0", "object1");
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Validate that all objects in the same equivalence-class have the same value.
-template <class T, class Prof>
-struct ExpectEquivalenceClassConsistency {
-  template <class Fun0, class Fun1>
-  void operator()(const Fun0& generator0, const Fun1& generator1) const {
-    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
-        ExpectMoveAssign<T, Prof>{errors}, generator0, generator1);
-
-    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
-        ExpectCopyAssign<T, Prof>{errors}, generator0, generator1);
-
-    If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
-                                                  generator0, generator1);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Given a "lesser" object and a "greater" object, perform every combination of
-// comparison operators supported for the type, expecting consistent results.
-template <class T, class Prof>
-void ExpectOrdered(ConformanceErrors* errors, absl::string_view context,
-                   const T& small, const T& big, absl::string_view small_name,
-                   absl::string_view big_name) {
-  const absl::string_view test_name = "Comparison";
-
-  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
-      ExpectNotEq{errors}, test_name, context, small, big, small_name,
-      big_name);
-  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
-      ExpectNotEq{errors}, test_name, context, big, small, big_name,
-      small_name);
-
-  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
-      ExpectNe{errors}, test_name, context, small, big, small_name, big_name);
-  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
-      ExpectNe{errors}, test_name, context, big, small, big_name, small_name);
-
-  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
-      ExpectLt{errors}, test_name, context, small, big, small_name, big_name);
-  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
-      ExpectNotLt{errors}, test_name, context, big, small, big_name,
-      small_name);
-
-  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
-      ExpectLe{errors}, test_name, context, small, big, small_name, big_name);
-  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
-      ExpectNotLe{errors}, test_name, context, big, small, big_name,
-      small_name);
-
-  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
-      ExpectNotGe{errors}, test_name, context, small, big, small_name,
-      big_name);
-  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
-      ExpectGe{errors}, test_name, context, big, small, big_name, small_name);
-
-  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
-      ExpectNotGt{errors}, test_name, context, small, big, small_name,
-      big_name);
-  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
-      ExpectGt{errors}, test_name, context, big, small, big_name, small_name);
-}
-
-// For every two elements of an equivalence class, makes sure that those two
-// elements compare equal, including checks with the same argument passed as
-// both operands.
-template <class T, class Prof>
-struct ExpectEquivalenceClassComparisons {
-  template <class... Funs>
-  void operator()(EquivalenceClassType<Funs...> eq_class) const {
-    (ForEachTupleElement)(ExpectSelfComparison<T, Prof>{errors},
-                          eq_class.generators);
-
-    (ForEveryTwo)(ExpectEquivalenceClassComparison<T, Prof>{errors},
-                  eq_class.generators);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// For every element of an equivalence class, makes sure that the element is
-// self-consistent (in other words, if any of move/copy/swap are defined,
-// perform those operations and make such that results and operands still
-// compare equal to known values whenever it is required for that operation.
-template <class T, class Prof>
-struct ExpectEquivalenceClass {
-  template <class... Funs>
-  void operator()(EquivalenceClassType<Funs...> eq_class) const {
-    (ForEachTupleElement)(ExpectConsistency<T, Prof>{errors},
-                          eq_class.generators);
-
-    (ForEveryTwo)(ExpectEquivalenceClassConsistency<T, Prof>{errors},
-                  eq_class.generators);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Validate that the passed-in argument is a generator of a greater value than
-// the one produced by the "small_gen" datamember with respect to all of the
-// comparison operators that Prof requires, with both argument orders to test.
-template <class T, class Prof, class SmallGenerator>
-struct ExpectBiggerGeneratorThanComparisons {
-  template <class BigGenerator>
-  void operator()(BigGenerator big_gen) const {
-    const T small = small_gen();
-    const T big = big_gen();
-
-    (ExpectOrdered<T, Prof>)(errors,
-                             PrepareGivenContext(
-                                 GivenDeclaration{"const _T small",
-                                                  small_gen.description},
-                                 GivenDeclaration{"const _T big",
-                                                  big_gen.description}),
-                             small, big, "small", "big");
-  }
-
-  SmallGenerator small_gen;
-  ConformanceErrors* errors;
-};
-
-// Perform all of the move, copy, and swap checks on the value generated by
-// `small_gen` and the value generated by `big_gen`.
-template <class T, class Prof, class SmallGenerator>
-struct ExpectBiggerGeneratorThan {
-  template <class BigGenerator>
-  void operator()(BigGenerator big_gen) const {
-    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
-        ExpectMoveAssign<T, Prof>{errors}, small_gen, big_gen);
-    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
-        ExpectMoveAssign<T, Prof>{errors}, big_gen, small_gen);
-
-    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
-        ExpectCopyAssign<T, Prof>{errors}, small_gen, big_gen);
-    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
-        ExpectCopyAssign<T, Prof>{errors}, big_gen, small_gen);
-
-    If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
-                                                  small_gen, big_gen);
-  }
-
-  SmallGenerator small_gen;
-  ConformanceErrors* errors;
-};
-
-// Validate that the result of a generator is greater than the results of all
-// generators in an equivalence class with respect to comparisons.
-template <class T, class Prof, class SmallGenerator>
-struct ExpectBiggerGeneratorThanEqClassesComparisons {
-  template <class BigEqClass>
-  void operator()(BigEqClass big_eq_class) const {
-    (ForEachTupleElement)(
-        ExpectBiggerGeneratorThanComparisons<T, Prof, SmallGenerator>{small_gen,
-                                                                      errors},
-        big_eq_class.generators);
-  }
-
-  SmallGenerator small_gen;
-  ConformanceErrors* errors;
-};
-
-// Validate that the non-comparison binary operations required by Prof are
-// correct for the result of each generator of big_eq_class and a generator of
-// the logically smaller value returned by small_gen.
-template <class T, class Prof, class SmallGenerator>
-struct ExpectBiggerGeneratorThanEqClasses {
-  template <class BigEqClass>
-  void operator()(BigEqClass big_eq_class) const {
-    (ForEachTupleElement)(
-        ExpectBiggerGeneratorThan<T, Prof, SmallGenerator>{small_gen, errors},
-        big_eq_class.generators);
-  }
-
-  SmallGenerator small_gen;
-  ConformanceErrors* errors;
-};
-
-// Validate that each equivalence class that is passed is logically less than
-// the equivalence classes that comes later on in the argument list.
-template <class T, class Prof>
-struct ExpectOrderedEquivalenceClassesComparisons {
-  template <class... BigEqClasses>
-  struct Impl {
-    // Validate that the value produced by `small_gen` is less than all of the
-    // values generated by those of the logically larger equivalence classes.
-    template <class SmallGenerator>
-    void operator()(SmallGenerator small_gen) const {
-      (ForEachTupleElement)(ExpectBiggerGeneratorThanEqClassesComparisons<
-                                T, Prof, SmallGenerator>{small_gen, errors},
-                            big_eq_classes);
-    }
-
-    std::tuple<BigEqClasses...> big_eq_classes;
-    ConformanceErrors* errors;
-  };
-
-  // When given no equivalence classes, no validation is necessary.
-  void operator()() const {}
-
-  template <class SmallEqClass, class... BigEqClasses>
-  void operator()(SmallEqClass small_eq_class,
-                  BigEqClasses... big_eq_classes) const {
-    // For each generator in the first equivalence class, make sure that it is
-    // less than each of those in the logically greater equivalence classes.
-    (ForEachTupleElement)(
-        Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
-                              errors},
-        small_eq_class.generators);
-
-    // Recurse so that all equivalence class combinations are checked.
-    (*this)(absl::move(big_eq_classes)...);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Validate that the non-comparison binary operations required by Prof are
-// correct for the result of each generator of big_eq_classes and a generator of
-// the logically smaller value returned by small_gen.
-template <class T, class Prof>
-struct ExpectOrderedEquivalenceClasses {
-  template <class... BigEqClasses>
-  struct Impl {
-    template <class SmallGenerator>
-    void operator()(SmallGenerator small_gen) const {
-      (ForEachTupleElement)(
-          ExpectBiggerGeneratorThanEqClasses<T, Prof, SmallGenerator>{small_gen,
-                                                                      errors},
-          big_eq_classes);
-    }
-
-    std::tuple<BigEqClasses...> big_eq_classes;
-    ConformanceErrors* errors;
-  };
-
-  // Check that small_eq_class is logically consistent and also is logically
-  // less than all values in big_eq_classes.
-  template <class SmallEqClass, class... BigEqClasses>
-  void operator()(SmallEqClass small_eq_class,
-                  BigEqClasses... big_eq_classes) const {
-    (ForEachTupleElement)(
-        Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
-                              errors},
-        small_eq_class.generators);
-
-    (*this)(absl::move(big_eq_classes)...);
-  }
-
-  // Terminating case of operator().
-  void operator()() const {}
-
-  ConformanceErrors* errors;
-};
-
-// Validate that a type meets the syntactic requirements of std::hash if the
-// range of profiles requires it.
-template <class T, class MinProf, class MaxProf>
-struct ExpectHashable {
-  void operator()() const {
-    ExpectModelOfHashable<T, MinProf, MaxProf>(errors);
-  }
-
-  ConformanceErrors* errors;
-};
-
-// Validate that the type `T` meets all of the requirements associated with
-// `MinProf` and without going beyond the syntactic properties of `MaxProf`.
-template <class T, class MinProf, class MaxProf>
-struct ExpectModels {
-  void operator()(ConformanceErrors* errors) const {
-    ExpectModelOfDefaultConstructible<T, MinProf, MaxProf>(errors);
-    ExpectModelOfMoveConstructible<T, MinProf, MaxProf>(errors);
-    ExpectModelOfCopyConstructible<T, MinProf, MaxProf>(errors);
-    ExpectModelOfMoveAssignable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfCopyAssignable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfDestructible<T, MinProf, MaxProf>(errors);
-    ExpectModelOfEqualityComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfInequalityComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfLessThanComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfLessEqualComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfGreaterEqualComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfGreaterThanComparable<T, MinProf, MaxProf>(errors);
-    ExpectModelOfSwappable<T, MinProf, MaxProf>(errors);
-
-    // Only check hashability on compilers that have a compliant default-hash.
-    If<!poisoned_hash_fails_instantiation()>::Invoke(
-        ExpectHashable<T, MinProf, MaxProf>{errors});
-  }
-};
-
-// A metafunction that yields a Profile matching the set of properties that are
-// safe to be checked (lack-of-hashability is only checked on standard library
-// implementations that are standards compliant in that they provide a std::hash
-// primary template that is SFINAE-friendly)
-template <class LogicalProf, class T>
-struct MinimalCheckableProfile {
-  using type =
-      MinimalProfiles<PropertiesOfT<LogicalProf>,
-                      PropertiesOfT<SyntacticConformanceProfileOf<
-                          T, !PropertiesOfT<LogicalProf>::is_hashable &&
-                                     poisoned_hash_fails_instantiation()
-                                 ? CheckHashability::no
-                                 : CheckHashability::yes>>>;
-};
-
-// An identity metafunction
-template <class T>
-struct Always {
-  using type = T;
-};
-
-// Validate the T meets all of the necessary requirements of LogicalProf, with
-// syntactic requirements defined by the profile range [MinProf, MaxProf].
-template <class T, class LogicalProf, class MinProf, class MaxProf,
-          class... EqClasses>
-ConformanceErrors ExpectRegularityImpl(
-    OrderedEquivalenceClasses<EqClasses...> vals) {
-  ConformanceErrors errors((NameOf<T>()));
-
-  If<!constexpr_instantiation_when_unevaluated()>::Invoke(
-      ExpectModels<T, MinProf, MaxProf>(), &errors);
-
-  using minimal_profile = typename absl::conditional_t<
-      constexpr_instantiation_when_unevaluated(), Always<LogicalProf>,
-      MinimalCheckableProfile<LogicalProf, T>>::type;
-
-  If<PropertiesOfT<minimal_profile>::is_default_constructible>::Invoke(
-      ExpectDefaultConstructWithDestruct<T>{&errors});
-
-  //////////////////////////////////////////////////////////////////////////////
-  // Perform all comparison checks first, since later checks depend on their
-  // correctness.
-  //
-  // Check all of the comparisons for all values in the same equivalence
-  // class (equal with respect to comparison operators and hash the same).
-  (ForEachTupleElement)(
-      ExpectEquivalenceClassComparisons<T, minimal_profile>{&errors},
-      vals.eq_classes);
-
-  // Check all of the comparisons for each combination of values that are in
-  // different equivalence classes (not equal with respect to comparison
-  // operators).
-  absl::apply(
-      ExpectOrderedEquivalenceClassesComparisons<T, minimal_profile>{&errors},
-      vals.eq_classes);
-  //
-  //////////////////////////////////////////////////////////////////////////////
-
-  // Perform remaining checks, relying on comparisons.
-  // TODO(calabrese) short circuit if any comparisons above failed.
-  (ForEachTupleElement)(ExpectEquivalenceClass<T, minimal_profile>{&errors},
-                        vals.eq_classes);
-
-  absl::apply(ExpectOrderedEquivalenceClasses<T, minimal_profile>{&errors},
-              vals.eq_classes);
-
-  return errors;
-}
-
-// A type that represents a range of profiles that are acceptable to be matched.
-//
-// `MinProf` is the minimum set of syntactic requirements that must be met.
-//
-// `MaxProf` is the maximum set of syntactic requirements that must be met.
-// This maximum is particularly useful for certain "strictness" checking. Some
-// examples for when this is useful:
-//
-// * Making sure that a type is move-only (rather than simply movable)
-//
-// * Making sure that a member function is *not* noexcept in cases where it
-//   cannot be noexcept, such as if a dependent datamember has certain
-//   operations that are not noexcept.
-//
-// * Making sure that a type tightly matches a spec, such as the standard.
-//
-// `LogicalProf` is the Profile for which run-time testing is to take place.
-//
-// Note: The reason for `LogicalProf` is because it is often the case, when
-// dealing with templates, that a declaration of a given operation is specified,
-// but whose body would fail to instantiate. Examples include the
-// copy-constructor of a standard container when the element-type is move-only,
-// or the comparison operators of a standard container when the element-type
-// does not have the necessary comparison operations defined. The `LogicalProf`
-// parameter allows us to capture the intent of what should be tested at
-// run-time, even in the cases where syntactically it might otherwise appear as
-// though the type undergoing testing supports more than it actually does.
-template <class LogicalProf, class MinProf = LogicalProf,
-          class MaxProf = MinProf>
-struct ProfileRange {
-  using logical_profile = LogicalProf;
-  using min_profile = MinProf;
-  using max_profile = MaxProf;
-};
-
-// Similar to ProfileRange except that it creates a profile range that is
-// coupled with a Domain and is used when testing that a type matches exactly
-// the "minimum" requirements of LogicalProf.
-template <class StrictnessDomain, class LogicalProf,
-          class MinProf = LogicalProf, class MaxProf = MinProf>
-struct StrictProfileRange {
-  // We do not yet support extension.
-  static_assert(
-      std::is_same<StrictnessDomain, RegularityDomain>::value,
-      "Currently, the only valid StrictnessDomain is RegularityDomain.");
-  using strictness_domain = StrictnessDomain;
-  using logical_profile = LogicalProf;
-  using min_profile = MinProf;
-  using max_profile = MaxProf;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction that creates a StrictProfileRange from a Domain and either a
-// Profile or ProfileRange.
-template <class StrictnessDomain, class ProfOrRange>
-struct MakeStrictProfileRange;
-
-template <class StrictnessDomain, class LogicalProf>
-struct MakeStrictProfileRange {
-  using type = StrictProfileRange<StrictnessDomain, LogicalProf>;
-};
-
-template <class StrictnessDomain, class LogicalProf, class MinProf,
-          class MaxProf>
-struct MakeStrictProfileRange<StrictnessDomain,
-                              ProfileRange<LogicalProf, MinProf, MaxProf>> {
-  using type =
-      StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
-};
-
-template <class StrictnessDomain, class ProfOrRange>
-using MakeStrictProfileRangeT =
-    typename MakeStrictProfileRange<StrictnessDomain, ProfOrRange>::type;
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// A profile in the RegularityDomain with the strongest possible requirements.
-using MostStrictProfile =
-    CombineProfiles<TriviallyCompleteProfile, NothrowComparableProfile>;
-
-// Forms a ProfileRange that treats the Profile as the bare minimum requirements
-// of a type.
-template <class LogicalProf, class MinProf = LogicalProf>
-using LooseProfileRange = StrictProfileRange<RegularityDomain, LogicalProf,
-                                             MinProf, MostStrictProfile>;
-
-template <class Prof>
-using MakeLooseProfileRangeT = Prof;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// The following classes implement the metafunction ProfileRangeOfT<T> that
-// takes either a Profile or ProfileRange and yields the ProfileRange to be
-// used during testing.
-//
-template <class T, class /*Enabler*/ = void>
-struct ProfileRangeOfImpl;
-
-template <class T>
-struct ProfileRangeOfImpl<T, absl::void_t<PropertiesOfT<T>>> {
-  using type = LooseProfileRange<T>;
-};
-
-template <class T>
-struct ProfileRangeOf : ProfileRangeOfImpl<T> {};
-
-template <class StrictnessDomain, class LogicalProf, class MinProf,
-          class MaxProf>
-struct ProfileRangeOf<
-    StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> {
-  using type =
-      StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
-};
-
-template <class T>
-using ProfileRangeOfT = typename ProfileRangeOf<T>::type;
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Extract the logical profile of a range (what will be runtime tested).
-template <class T>
-using LogicalProfileOfT = typename ProfileRangeOfT<T>::logical_profile;
-
-// Extract the minimal syntactic profile of a range (error if not at least).
-template <class T>
-using MinProfileOfT = typename ProfileRangeOfT<T>::min_profile;
-
-// Extract the maximum syntactic profile of a range (error if more than).
-template <class T>
-using MaxProfileOfT = typename ProfileRangeOfT<T>::max_profile;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-template <class T>
-struct IsProfileOrProfileRange : IsProfile<T>::type {};
-
-template <class StrictnessDomain, class LogicalProf, class MinProf,
-          class MaxProf>
-struct IsProfileOrProfileRange<
-    StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>>
-    : std::true_type {};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// TODO(calabrese): Consider naming the functions in this class the same as
-// the macros (defined later on) so that auto-complete leads to the correct name
-// and so that a user cannot accidentally call a function rather than the macro
-// form.
-template <bool ExpectSuccess, class T, class... EqClasses>
-struct ExpectConformanceOf {
-  // Add a value to be tested. Subsequent calls to this function on the same
-  // object must specify logically "larger" values with respect to the
-  // comparison operators of the type, if any.
-  //
-  // NOTE: This function should not be called directly. A stateless lambda is
-  // implicitly formed and passed when using the INITIALIZER macro at the bottom
-  // of this file.
-  template <class Fun,
-            absl::enable_if_t<std::is_same<
-                ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
-  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
-                                           EquivalenceClassType<Fun>>
-  initializer(GeneratorType<Fun> fun) && {
-    return {
-        {std::tuple_cat(absl::move(ordered_vals.eq_classes),
-                        std::make_tuple((EquivalenceClass)(absl::move(fun))))},
-        std::move(expected_failed_tests)};
-  }
-
-  template <class... TestNames,
-            absl::enable_if_t<!ExpectSuccess && sizeof...(EqClasses) == 0 &&
-                              absl::conjunction<std::is_convertible<
-                                  TestNames, absl::string_view>...>::value>** =
-                nullptr>
-  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
-  due_to(TestNames&&... test_names) && {
-    (InsertEach)(&expected_failed_tests,
-                 absl::AsciiStrToLower(absl::string_view(test_names))...);
-
-    return {absl::move(ordered_vals), std::move(expected_failed_tests)};
-  }
-
-  template <class... TestNames, int = 0,  // MSVC disambiguator
-            absl::enable_if_t<ExpectSuccess && sizeof...(EqClasses) == 0 &&
-                              absl::conjunction<std::is_convertible<
-                                  TestNames, absl::string_view>...>::value>** =
-                nullptr>
-  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
-  due_to(TestNames&&... test_names) && {
-    // TODO(calabrese) Instead have DUE_TO only exist via a CRTP base.
-    // This would produce better errors messages than the static_assert.
-    static_assert(!ExpectSuccess,
-                  "DUE_TO cannot be called when conformance is expected -- did "
-                  "you mean to use ASSERT_NONCONFORMANCE_OF?");
-  }
-
-  // Add a value to be tested. Subsequent calls to this function on the same
-  // object must specify logically "larger" values with respect to the
-  // comparison operators of the type, if any.
-  //
-  // NOTE: This function should not be called directly. A stateful lambda is
-  // implicitly formed and passed when using the INITIALIZER macro at the bottom
-  // of this file.
-  template <class Fun,
-            absl::enable_if_t<std::is_same<
-                ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
-  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
-                                           EquivalenceClassType<Fun>>
-  dont_class_directly_stateful_initializer(GeneratorType<Fun> fun) && {
-    return {
-        {std::tuple_cat(absl::move(ordered_vals.eq_classes),
-                        std::make_tuple((EquivalenceClass)(absl::move(fun))))},
-        std::move(expected_failed_tests)};
-  }
-
-  // Add a set of value to be tested, where each value is equal with respect to
-  // the comparison operators and std::hash specialization, if defined.
-  template <
-      class... Funs,
-      absl::void_t<absl::enable_if_t<std::is_same<
-          ResultOfGeneratorT<GeneratorType<Funs>>, T>::value>...>** = nullptr>
-  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
-                                           EquivalenceClassType<Funs...>>
-  equivalence_class(GeneratorType<Funs>... funs) && {
-    return {{std::tuple_cat(
-                absl::move(ordered_vals.eq_classes),
-                std::make_tuple((EquivalenceClass)(absl::move(funs)...)))},
-            std::move(expected_failed_tests)};
-  }
-
-  // Execute the tests for the captured set of values, strictly matching a range
-  // of expected profiles in a given domain.
-  template <
-      class ProfRange,
-      absl::enable_if_t<IsProfileOrProfileRange<ProfRange>::value>** = nullptr>
-  ABSL_MUST_USE_RESULT ::testing::AssertionResult with_strict_profile(
-      ProfRange /*profile*/) {
-    ConformanceErrors test_result =
-        (ExpectRegularityImpl<
-            T, LogicalProfileOfT<ProfRange>, MinProfileOfT<ProfRange>,
-            MaxProfileOfT<ProfRange>>)(absl::move(ordered_vals));
-
-    return ExpectSuccess ? test_result.assertionResult()
-                         : test_result.expectFailedTests(expected_failed_tests);
-  }
-
-  // Execute the tests for the captured set of values, loosely matching a range
-  // of expected profiles (loose in that an interface is allowed to be more
-  // refined that a profile suggests, such as a type having a noexcept copy
-  // constructor when all that is required is that the copy constructor exists).
-  template <class Prof, absl::enable_if_t<IsProfile<Prof>::value>** = nullptr>
-  ABSL_MUST_USE_RESULT ::testing::AssertionResult with_loose_profile(
-      Prof /*profile*/) {
-    ConformanceErrors test_result =
-        (ExpectRegularityImpl<
-            T, Prof, Prof,
-            CombineProfiles<TriviallyCompleteProfile,
-                            NothrowComparableProfile>>)(absl::
-                                                            move(ordered_vals));
-
-    return ExpectSuccess ? test_result.assertionResult()
-                         : test_result.expectFailedTests(expected_failed_tests);
-  }
-
-  OrderedEquivalenceClasses<EqClasses...> ordered_vals;
-  std::set<std::string> expected_failed_tests;
-};
-
-template <class T>
-using ExpectConformanceOfType = ExpectConformanceOf</*ExpectSuccess=*/true, T>;
-
-template <class T>
-using ExpectNonconformanceOfType =
-    ExpectConformanceOf</*ExpectSuccess=*/false, T>;
-
-struct EquivalenceClassMaker {
-  // TODO(calabrese) Constrain to callable
-  template <class Fun>
-  static GeneratorType<Fun> initializer(GeneratorType<Fun> fun) {
-    return fun;
-  }
-};
-
-// A top-level macro that begins the builder pattern.
-//
-// The argument here takes the datatype to be tested.
-#define ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(...)                            \
-  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                             \
-  if ABSL_INTERNAL_LPAREN                                                   \
-  const ::testing::AssertionResult gtest_ar =                               \
-      ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectConformanceOfType< \
-          __VA_ARGS__>()
-
-// Akin to ASSERT_CONFORMANCE_OF except that it expects failure and tries to
-// match text.
-#define ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(...)                            \
-  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
-  if ABSL_INTERNAL_LPAREN                                                      \
-  const ::testing::AssertionResult gtest_ar =                                  \
-      ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectNonconformanceOfType< \
-          __VA_ARGS__>()
-
-////////////////////////////////////////////////////////////////////////////////
-// NOTE: The following macros look like they are recursive, but are not (macros
-// cannot recurse). These actually refer to member functions of the same name.
-// This is done intentionally so that a user cannot accidentally invoke a
-// member function of the conformance-testing suite without going through the
-// macro.
-////////////////////////////////////////////////////////////////////////////////
-
-// Specify expected test failures as comma-separated strings.
-#define DUE_TO(...) due_to(__VA_ARGS__)
-
-// Specify a value to be tested.
-//
-// Note: Internally, this takes an expression and turns it into the return value
-// of lambda that captures no data. The expression is stringized during
-// preprocessing so that it can be used in error reports.
-#define INITIALIZER(...)                         \
-  initializer(::absl::types_internal::Generator( \
-      [] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
-
-// Specify a value to be tested.
-//
-// Note: Internally, this takes an expression and turns it into the return value
-// of lambda that captures data by reference. The expression is stringized
-// during preprocessing so that it can be used in error reports.
-#define STATEFUL_INITIALIZER(...)                         \
-  stateful_initializer(::absl::types_internal::Generator( \
-      [&] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
-
-// Used in the builder-pattern.
-//
-// Takes a series of INITIALIZER and/or STATEFUL_INITIALIZER invocations and
-// forwards them along to be tested, grouping them such that the testing suite
-// knows that they are supposed to represent the same logical value (the values
-// compare the same, hash the same, etc.).
-#define EQUIVALENCE_CLASS(...)                    \
-  equivalence_class(ABSL_INTERNAL_TRANSFORM_ARGS( \
-      ABSL_INTERNAL_PREPEND_EQ_MAKER, __VA_ARGS__))
-
-// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
-// It takes a Profile as its argument.
-//
-// This executes the tests and allows types that are "more referined" than the
-// profile specifies, but not less. For instance, if the Profile specifies
-// noexcept copy-constructiblity, the test will fail if the copy-constructor is
-// not noexcept, however, it will succeed if the copy constructor is trivial.
-//
-// This is useful for testing that a type meets some minimum set of
-// requirements.
-#define WITH_LOOSE_PROFILE(...)                                      \
-  with_loose_profile(                                                \
-      ::absl::types_internal::MakeLooseProfileRangeT<__VA_ARGS__>()) \
-      ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN;                     \
-  else GTEST_FATAL_FAILURE_(gtest_ar.failure_message())  // NOLINT
-
-// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
-// It takes a Domain and a Profile as its arguments.
-//
-// This executes the tests and disallows types that differ at all from the
-// properties of the Profile. For instance, if the Profile specifies noexcept
-// copy-constructiblity, the test will fail if the copy constructor is trivial.
-//
-// This is useful for testing that a type does not do anything more than a
-// specification requires, such as to minimize things like Hyrum's Law, or more
-// commonly, to prevent a type from being "accidentally" copy-constructible in
-// a way that may produce incorrect results, simply because the user forget to
-// delete that operation.
-#define WITH_STRICT_PROFILE(...)                                      \
-  with_strict_profile(                                                \
-      ::absl::types_internal::MakeStrictProfileRangeT<__VA_ARGS__>()) \
-      ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN;                      \
-  else GTEST_FATAL_FAILURE_(gtest_ar.failure_message())  // NOLINT
-
-// Internal macro that is used in the internals of the EDSL when forming
-// equivalence classes.
-#define ABSL_INTERNAL_PREPEND_EQ_MAKER(arg) \
-  ::absl::types_internal::EquivalenceClassMaker().arg
-
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h b/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
deleted file mode 100644
index 00775f9..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
+++ /dev/null
@@ -1,391 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
-#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
-
-// Checks to determine whether or not we can use abi::__cxa_demangle
-#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID)
-#define ABSL_INTERNAL_OS_ANDROID
-#endif
-
-// We support certain compilers only.  See demangle.h for details.
-#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
-#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
-#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
-    !defined(__mips__)
-#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
-#elif defined(__clang__) && !defined(_MSC_VER)
-#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
-#else
-#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
-#endif
-
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-#include "absl/meta/type_traits.h"
-#include "absl/strings/string_view.h"
-#include "absl/utility/utility.h"
-
-#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
-#include <cxxabi.h>
-
-#include <cstdlib>
-#endif
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-
-// Return a readable name for type T.
-template <class T>
-absl::string_view NameOfImpl() {
-// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback.
-#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
-  int status = 0;
-  char* demangled_name = nullptr;
-
-  demangled_name =
-      abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
-
-  if (status == 0 && demangled_name != nullptr) {
-    return demangled_name;
-  } else {
-    return typeid(T).name();
-  }
-#else
-  return typeid(T).name();
-#endif
-  // NOTE: We intentionally leak demangled_name so that it remains valid
-  // throughout the remainder of the program.
-}
-
-// Given a type, returns as nice of a type name as we can produce (demangled).
-//
-// Note: This currently strips cv-qualifiers and references, but that is okay
-// because we only use this internally with unqualified object types.
-template <class T>
-std::string NameOf() {
-  static const absl::string_view result = NameOfImpl<T>();
-  return std::string(result);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Metafunction to check if a type is callable with no explicit arguments
-template <class Fun, class /*Enabler*/ = void>
-struct IsNullaryCallableImpl : std::false_type {};
-
-template <class Fun>
-struct IsNullaryCallableImpl<
-    Fun, absl::void_t<decltype(std::declval<const Fun&>()())>>
-    : std::true_type {
-  using result_type = decltype(std::declval<const Fun&>()());
-
-  template <class ValueType>
-  using for_type = std::is_same<ValueType, result_type>;
-
-  using void_if_true = void;
-};
-
-template <class Fun>
-struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// A type that contains a function object that returns an instance of a type
-// that is undergoing conformance testing. This function is required to always
-// return the same value upon invocation.
-template <class Fun>
-struct GeneratorType;
-
-// A type that contains a tuple of GeneratorType<Fun> where each Fun has the
-// same return type. The result of each of the different generators should all
-// be equal values, though the underlying object representation may differ (such
-// as if one returns 0.0 and another return -0.0, or if one returns an empty
-// vector and another returns an empty vector with a different capacity.
-template <class... Funs>
-struct EquivalenceClassType;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction to check if a type is a specialization of EquivalenceClassType
-template <class T>
-struct IsEquivalenceClass : std::false_type {};
-
-template <>
-struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type {
-  using self = IsEquivalenceClass;
-
-  // A metafunction to check if this EquivalenceClassType is a valid
-  // EquivalenceClassType for a type `ValueType` that is undergoing testing
-  template <class ValueType>
-  using for_type = std::true_type;
-};
-
-template <class Head, class... Tail>
-struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>>
-    : std::true_type {
-  using self = IsEquivalenceClass;
-
-  // The type undergoing conformance testing that this EquivalenceClass
-  // corresponds to
-  using result_type = typename IsNullaryCallable<Head>::result_type;
-
-  // A metafunction to check if this EquivalenceClassType is a valid
-  // EquivalenceClassType for a type `ValueType` that is undergoing testing
-  template <class ValueType>
-  using for_type = std::is_same<ValueType, result_type>;
-};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// A type that contains an ordered series of EquivalenceClassTypes, where the
-// the function object of each underlying GeneratorType has the same return type
-//
-// These equivalence classes are required to be in a logical ascending order
-// that is consistent with comparison operators that are defined for the return
-// type of each GeneratorType, if any.
-template <class... EqClasses>
-struct OrderedEquivalenceClasses;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction to determine the return type of the function object contained
-// in a GeneratorType specialization.
-template <class T>
-struct ResultOfGenerator {};
-
-template <class Fun>
-struct ResultOfGenerator<GeneratorType<Fun>> {
-  using type = decltype(std::declval<const Fun&>()());
-};
-
-template <class Fun>
-using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type;
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction that yields true iff each of Funs is a GeneratorType
-// specialization and they all contain functions with the same return type
-template <class /*Enabler*/, class... Funs>
-struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {};
-
-template <>
-struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {};
-
-template <class Head, class... Tail>
-struct AreGeneratorsWithTheSameReturnTypeImpl<
-    typename std::enable_if<absl::conjunction<std::is_same<
-        ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type,
-    Head, Tail...> : std::true_type {};
-
-template <class... Funs>
-struct AreGeneratorsWithTheSameReturnType
-    : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A metafunction that yields true iff each of Funs is an EquivalenceClassType
-// specialization and they all contain GeneratorType specializations that have
-// the same return type
-template <class... EqClasses>
-struct AreEquivalenceClassesOfTheSameType {
-  static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), "");
-};
-
-template <>
-struct AreEquivalenceClassesOfTheSameType<> : std::true_type {
-  using self = AreEquivalenceClassesOfTheSameType;
-
-  // Metafunction to check that a type is the same as all of the equivalence
-  // classes, if any.
-  // Note: In this specialization there are no equivalence classes, so the
-  // value type is always compatible.
-  template <class /*ValueType*/>
-  using for_type = std::true_type;
-};
-
-template <class... Funs>
-struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>>
-    : std::true_type {
-  using self = AreEquivalenceClassesOfTheSameType;
-
-  // Metafunction to check that a type is the same as all of the equivalence
-  // classes, if any.
-  template <class ValueType>
-  using for_type = typename IsEquivalenceClass<
-      EquivalenceClassType<Funs...>>::template for_type<ValueType>;
-};
-
-template <class... TailEqClasses>
-struct AreEquivalenceClassesOfTheSameType<
-    EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...>
-    : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {};
-
-template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses>
-struct AreEquivalenceClassesOfTheSameType<
-    EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>,
-    TailEqClasses...>
-    : AreEquivalenceClassesOfTheSameType<
-          EquivalenceClassType<HeadNextFun, TailNextFuns...>,
-          TailEqClasses...>::self {};
-
-template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses>
-struct AreEquivalenceClassesOfTheSameType<
-    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>,
-    TailEqClasses...>
-    : AreEquivalenceClassesOfTheSameType<
-          EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
-          TailEqClasses...>::self {};
-
-template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun,
-          class... TailNextFuns, class... TailEqClasses>
-struct AreEquivalenceClassesOfTheSameType<
-    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
-    EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...>
-    : absl::conditional_t<
-          IsNullaryCallable<HeadNextFun>::template for_type<
-              typename IsNullaryCallable<HeadHeadFun>::result_type>::value,
-          AreEquivalenceClassesOfTheSameType<
-              EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
-              TailEqClasses...>,
-          std::false_type> {};
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Execute a function for each passed-in parameter.
-template <class Fun, class... Cases>
-void ForEachParameter(const Fun& fun, const Cases&... cases) {
-  const std::initializer_list<bool> results = {
-      (static_cast<void>(fun(cases)), true)...};
-
-  (void)results;
-}
-
-// Execute a function on each passed-in parameter (using a bound function).
-template <class Fun>
-struct ForEachParameterFun {
-  template <class... T>
-  void operator()(const T&... cases) const {
-    (ForEachParameter)(fun, cases...);
-  }
-
-  Fun fun;
-};
-
-// Execute a function on each element of a tuple.
-template <class Fun, class Tup>
-void ForEachTupleElement(const Fun& fun, const Tup& tup) {
-  absl::apply(ForEachParameterFun<Fun>{fun}, tup);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Execute a function for each combination of two elements of a tuple, including
-// combinations of an element with itself.
-template <class Fun, class... T>
-struct ForEveryTwoImpl {
-  template <class Lhs>
-  struct WithBoundLhs {
-    template <class Rhs>
-    void operator()(const Rhs& rhs) const {
-      fun(lhs, rhs);
-    }
-
-    Fun fun;
-    Lhs lhs;
-  };
-
-  template <class Lhs>
-  void operator()(const Lhs& lhs) const {
-    (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args);
-  }
-
-  Fun fun;
-  std::tuple<T...> args;
-};
-
-template <class Fun, class... T>
-void ForEveryTwo(const Fun& fun, std::tuple<T...> args) {
-  (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args);
-}
-//
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Insert all values into an associative container
-template<class Container>
-void InsertEach(Container* cont) {
-}
-
-template<class Container, class H, class... T>
-void InsertEach(Container* cont, H&& head, T&&... tail) {
-  cont->insert(head);
-  (InsertEach)(cont, tail...);
-}
-//
-////////////////////////////////////////////////////////////////////////////////
-// A template with a nested "Invoke" static-member-function that executes a
-// passed-in Callable when `Condition` is true, otherwise it ignores the
-// Callable. This is useful for executing a function object with a condition
-// that corresponds to whether or not the Callable can be safely instantiated.
-// It has some overlapping uses with C++17 `if constexpr`.
-template <bool Condition>
-struct If;
-
-template <>
-struct If</*Condition =*/false> {
-  template <class Fun, class... P>
-  static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {}
-};
-
-template <>
-struct If</*Condition =*/true> {
-  template <class Fun, class... P>
-  static void Invoke(const Fun& fun, P&&... args) {
-    // TODO(calabrese) Use std::invoke equivalent instead of function-call.
-    fun(absl::forward<P>(args)...);
-  }
-};
-
-//
-// ABSL_INTERNAL_STRINGIZE(...)
-//
-// This variadic macro transforms its arguments into a c-string literal after
-// expansion.
-//
-// Example:
-//
-//   ABSL_INTERNAL_STRINGIZE(std::array<int, 10>)
-//
-// Results in:
-//
-//   "std::array<int, 10>"
-#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__))
-#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg
-#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__
-
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc b/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc
deleted file mode 100644
index cf262fa6..0000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc
+++ /dev/null
@@ -1,1556 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/internal/conformance_testing.h"
-
-#include <new>
-#include <type_traits>
-#include <utility>
-
-#include "gtest/gtest.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/internal/conformance_aliases.h"
-#include "absl/types/internal/conformance_profile.h"
-
-namespace {
-
-namespace ti = absl::types_internal;
-
-template <class T>
-using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T);
-
-template <class T>
-using DefaultConstructibleWithNew =
-    absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>;
-
-template <class T>
-using MoveConstructibleWithNewImpl =
-    decltype(::new (std::nothrow) T(std::declval<T>()));
-
-template <class T>
-using MoveConstructibleWithNew =
-    absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>;
-
-template <class T>
-using CopyConstructibleWithNewImpl =
-    decltype(::new (std::nothrow) T(std::declval<const T&>()));
-
-template <class T>
-using CopyConstructibleWithNew =
-    absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>;
-
-template <class T,
-          class Result =
-              std::integral_constant<bool, noexcept(::new (std::nothrow) T)>>
-using NothrowDefaultConstructibleWithNewImpl =
-    typename std::enable_if<Result::value>::type;
-
-template <class T>
-using NothrowDefaultConstructibleWithNew =
-    absl::type_traits_internal::is_detected<
-        NothrowDefaultConstructibleWithNewImpl, T>;
-
-template <class T,
-          class Result = std::integral_constant<
-              bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>>
-using NothrowMoveConstructibleWithNewImpl =
-    typename std::enable_if<Result::value>::type;
-
-template <class T>
-using NothrowMoveConstructibleWithNew =
-    absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl,
-                                            T>;
-
-template <class T,
-          class Result = std::integral_constant<
-              bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>>
-using NothrowCopyConstructibleWithNewImpl =
-    typename std::enable_if<Result::value>::type;
-
-template <class T>
-using NothrowCopyConstructibleWithNew =
-    absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl,
-                                            T>;
-
-// NOTE: ?: is used to verify contextually-convertible to bool and not simply
-//       implicit or explicit convertibility.
-#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \
-  ((std::declval<const T&>() op std::declval<const T&>()) ? true : true)
-
-#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op)                         \
-  template <class T>                                                        \
-  using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op));        \
-                                                                            \
-  template <class T>                                                        \
-  using name = absl::type_traits_internal::is_detected<name##Impl, T>;      \
-                                                                            \
-  template <class T,                                                        \
-            class Result = std::integral_constant<                          \
-                bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>>      \
-  using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \
-                                                                            \
-  template <class T>                                                        \
-  using Nothrow##name =                                                     \
-      absl::type_traits_internal::is_detected<Nothrow##name##Impl, T>
-
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==);
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=);
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <);
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=);
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=);
-ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >);
-
-#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT
-
-template <class T>
-class ProfileTest : public ::testing::Test {};
-
-TYPED_TEST_SUITE_P(ProfileTest);
-
-TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) {
-  using profile = typename TypeParam::profile;
-  using arch = typename TypeParam::arch;
-  using expected_profile = typename TypeParam::expected_profile;
-
-  using props = ti::PropertiesOfT<profile>;
-  using arch_props = ti::PropertiesOfArchetypeT<arch>;
-  using expected_props = ti::PropertiesOfT<expected_profile>;
-
-  // Make sure all of the properties are as expected.
-  // There are seemingly redundant tests here to make it easier to diagnose
-  // the specifics of the failure if something were to go wrong.
-  EXPECT_TRUE((std::is_same<props, arch_props>::value));
-  EXPECT_TRUE((std::is_same<props, expected_props>::value));
-  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
-
-  EXPECT_EQ(props::default_constructible_support,
-            expected_props::default_constructible_support);
-
-  EXPECT_EQ(props::move_constructible_support,
-            expected_props::move_constructible_support);
-
-  EXPECT_EQ(props::copy_constructible_support,
-            expected_props::copy_constructible_support);
-
-  EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
-
-  // Avoid additional error message noise when profile and archetype match with
-  // each other but were not what was expected.
-  if (!std::is_same<props, arch_props>::value) {
-    EXPECT_EQ(arch_props::default_constructible_support,
-              expected_props::default_constructible_support);
-
-    EXPECT_EQ(arch_props::move_constructible_support,
-              expected_props::move_constructible_support);
-
-    EXPECT_EQ(arch_props::copy_constructible_support,
-              expected_props::copy_constructible_support);
-
-    EXPECT_EQ(arch_props::destructible_support,
-              expected_props::destructible_support);
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                       Default constructor checks                         //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::default_constructible_support,
-            expected_props::default_constructible_support);
-
-  switch (expected_props::default_constructible_support) {
-    case ti::default_constructible::maybe:
-      EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_FALSE(std::is_default_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
-      }
-      break;
-    case ti::default_constructible::yes:
-      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_default_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
-      }
-      break;
-    case ti::default_constructible::nothrow:
-      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_default_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
-
-        // Constructor traits also check the destructor.
-        if (std::is_nothrow_destructible<arch>::value) {
-          EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
-        }
-      }
-      break;
-    case ti::default_constructible::trivial:
-      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_default_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
-
-        // Constructor triviality traits require trivially destructible types.
-        if (absl::is_trivially_destructible<arch>::value) {
-          EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value);
-        }
-      }
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                         Move constructor checks                          //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::move_constructible_support,
-            expected_props::move_constructible_support);
-
-  switch (expected_props::move_constructible_support) {
-    case ti::move_constructible::maybe:
-      EXPECT_FALSE(MoveConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_FALSE(std::is_move_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
-      }
-      break;
-    case ti::move_constructible::yes:
-      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_move_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
-      }
-      break;
-    case ti::move_constructible::nothrow:
-      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_move_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
-
-        // Constructor traits also check the destructor.
-        if (std::is_nothrow_destructible<arch>::value) {
-          EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
-        }
-      }
-      break;
-    case ti::move_constructible::trivial:
-      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_move_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
-
-        // Constructor triviality traits require trivially destructible types.
-        if (absl::is_trivially_destructible<arch>::value) {
-          EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value);
-        }
-      }
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                         Copy constructor checks                          //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::copy_constructible_support,
-            expected_props::copy_constructible_support);
-
-  switch (expected_props::copy_constructible_support) {
-    case ti::copy_constructible::maybe:
-      EXPECT_FALSE(CopyConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_FALSE(std::is_copy_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
-      }
-      break;
-    case ti::copy_constructible::yes:
-      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
-      EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
-        EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
-      }
-      break;
-    case ti::copy_constructible::nothrow:
-      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
-        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
-
-        // Constructor traits also check the destructor.
-        if (std::is_nothrow_destructible<arch>::value) {
-          EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
-        }
-      }
-      break;
-    case ti::copy_constructible::trivial:
-      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
-      EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
-
-      // Standard constructible traits depend on the destructor.
-      if (std::is_destructible<arch>::value) {
-        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
-        EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
-
-        // Constructor triviality traits require trivially destructible types.
-        if (absl::is_trivially_destructible<arch>::value) {
-          EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value);
-        }
-      }
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                           Destructible checks                            //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
-
-  switch (expected_props::destructible_support) {
-    case ti::destructible::maybe:
-      EXPECT_FALSE(std::is_destructible<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
-      break;
-    case ti::destructible::yes:
-      EXPECT_TRUE(std::is_destructible<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
-      break;
-    case ti::destructible::nothrow:
-      EXPECT_TRUE(std::is_destructible<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
-      break;
-    case ti::destructible::trivial:
-      EXPECT_TRUE(std::is_destructible<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
-      EXPECT_TRUE(absl::is_trivially_destructible<arch>::value);
-      break;
-  }
-}
-
-TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) {
-  using profile = typename TypeParam::profile;
-  using arch = typename TypeParam::arch;
-  using expected_profile = typename TypeParam::expected_profile;
-
-  using props = ti::PropertiesOfT<profile>;
-  using arch_props = ti::PropertiesOfArchetypeT<arch>;
-  using expected_props = ti::PropertiesOfT<expected_profile>;
-
-  // Make sure all of the properties are as expected.
-  // There are seemingly redundant tests here to make it easier to diagnose
-  // the specifics of the failure if something were to go wrong.
-  EXPECT_TRUE((std::is_same<props, arch_props>::value));
-  EXPECT_TRUE((std::is_same<props, expected_props>::value));
-  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
-
-  EXPECT_EQ(props::move_assignable_support,
-            expected_props::move_assignable_support);
-
-  EXPECT_EQ(props::copy_assignable_support,
-            expected_props::copy_assignable_support);
-
-  // Avoid additional error message noise when profile and archetype match with
-  // each other but were not what was expected.
-  if (!std::is_same<props, arch_props>::value) {
-    EXPECT_EQ(arch_props::move_assignable_support,
-              expected_props::move_assignable_support);
-
-    EXPECT_EQ(arch_props::copy_assignable_support,
-              expected_props::copy_assignable_support);
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                          Move assignment checks                          //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::move_assignable_support,
-            expected_props::move_assignable_support);
-
-  switch (expected_props::move_assignable_support) {
-    case ti::move_assignable::maybe:
-      EXPECT_FALSE(std::is_move_assignable<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
-      break;
-    case ti::move_assignable::yes:
-      EXPECT_TRUE(std::is_move_assignable<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
-      break;
-    case ti::move_assignable::nothrow:
-      EXPECT_TRUE(std::is_move_assignable<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
-      break;
-    case ti::move_assignable::trivial:
-      EXPECT_TRUE(std::is_move_assignable<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
-      EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                          Copy assignment checks                          //
-  //////////////////////////////////////////////////////////////////////////////
-  EXPECT_EQ(props::copy_assignable_support,
-            expected_props::copy_assignable_support);
-
-  switch (expected_props::copy_assignable_support) {
-    case ti::copy_assignable::maybe:
-      EXPECT_FALSE(std::is_copy_assignable<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
-      break;
-    case ti::copy_assignable::yes:
-      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
-      EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
-      break;
-    case ti::copy_assignable::nothrow:
-      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
-      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
-      break;
-    case ti::copy_assignable::trivial:
-      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
-      EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
-      EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value);
-      break;
-  }
-}
-
-TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) {
-  using profile = typename TypeParam::profile;
-  using arch = typename TypeParam::arch;
-  using expected_profile = typename TypeParam::expected_profile;
-
-  using props = ti::PropertiesOfT<profile>;
-  using arch_props = ti::PropertiesOfArchetypeT<arch>;
-  using expected_props = ti::PropertiesOfT<expected_profile>;
-
-  // Make sure all of the properties are as expected.
-  // There are seemingly redundant tests here to make it easier to diagnose
-  // the specifics of the failure if something were to go wrong.
-  EXPECT_TRUE((std::is_same<props, arch_props>::value));
-  EXPECT_TRUE((std::is_same<props, expected_props>::value));
-  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
-
-  EXPECT_EQ(props::equality_comparable_support,
-            expected_props::equality_comparable_support);
-
-  EXPECT_EQ(props::inequality_comparable_support,
-            expected_props::inequality_comparable_support);
-
-  EXPECT_EQ(props::less_than_comparable_support,
-            expected_props::less_than_comparable_support);
-
-  EXPECT_EQ(props::less_equal_comparable_support,
-            expected_props::less_equal_comparable_support);
-
-  EXPECT_EQ(props::greater_equal_comparable_support,
-            expected_props::greater_equal_comparable_support);
-
-  EXPECT_EQ(props::greater_than_comparable_support,
-            expected_props::greater_than_comparable_support);
-
-  // Avoid additional error message noise when profile and archetype match with
-  // each other but were not what was expected.
-  if (!std::is_same<props, arch_props>::value) {
-    EXPECT_EQ(arch_props::equality_comparable_support,
-              expected_props::equality_comparable_support);
-
-    EXPECT_EQ(arch_props::inequality_comparable_support,
-              expected_props::inequality_comparable_support);
-
-    EXPECT_EQ(arch_props::less_than_comparable_support,
-              expected_props::less_than_comparable_support);
-
-    EXPECT_EQ(arch_props::less_equal_comparable_support,
-              expected_props::less_equal_comparable_support);
-
-    EXPECT_EQ(arch_props::greater_equal_comparable_support,
-              expected_props::greater_equal_comparable_support);
-
-    EXPECT_EQ(arch_props::greater_than_comparable_support,
-              expected_props::greater_than_comparable_support);
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                        Equality comparable checks                        //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::equality_comparable_support) {
-    case ti::equality_comparable::maybe:
-      EXPECT_FALSE(EqualityComparable<arch>::value);
-      EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
-      break;
-    case ti::equality_comparable::yes:
-      EXPECT_TRUE(EqualityComparable<arch>::value);
-      EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
-      break;
-    case ti::equality_comparable::nothrow:
-      EXPECT_TRUE(EqualityComparable<arch>::value);
-      EXPECT_TRUE(NothrowEqualityComparable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                       Inequality comparable checks                       //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::inequality_comparable_support) {
-    case ti::inequality_comparable::maybe:
-      EXPECT_FALSE(InequalityComparable<arch>::value);
-      EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
-      break;
-    case ti::inequality_comparable::yes:
-      EXPECT_TRUE(InequalityComparable<arch>::value);
-      EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
-      break;
-    case ti::inequality_comparable::nothrow:
-      EXPECT_TRUE(InequalityComparable<arch>::value);
-      EXPECT_TRUE(NothrowInequalityComparable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                       Less than comparable checks                        //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::less_than_comparable_support) {
-    case ti::less_than_comparable::maybe:
-      EXPECT_FALSE(LessThanComparable<arch>::value);
-      EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
-      break;
-    case ti::less_than_comparable::yes:
-      EXPECT_TRUE(LessThanComparable<arch>::value);
-      EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
-      break;
-    case ti::less_than_comparable::nothrow:
-      EXPECT_TRUE(LessThanComparable<arch>::value);
-      EXPECT_TRUE(NothrowLessThanComparable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                      Less equal comparable checks                        //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::less_equal_comparable_support) {
-    case ti::less_equal_comparable::maybe:
-      EXPECT_FALSE(LessEqualComparable<arch>::value);
-      EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
-      break;
-    case ti::less_equal_comparable::yes:
-      EXPECT_TRUE(LessEqualComparable<arch>::value);
-      EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
-      break;
-    case ti::less_equal_comparable::nothrow:
-      EXPECT_TRUE(LessEqualComparable<arch>::value);
-      EXPECT_TRUE(NothrowLessEqualComparable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                     Greater equal comparable checks                      //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::greater_equal_comparable_support) {
-    case ti::greater_equal_comparable::maybe:
-      EXPECT_FALSE(GreaterEqualComparable<arch>::value);
-      EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
-      break;
-    case ti::greater_equal_comparable::yes:
-      EXPECT_TRUE(GreaterEqualComparable<arch>::value);
-      EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
-      break;
-    case ti::greater_equal_comparable::nothrow:
-      EXPECT_TRUE(GreaterEqualComparable<arch>::value);
-      EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                     Greater than comparable checks                       //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::greater_than_comparable_support) {
-    case ti::greater_than_comparable::maybe:
-      EXPECT_FALSE(GreaterThanComparable<arch>::value);
-      EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
-      break;
-    case ti::greater_than_comparable::yes:
-      EXPECT_TRUE(GreaterThanComparable<arch>::value);
-      EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
-      break;
-    case ti::greater_than_comparable::nothrow:
-      EXPECT_TRUE(GreaterThanComparable<arch>::value);
-      EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value);
-      break;
-  }
-}
-
-TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) {
-  using profile = typename TypeParam::profile;
-  using arch = typename TypeParam::arch;
-  using expected_profile = typename TypeParam::expected_profile;
-
-  using props = ti::PropertiesOfT<profile>;
-  using arch_props = ti::PropertiesOfArchetypeT<arch>;
-  using expected_props = ti::PropertiesOfT<expected_profile>;
-
-  // Make sure all of the properties are as expected.
-  // There are seemingly redundant tests here to make it easier to diagnose
-  // the specifics of the failure if something were to go wrong.
-  EXPECT_TRUE((std::is_same<props, arch_props>::value));
-  EXPECT_TRUE((std::is_same<props, expected_props>::value));
-  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
-
-  EXPECT_EQ(props::swappable_support, expected_props::swappable_support);
-
-  EXPECT_EQ(props::hashable_support, expected_props::hashable_support);
-
-  // Avoid additional error message noise when profile and archetype match with
-  // each other but were not what was expected.
-  if (!std::is_same<props, arch_props>::value) {
-    EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support);
-
-    EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support);
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                            Swappable checks                              //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::swappable_support) {
-    case ti::swappable::maybe:
-      EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value);
-      EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
-      break;
-    case ti::swappable::yes:
-      EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
-      EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
-      break;
-    case ti::swappable::nothrow:
-      EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
-      EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
-      break;
-  }
-
-  //////////////////////////////////////////////////////////////////////////////
-  //                             Hashable checks                              //
-  //////////////////////////////////////////////////////////////////////////////
-  switch (expected_props::hashable_support) {
-    case ti::hashable::maybe:
-#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
-      EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value);
-#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
-      break;
-    case ti::hashable::yes:
-      EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value);
-      break;
-  }
-}
-
-REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties,
-                            HasAppropriateAssignmentProperties,
-                            HasAppropriateComparisonProperties,
-                            HasAppropriateAuxilliaryProperties);
-
-template <class Profile, class Arch, class ExpectedProfile>
-struct ProfileAndExpectation {
-  using profile = Profile;
-  using arch = Arch;
-  using expected_profile = ExpectedProfile;
-};
-
-using CoreProfilesToTest = ::testing::Types<
-    // The terminating case of combine (all properties are "maybe").
-    ProfileAndExpectation<ti::CombineProfiles<>,
-                          ti::Archetype<ti::CombineProfiles<>>,
-                          ti::ConformanceProfile<>>,
-
-    // Core default constructor profiles
-    ProfileAndExpectation<
-        ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowDefaultConstructorProfile,
-        ti::HasNothrowDefaultConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialDefaultConstructorProfile,
-        ti::HasTrivialDefaultConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::trivial>>,
-
-    // Core move constructor profiles
-    ProfileAndExpectation<
-        ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowMoveConstructorProfile,
-        ti::HasNothrowMoveConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialMoveConstructorProfile,
-        ti::HasTrivialMoveConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::trivial>>,
-
-    // Core copy constructor profiles
-    ProfileAndExpectation<
-        ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::maybe,
-                               ti::copy_constructible::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowCopyConstructorProfile,
-        ti::HasNothrowCopyConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::maybe,
-                               ti::copy_constructible::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialCopyConstructorProfile,
-        ti::HasTrivialCopyConstructorArchetype,
-        ti::ConformanceProfile<ti::default_constructible::maybe,
-                               ti::move_constructible::maybe,
-                               ti::copy_constructible::trivial>>,
-
-    // Core move assignment profiles
-    ProfileAndExpectation<
-        ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::trivial>>,
-
-    // Core copy assignment profiles
-    ProfileAndExpectation<
-        ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::trivial>>,
-
-    // Core destructor profiles
-    ProfileAndExpectation<
-        ti::HasDestructorProfile, ti::HasDestructorArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
-    ProfileAndExpectation<
-        ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::trivial>>,
-
-    // Core equality comparable profiles
-    ProfileAndExpectation<
-        ti::HasEqualityProfile, ti::HasEqualityArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::nothrow>>,
-
-    // Core inequality comparable profiles
-    ProfileAndExpectation<
-        ti::HasInequalityProfile, ti::HasInequalityArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe,
-            ti::inequality_comparable::nothrow>>,
-
-    // Core less than comparable profiles
-    ProfileAndExpectation<
-        ti::HasLessThanProfile, ti::HasLessThanArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::nothrow>>,
-
-    // Core less equal comparable profiles
-    ProfileAndExpectation<
-        ti::HasLessEqualProfile, ti::HasLessEqualArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe,
-            ti::less_equal_comparable::nothrow>>,
-
-    // Core greater equal comparable profiles
-    ProfileAndExpectation<
-        ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::nothrow>>,
-
-    // Core greater than comparable profiles
-    ProfileAndExpectation<
-        ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::nothrow>>,
-
-    // Core swappable profiles
-    ProfileAndExpectation<
-        ti::HasSwapProfile, ti::HasSwapArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::yes>>,
-    ProfileAndExpectation<
-        ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
-
-    // Core hashable profiles
-    ProfileAndExpectation<
-        ti::HasStdHashSpecializationProfile,
-        ti::HasStdHashSpecializationArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::maybe,
-            ti::hashable::yes>>>;
-
-using CommonProfilesToTest = ::testing::Types<
-    // NothrowMoveConstructible
-    ProfileAndExpectation<
-        ti::NothrowMoveConstructibleProfile,
-        ti::NothrowMoveConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
-
-    // CopyConstructible
-    ProfileAndExpectation<
-        ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
-
-    // NothrowMovable
-    ProfileAndExpectation<
-        ti::NothrowMovableProfile, ti::NothrowMovableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
-            ti::copy_assignable::maybe, ti::destructible::nothrow,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
-
-    // Value
-    ProfileAndExpectation<
-        ti::ValueProfile, ti::ValueArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::nothrow,
-            ti::copy_assignable::yes, ti::destructible::nothrow,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
-
-    ////////////////////////////////////////////////////////////////////////////
-    //                  Common but also DefaultConstructible                  //
-    ////////////////////////////////////////////////////////////////////////////
-
-    // DefaultConstructibleNothrowMoveConstructible
-    ProfileAndExpectation<
-        ti::DefaultConstructibleNothrowMoveConstructibleProfile,
-        ti::DefaultConstructibleNothrowMoveConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::yes, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
-
-    // DefaultConstructibleCopyConstructible
-    ProfileAndExpectation<
-        ti::DefaultConstructibleCopyConstructibleProfile,
-        ti::DefaultConstructibleCopyConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::yes, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
-
-    // DefaultConstructibleNothrowMovable
-    ProfileAndExpectation<
-        ti::DefaultConstructibleNothrowMovableProfile,
-        ti::DefaultConstructibleNothrowMovableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::yes, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
-            ti::copy_assignable::maybe, ti::destructible::nothrow,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
-
-    // DefaultConstructibleValue
-    ProfileAndExpectation<
-        ti::DefaultConstructibleValueProfile,
-        ti::DefaultConstructibleValueArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::yes, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::nothrow,
-            ti::copy_assignable::yes, ti::destructible::nothrow,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>;
-
-using ComparableHelpersProfilesToTest = ::testing::Types<
-    // Equatable
-    ProfileAndExpectation<
-        ti::EquatableProfile, ti::EquatableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes>>,
-
-    // Comparable
-    ProfileAndExpectation<
-        ti::ComparableProfile, ti::ComparableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes,
-            ti::greater_than_comparable::yes>>,
-
-    // NothrowEquatable
-    ProfileAndExpectation<
-        ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::nothrow,
-            ti::inequality_comparable::nothrow>>,
-
-    // NothrowComparable
-    ProfileAndExpectation<
-        ti::NothrowComparableProfile, ti::NothrowComparableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::maybe,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::maybe,
-            ti::equality_comparable::nothrow,
-            ti::inequality_comparable::nothrow,
-            ti::less_than_comparable::nothrow,
-            ti::less_equal_comparable::nothrow,
-            ti::greater_equal_comparable::nothrow,
-            ti::greater_than_comparable::nothrow>>>;
-
-using CommonComparableProfilesToTest = ::testing::Types<
-    // ComparableNothrowMoveConstructible
-    ProfileAndExpectation<
-        ti::ComparableNothrowMoveConstructibleProfile,
-        ti::ComparableNothrowMoveConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes,
-            ti::greater_than_comparable::yes>>,
-
-    // ComparableCopyConstructible
-    ProfileAndExpectation<
-        ti::ComparableCopyConstructibleProfile,
-        ti::ComparableCopyConstructibleArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::maybe,
-            ti::copy_assignable::maybe, ti::destructible::nothrow,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes,
-            ti::greater_than_comparable::yes>>,
-
-    // ComparableNothrowMovable
-    ProfileAndExpectation<
-        ti::ComparableNothrowMovableProfile,
-        ti::ComparableNothrowMovableArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
-            ti::copy_assignable::maybe, ti::destructible::nothrow,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
-            ti::swappable::nothrow>>,
-
-    // ComparableValue
-    ProfileAndExpectation<
-        ti::ComparableValueProfile, ti::ComparableValueArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::maybe, ti::move_constructible::nothrow,
-            ti::copy_constructible::yes, ti::move_assignable::nothrow,
-            ti::copy_assignable::yes, ti::destructible::nothrow,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
-            ti::swappable::nothrow>>>;
-
-using TrivialProfilesToTest = ::testing::Types<
-    ProfileAndExpectation<
-        ti::TrivialSpecialMemberFunctionsProfile,
-        ti::TrivialSpecialMemberFunctionsArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::trivial, ti::move_constructible::trivial,
-            ti::copy_constructible::trivial, ti::move_assignable::trivial,
-            ti::copy_assignable::trivial, ti::destructible::trivial,
-            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
-            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
-            ti::greater_equal_comparable::maybe,
-            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
-
-    ProfileAndExpectation<
-        ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype,
-        ti::ConformanceProfile<
-            ti::default_constructible::trivial, ti::move_constructible::trivial,
-            ti::copy_constructible::trivial, ti::move_assignable::trivial,
-            ti::copy_assignable::trivial, ti::destructible::trivial,
-            ti::equality_comparable::yes, ti::inequality_comparable::yes,
-            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
-            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
-            ti::swappable::nothrow, ti::hashable::yes>>>;
-
-INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest);
-INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest);
-INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest,
-                               ComparableHelpersProfilesToTest);
-INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest,
-                               CommonComparableProfilesToTest);
-INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest);
-
-TEST(ConformanceTestingTest, Basic) {
-  using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
-                                      ti::NothrowComparableProfile>;
-
-  using lim = std::numeric_limits<float>;
-
-  ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float)
-      .INITIALIZER(-lim::infinity())
-      .INITIALIZER(lim::lowest())
-      .INITIALIZER(-1.f)
-      .INITIALIZER(-lim::min())
-      .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f))
-      .INITIALIZER(lim::min())
-      .INITIALIZER(1.f)
-      .INITIALIZER(lim::max())
-      .INITIALIZER(lim::infinity())
-      .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile);
-}
-
-struct BadMoveConstruct {
-  BadMoveConstruct() = default;
-  BadMoveConstruct(BadMoveConstruct&& other) noexcept
-      : value(other.value + 1) {}
-  BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default;
-  int value = 0;
-
-  friend bool operator==(BadMoveConstruct const& lhs,
-                         BadMoveConstruct const& rhs) {
-    return lhs.value == rhs.value;
-  }
-  friend bool operator!=(BadMoveConstruct const& lhs,
-                         BadMoveConstruct const& rhs) {
-    return lhs.value != rhs.value;
-  }
-};
-
-struct BadMoveAssign {
-  BadMoveAssign() = default;
-  BadMoveAssign(BadMoveAssign&& other) noexcept = default;
-  BadMoveAssign& operator=(BadMoveAssign&& other) noexcept {
-    int new_value = other.value + 1;
-    value = new_value;
-    return *this;
-  }
-  int value = 0;
-
-  friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
-    return lhs.value == rhs.value;
-  }
-  friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
-    return lhs.value != rhs.value;
-  }
-};
-
-enum class WhichCompIsBad { eq, ne, lt, le, ge, gt };
-
-template <WhichCompIsBad Which>
-struct BadCompare {
-  int value;
-
-  friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::eq ? lhs.value != rhs.value
-                                       : lhs.value == rhs.value;
-  }
-
-  friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::ne ? lhs.value == rhs.value
-                                       : lhs.value != rhs.value;
-  }
-
-  friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value
-                                       : lhs.value < rhs.value;
-  }
-
-  friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::le ? lhs.value > rhs.value
-                                       : lhs.value <= rhs.value;
-  }
-
-  friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::ge ? lhs.value < rhs.value
-                                       : lhs.value >= rhs.value;
-  }
-
-  friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) {
-    return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value
-                                       : lhs.value > rhs.value;
-  }
-};
-
-TEST(ConformanceTestingDeathTest, Failures) {
-  {
-    using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
-                                        ti::NothrowComparableProfile>;
-
-    // Note: The initializers are intentionally in the wrong order.
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float)
-        .INITIALIZER(1.f)
-        .INITIALIZER(0.f)
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using profile =
-        ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct)
-        .DUE_TO("Move construction")
-        .INITIALIZER(BadMoveConstruct())
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using profile =
-        ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign)
-        .DUE_TO("Move assignment")
-        .INITIALIZER(BadMoveAssign())
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-TEST(ConformanceTestingDeathTest, CompFailures) {
-  using profile = ti::ComparableProfile;
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::eq>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::ne>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::lt>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::le>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::ge>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-
-  {
-    using BadComp = BadCompare<WhichCompIsBad::gt>;
-
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
-        .DUE_TO("Comparison")
-        .INITIALIZER(BadComp{0})
-        .INITIALIZER(BadComp{1})
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-struct BadSelfMove {
-  BadSelfMove() = default;
-  BadSelfMove(BadSelfMove&&) = default;
-  BadSelfMove& operator=(BadSelfMove&& other) noexcept {
-    if (this == &other) {
-      broken_state = true;
-    }
-    return *this;
-  }
-
-  friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) {
-    return !(lhs.broken_state || rhs.broken_state);
-  }
-
-  friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) {
-    return lhs.broken_state || rhs.broken_state;
-  }
-
-  bool broken_state = false;
-};
-
-TEST(ConformanceTestingDeathTest, SelfMoveFailure) {
-  using profile = ti::EquatableNothrowMovableProfile;
-
-  {
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove)
-        .DUE_TO("Move assignment")
-        .INITIALIZER(BadSelfMove())
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-struct BadSelfCopy {
-  BadSelfCopy() = default;
-  BadSelfCopy(BadSelfCopy&&) = default;
-  BadSelfCopy(const BadSelfCopy&) = default;
-  BadSelfCopy& operator=(BadSelfCopy&&) = default;
-  BadSelfCopy& operator=(BadSelfCopy const& other) {
-    if (this == &other) {
-      broken_state = true;
-    }
-    return *this;
-  }
-
-  friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
-    return !(lhs.broken_state || rhs.broken_state);
-  }
-
-  friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
-    return lhs.broken_state || rhs.broken_state;
-  }
-
-  bool broken_state = false;
-};
-
-TEST(ConformanceTestingDeathTest, SelfCopyFailure) {
-  using profile = ti::EquatableValueProfile;
-
-  {
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy)
-        .DUE_TO("Copy assignment")
-        .INITIALIZER(BadSelfCopy())
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-struct BadSelfSwap {
-  friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept {
-    if (&lhs == &rhs) lhs.broken_state = true;
-  }
-
-  friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
-    return !(lhs.broken_state || rhs.broken_state);
-  }
-
-  friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
-    return lhs.broken_state || rhs.broken_state;
-  }
-
-  bool broken_state = false;
-};
-
-TEST(ConformanceTestingDeathTest, SelfSwapFailure) {
-  using profile = ti::EquatableNothrowMovableProfile;
-
-  {
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap)
-        .DUE_TO("Swap")
-        .INITIALIZER(BadSelfSwap())
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-struct BadDefaultInitializedMoveAssign {
-  BadDefaultInitializedMoveAssign() : default_initialized(true) {}
-  explicit BadDefaultInitializedMoveAssign(int v) : value(v) {}
-  BadDefaultInitializedMoveAssign(
-      BadDefaultInitializedMoveAssign&& other) noexcept
-      : value(other.value) {}
-  BadDefaultInitializedMoveAssign& operator=(
-      BadDefaultInitializedMoveAssign&& other) noexcept {
-    value = other.value;
-    if (default_initialized) ++value;  // Bad move if lhs is default initialized
-    return *this;
-  }
-
-  friend bool operator==(const BadDefaultInitializedMoveAssign& lhs,
-                         const BadDefaultInitializedMoveAssign& rhs) {
-    return lhs.value == rhs.value;
-  }
-
-  friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs,
-                         const BadDefaultInitializedMoveAssign& rhs) {
-    return lhs.value != rhs.value;
-  }
-
-  bool default_initialized = false;
-  int value = 0;
-};
-
-TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) {
-  using profile =
-      ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile,
-                          ti::EquatableProfile>;
-
-  {
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign)
-        .DUE_TO("move assignment")
-        .INITIALIZER(BadDefaultInitializedMoveAssign(0))
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-struct BadDefaultInitializedCopyAssign {
-  BadDefaultInitializedCopyAssign() : default_initialized(true) {}
-  explicit BadDefaultInitializedCopyAssign(int v) : value(v) {}
-  BadDefaultInitializedCopyAssign(
-      BadDefaultInitializedCopyAssign&& other) noexcept
-      : value(other.value) {}
-  BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other)
-      : value(other.value) {}
-
-  BadDefaultInitializedCopyAssign& operator=(
-      BadDefaultInitializedCopyAssign&& other) noexcept {
-    value = other.value;
-    return *this;
-  }
-
-  BadDefaultInitializedCopyAssign& operator=(
-      const BadDefaultInitializedCopyAssign& other) {
-    value = other.value;
-    if (default_initialized) ++value;  // Bad move if lhs is default initialized
-    return *this;
-  }
-
-  friend bool operator==(const BadDefaultInitializedCopyAssign& lhs,
-                         const BadDefaultInitializedCopyAssign& rhs) {
-    return lhs.value == rhs.value;
-  }
-
-  friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs,
-                         const BadDefaultInitializedCopyAssign& rhs) {
-    return lhs.value != rhs.value;
-  }
-
-  bool default_initialized = false;
-  int value = 0;
-};
-
-TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) {
-  using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile,
-                                      ti::EquatableProfile>;
-
-  {
-    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign)
-        .DUE_TO("copy assignment")
-        .INITIALIZER(BadDefaultInitializedCopyAssign(0))
-        .WITH_LOOSE_PROFILE(profile);
-  }
-}
-
-}  // namespace
diff --git a/third_party/abseil-cpp/absl/types/internal/parentheses.h b/third_party/abseil-cpp/absl/types/internal/parentheses.h
deleted file mode 100644
index 5aebee8..0000000
--- a/third_party/abseil-cpp/absl/types/internal/parentheses.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// parentheses.h
-// -----------------------------------------------------------------------------
-//
-// This file contains macros that expand to a left parenthesis and a right
-// parenthesis. These are in their own file and are generated from macros
-// because otherwise clang-format gets confused and clang-format off directives
-// do not help.
-//
-// The parentheses macros are used when wanting to require a rescan before
-// expansion of parenthesized text appearing after a function-style macro name.
-
-#ifndef ABSL_TYPES_INTERNAL_PARENTHESES_H_
-#define ABSL_TYPES_INTERNAL_PARENTHESES_H_
-
-#define ABSL_INTERNAL_LPAREN (
-
-#define ABSL_INTERNAL_RPAREN )
-
-#endif  // ABSL_TYPES_INTERNAL_PARENTHESES_H_
diff --git a/third_party/abseil-cpp/absl/types/internal/transform_args.h b/third_party/abseil-cpp/absl/types/internal/transform_args.h
deleted file mode 100644
index 4a0ab42..0000000
--- a/third_party/abseil-cpp/absl/types/internal/transform_args.h
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// transform_args.h
-// -----------------------------------------------------------------------------
-//
-// This file contains a higher-order macro that "transforms" each element of a
-// a variadic argument by a provided secondary macro.
-
-#ifndef ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
-#define ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
-
-//
-// ABSL_INTERNAL_CAT(a, b)
-//
-// This macro takes two arguments and concatenates them together via ## after
-// expansion.
-//
-// Example:
-//
-//   ABSL_INTERNAL_CAT(foo_, bar)
-//
-// Results in:
-//
-//   foo_bar
-#define ABSL_INTERNAL_CAT(a, b) ABSL_INTERNAL_CAT_IMPL(a, b)
-#define ABSL_INTERNAL_CAT_IMPL(a, b) a##b
-
-//
-// ABSL_INTERNAL_TRANSFORM_ARGS(m, ...)
-//
-// This macro takes another macro as an argument followed by a trailing series
-// of additional parameters (up to 32 additional arguments). It invokes the
-// passed-in macro once for each of the additional arguments, with the
-// expansions separated by commas.
-//
-// Example:
-//
-//   ABSL_INTERNAL_TRANSFORM_ARGS(MY_MACRO, a, b, c)
-//
-// Results in:
-//
-//   MY_MACRO(a), MY_MACRO(b), MY_MACRO(c)
-//
-// TODO(calabrese) Handle no arguments as a special case.
-#define ABSL_INTERNAL_TRANSFORM_ARGS(m, ...)             \
-  ABSL_INTERNAL_CAT(ABSL_INTERNAL_TRANSFORM_ARGS,        \
-                    ABSL_INTERNAL_NUM_ARGS(__VA_ARGS__)) \
-  (m, __VA_ARGS__)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS1(m, a0) m(a0)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS2(m, a0, a1) m(a0), m(a1)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS3(m, a0, a1, a2) m(a0), m(a1), m(a2)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS4(m, a0, a1, a2, a3) \
-  m(a0), m(a1), m(a2), m(a3)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS5(m, a0, a1, a2, a3, a4) \
-  m(a0), m(a1), m(a2), m(a3), m(a4)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS6(m, a0, a1, a2, a3, a4, a5) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS7(m, a0, a1, a2, a3, a4, a5, a6) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS8(m, a0, a1, a2, a3, a4, a5, a6, a7) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS9(m, a0, a1, a2, a3, a4, a5, a6, a7, a8) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS10(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9)                                    \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS11(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10)                               \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), m(a10)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS12(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11)                          \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS13(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12)                     \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS14(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13)                \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS15(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14)           \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS16(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15)      \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS17(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS18(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17)                                   \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS19(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18)                              \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS20(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18, a19)                         \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS21(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18, a19, a20)                    \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS22(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18, a19, a20, a21)               \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS23(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18, a19, a20, a21, a22)          \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS24(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
-                                       a9, a10, a11, a12, a13, a14, a15, a16, \
-                                       a17, a18, a19, a20, a21, a22, a23)     \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS25(m, a0, a1, a2, a3, a4, a5, a6, a7, a8,  \
-                                       a9, a10, a11, a12, a13, a14, a15, a16,  \
-                                       a17, a18, a19, a20, a21, a22, a23, a24) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS26(                                       \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25)                         \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS27(                                       \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26)                    \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS28(                                       \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27)               \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS29(                                       \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28)          \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
-      m(a28)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS30(                                       \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29)     \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
-      m(a28), m(a29)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS31(                                        \
-    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,   \
-    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27),  \
-      m(a28), m(a29), m(a30)
-
-#define ABSL_INTERNAL_TRANSFORM_ARGS32(m, a0, a1, a2, a3, a4, a5, a6, a7, a8,  \
-                                       a9, a10, a11, a12, a13, a14, a15, a16,  \
-                                       a17, a18, a19, a20, a21, a22, a23, a24, \
-                                       a25, a26, a27, a28, a29, a30, a31)      \
-  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
-      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
-      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27),  \
-      m(a28), m(a29), m(a30), m(a31)
-
-#define ABSL_INTERNAL_NUM_ARGS_IMPL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,    \
-                                    a10, a11, a12, a13, a14, a15, a16, a17,    \
-                                    a18, a19, a20, a21, a22, a23, a24, a25,    \
-                                    a26, a27, a28, a29, a30, a31, result, ...) \
-  result
-
-#define ABSL_INTERNAL_FORCE_EXPANSION(...) __VA_ARGS__
-
-#define ABSL_INTERNAL_NUM_ARGS(...)                                            \
-  ABSL_INTERNAL_FORCE_EXPANSION(ABSL_INTERNAL_NUM_ARGS_IMPL(                   \
-      __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \
-      17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, ))
-
-#endif  // ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
diff --git a/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch b/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch
index 15941972..98a8499 100644
--- a/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch
+++ b/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch
@@ -14,19 +14,6 @@
  // -------------------------------------------------------------------------
  // Decide which features are enabled
  
-diff --git a/third_party/abseil-cpp/absl/base/thread_annotations.h b/third_party/abseil-cpp/absl/base/thread_annotations.h
-index 5f51c0c2d2d5..10b9bde551a7 100644
---- a/third_party/abseil-cpp/absl/base/thread_annotations.h
-+++ b/third_party/abseil-cpp/absl/base/thread_annotations.h
-@@ -35,8 +35,6 @@
- #define ABSL_BASE_THREAD_ANNOTATIONS_H_
- 
- #include "absl/base/config.h"
--// TODO(mbonadei): Remove after the backward compatibility period.
--#include "absl/base/internal/thread_annotations.h"  // IWYU pragma: export
- 
- #if defined(__clang__)
- #define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
 diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel
 index 65ff0ddef9fd..d6fbf3581158 100644
 --- a/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -41,16 +28,6 @@
      hdrs = [
          "dynamic_annotations.h",
      ],
-@@ -131,9 +128,6 @@ cc_library(
-
- cc_library(
-     name = "core_headers",
--    srcs = [
--        "internal/thread_annotations.h",
--    ],
-     hdrs = [
-         "attributes.h",
-         "const_init.h",
 diff --git a/third_party/abseil-cpp/CMake/AbseilDll.cmake b/third_party/abseil-cpp/CMake/AbseilDll.cmake
 index 00cddb84c6b7f..a2b8b103885a6 100644
 --- a/third_party/abseil-cpp/CMake/AbseilDll.cmake
@@ -63,14 +40,6 @@
    "base/internal/endian.h"
    "base/internal/errno_saver.h"
    "base/internal/fast_type_id.h"
-@@ -41,7 +40,6 @@ set(ABSL_INTERNAL_DLL_FILES
-   "base/internal/spinlock_wait.h"
-   "base/internal/sysinfo.cc"
-   "base/internal/sysinfo.h"
--  "base/internal/thread_annotations.h"
-   "base/internal/thread_identity.cc"
-   "base/internal/thread_identity.h"
-   "base/internal/throw_delegate.cc"
 diff --git a/third_party/abseil-cpp/absl/base/CMakeLists.txt b/third_party/abseil-cpp/absl/base/CMakeLists.txt
 index ed55093abe80f..6908182e97c86 100644
 --- a/third_party/abseil-cpp/absl/base/CMakeLists.txt
@@ -84,11 +53,3 @@
    COPTS
      ${ABSL_DEFAULT_COPTS}
    DEPS
-@@ -128,7 +126,6 @@ absl_cc_library(
-     "optimization.h"
-     "port.h"
-     "thread_annotations.h"
--    "internal/thread_annotations.h"
-   COPTS
-     ${ABSL_DEFAULT_COPTS}
-   DEPS
diff --git a/third_party/abseil-cpp/roll_abseil.py b/third_party/abseil-cpp/roll_abseil.py
index 365b4602..c13151b 100755
--- a/third_party/abseil-cpp/roll_abseil.py
+++ b/third_party/abseil-cpp/roll_abseil.py
@@ -75,7 +75,6 @@
   for patch in os.listdir(os.path.join(abseil_in_chromium_dir, 'patches')):
     subprocess.check_call(['patch', '--strip', '1', '-i', os.path.join(abseil_in_chromium_dir, 'patches', patch)])
 
-  os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'thread_annotations.h'))
   os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'dynamic_annotations.h'))
 
 
diff --git a/third_party/angle b/third_party/angle
index b9e9c58b..bc7fc39 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit b9e9c58bbd779cfeb98b16c57fb76001379b4975
+Subproject commit bc7fc3997be824e3029da785ba5bc2e3df25e546
diff --git a/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.cc b/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.cc
index 9f6f75b..1cdf02c 100644
--- a/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.cc
+++ b/third_party/blink/renderer/core/inspector/thread_debugger_common_impl.cc
@@ -967,9 +967,7 @@
   // TODO(dgozman): we can save on a copy here if trace macro would take a
   // pointer with length.
   TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(
-      "blink.console", ToCoreString(title).Utf8().c_str(),
-      TRACE_ID_WITH_SCOPE(ToCoreString(title).Utf8().c_str(),
-                          TRACE_ID_LOCAL(this)));
+      "blink.console", ToCoreString(title).Utf8().c_str(), this);
 }
 
 void ThreadDebuggerCommonImpl::consoleTimeEnd(
@@ -977,9 +975,7 @@
   // TODO(dgozman): we can save on a copy here if trace macro would take a
   // pointer with length.
   TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(
-      "blink.console", ToCoreString(title).Utf8().c_str(),
-      TRACE_ID_WITH_SCOPE(ToCoreString(title).Utf8().c_str(),
-                          TRACE_ID_LOCAL(this)));
+      "blink.console", ToCoreString(title).Utf8().c_str(), this);
 }
 
 void ThreadDebuggerCommonImpl::consoleTimeStamp(
diff --git a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
index 2e6673b..3928674c 100644
--- a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
+++ b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
@@ -152,9 +152,9 @@
   std::memcpy(other.Data(), Data(), DataLength());
 }
 
-void* ArrayBufferContents::AllocateMemoryWithFlags(size_t size,
-                                                   InitializationPolicy policy,
-                                                   unsigned int flags) {
+template <unsigned int flags>
+void* ArrayBufferContents::AllocateMemory(size_t size,
+                                          InitializationPolicy policy) {
   // The array buffer contents are sometimes expected to be 16-byte aligned in
   // order to get the best optimization of SSE, especially in case of audio and
   // video buffers.  Hence, align the given size up to 16-byte boundary.
@@ -181,14 +181,22 @@
   // hooks (which are e.g. used by the heap profiler) should still be invoked.
   // Using the kNoOverrideHooks and kNoMemoryToolOverride flags with
   // accomplishes this.
-  flags |= partition_alloc::AllocFlags::kNoOverrideHooks;
-  flags |= partition_alloc::AllocFlags::kNoMemoryToolOverride;
+  constexpr auto new_flags = flags |
+                             partition_alloc::AllocFlags::kNoOverrideHooks |
+                             partition_alloc::AllocFlags::kNoMemoryToolOverride;
+#else
+  constexpr auto new_flags = flags;
 #endif
+  void* data;
   if (policy == kZeroInitialize) {
-    flags |= partition_alloc::AllocFlags::kZeroFill;
+    data = WTF::Partitions::ArrayBufferPartition()
+               ->Alloc<new_flags | partition_alloc::AllocFlags::kZeroFill>(
+                   size, WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
+  } else {
+    data = WTF::Partitions::ArrayBufferPartition()->Alloc<new_flags>(
+        size, WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
   }
-  void* data = WTF::Partitions::ArrayBufferPartition()->AllocWithFlags(
-      flags, size, WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
+
   if (partition_alloc::internal::kAlignment < 16) {
     char* ptr = reinterpret_cast<char*>(data);
     DCHECK_EQ(base::bits::AlignUp(ptr, 16), ptr)
@@ -201,15 +209,14 @@
 
 void* ArrayBufferContents::AllocateMemoryOrNull(size_t size,
                                                 InitializationPolicy policy) {
-  return AllocateMemoryWithFlags(size, policy,
-                                 partition_alloc::AllocFlags::kReturnNull);
+  return AllocateMemory<partition_alloc::AllocFlags::kReturnNull>(size, policy);
 }
 
 void ArrayBufferContents::FreeMemory(void* data) {
   InstanceCounters::DecrementCounter(
       InstanceCounters::kArrayBufferContentsCounter);
 #ifdef V8_ENABLE_SANDBOX
-  // See |AllocateMemoryWithFlags|.
+  // See |AllocateMemory|.
   WTF::Partitions::ArrayBufferPartition()
       ->Free<partition_alloc::FreeFlags::kNoMemoryToolOverride>(data);
 #else
diff --git a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
index eed68f28..ef05696 100644
--- a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
+++ b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
@@ -137,9 +137,8 @@
   static void FreeMemory(void*);
 
  private:
-  static void* AllocateMemoryWithFlags(size_t,
-                                       InitializationPolicy,
-                                       unsigned int);
+  template <unsigned int flags>
+  static void* AllocateMemory(size_t, InitializationPolicy);
 
   std::shared_ptr<v8::BackingStore> backing_store_;
 };
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string.cc b/third_party/blink/renderer/platform/bindings/parkable_string.cc
index f572a6f..e72efd8 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -130,9 +130,9 @@
  public:
   explicit NullableCharBuffer(size_t size) {
     data_ = reinterpret_cast<char*>(
-        WTF::Partitions::BufferPartition()->AllocWithFlags(
-            partition_alloc::AllocFlags::kReturnNull, size,
-            "NullableCharBuffer"));
+        WTF::Partitions::BufferPartition()
+            ->AllocInline<partition_alloc::AllocFlags::kReturnNull>(
+                size, "NullableCharBuffer"));
     size_ = size;
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc b/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
index 3aa8e53..81084be 100644
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
@@ -427,10 +427,10 @@
 }
 
 sk_sp<SkData> TryAllocateSkData(size_t size) {
-  void* buffer = WTF::Partitions::BufferPartition()->AllocWithFlags(
-      partition_alloc::AllocFlags::kReturnNull |
-          partition_alloc::AllocFlags::kZeroFill,
-      size, "SkData");
+  void* buffer =
+      WTF::Partitions::BufferPartition()
+          ->AllocInline<partition_alloc::AllocFlags::kReturnNull |
+                        partition_alloc::AllocFlags::kZeroFill>(size, "SkData");
   if (!buffer)
     return nullptr;
   return SkData::MakeWithProc(
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index ff9c21e1..23ebb09 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -788,10 +788,9 @@
 
   auto context_provider =
       base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
-          gpu_channel_host, gpu_memory_buffer_manager, kGpuStreamIdDefault,
-          kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, GURL(url),
-          automatic_flushes, support_locking, support_grcontext, limits,
-          attributes,
+          gpu_channel_host, kGpuStreamIdDefault, kGpuStreamPriorityDefault,
+          gpu::kNullSurfaceHandle, GURL(url), automatic_flushes,
+          support_locking, support_grcontext, limits, attributes,
           viz::command_buffer_metrics::ContextType::RENDER_COMPOSITOR);
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
index 1d005d6..69a21ca 100644
--- a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
+++ b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -393,8 +393,8 @@
 void* Partitions::FastZeroedMalloc(size_t n, const char* type_name) {
   auto* fast_malloc_partition = FastMallocPartition();
   if (UNLIKELY(fast_malloc_partition)) {
-    return fast_malloc_partition->AllocWithFlags(
-        partition_alloc::AllocFlags::kZeroFill, n, type_name);
+    return fast_malloc_partition
+        ->AllocInline<partition_alloc::AllocFlags::kZeroFill>(n, type_name);
   } else {
     return calloc(n, 1);
   }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 182a5495..b59e5ca 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6785,6 +6785,3 @@
 crbug.com/1475824 [ Mac10.15 ] external/wpt/fetch/api/basic/scheme-blob.sub.any.worker.html [ Failure Pass ]
 crbug.com/1475824 [ Mac10.15 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/basic/scheme-blob.sub.any.html [ Failure Pass ]
 crbug.com/1475824 [ Mac10.15 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/basic/scheme-blob.sub.any.worker.html [ Failure Pass ]
-
-# Gardener 2023-08-29
-crbug.com/1476723 [ Mac10.15 ] external/wpt/webrtc/RTCDataChannel-binaryType.window.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index d42c689..27ed500a 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
@@ -279726,6 +279726,16 @@
    }
   },
   "support": {
+   ".cache": {
+    "gitignore2.json": [
+     "9f02208355d223b2c6423a419cce9a76cfe51f07",
+     []
+    ],
+    "mtime.json": [
+     "e388689318fdd6391a5cdf483f921192486d0f4e",
+     []
+    ]
+   },
    ".gitignore": [
     "d93e645d547894b50149d3726de2654957b6e06f",
     []
@@ -334658,6 +334668,10 @@
       "5c1e91ea85823339ba30fafb8863391090ba9f4c",
       []
      ],
+     "page-name-fixed-pos-001-print.html.ini": [
+      "d73f3034b4d5a3bc4c278db10011a8a3b6f90b43",
+      []
+     ],
      "page-name-flex-001-print-ref.html": [
       "8cd606f8040a94d13ed80edbd11ddae376307bea",
       []
@@ -352610,6 +352624,14 @@
       "a448fc800d26f26f7976bb9358251a5c392262e1",
       []
      ],
+     "factory-font-relative-length-expected.txt": [
+      "02b679299029a7cffd2b98525bd4ade548c78b3d",
+      []
+     ],
+     "factory-font-relative-length.html.ini": [
+      "5aeba0740fdc794f04d8c458150cb0c9079e1d6e",
+      []
+     ],
      "historical-expected.txt": [
       "b53d7d1fbce7b381f65fb9482b610339d7f4e011",
       []
@@ -357499,7 +357521,7 @@
       []
      ],
      "sin-cos-tan-serialize-expected.txt": [
-      "7f5d851bd5e07a1ebc0d096a0232410b20eb5559",
+      "3f0377fc0ad934f0df8be5b419bbc854acef9a76",
       []
      ],
      "sin-cos-tan-serialize.html.ini": [
@@ -368404,7 +368426,7 @@
        []
       ],
       "scrollend-event-for-user-scroll.html.ini": [
-       "ef3da60e35d195e5b4f33bc1543eefff85a5b91b",
+       "5f77484df3be0c221fa57f83418e1fc2dc7aed31",
        []
       ],
       "scrollend-event-not-fired-after-removing-scroller.tentative.html.ini": [
@@ -376479,7 +376501,7 @@
       []
      ],
      "trusted-scoring-signals.https.sub.window.js.ini": [
-      "bd5b3d7e50ab7fa5b4abfedcbcb0653d0e87daf4",
+      "8aee48ab40f72aae7da6c5edd89a71b50ad8402c",
       []
      ]
     }
@@ -393509,7 +393531,7 @@
         []
        ],
        "sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini": [
-        "6b38ca4849da6a3aa161e78954cf4ef6b65c0815",
+        "bf36605f651a5456c56db2ca276636e082420964",
         []
        ],
        "sandbox-top-navigation-child.tentative.sub.window.js.ini": [
@@ -394678,6 +394700,10 @@
         "37d4b1b47146bcea345fb47a8d242264c509ec88",
         []
        ],
+       "selectlist-button-type-behavior.tentative.html.ini": [
+        "0d237c650722bdee63a9ecbd4fbd9ea48d150e5c",
+        []
+       ],
        "selectlist-default-button-slot-ref.html": [
         "faa96e1f2724a8f484a2211ba90c7c8ef3a1d478",
         []
@@ -409441,6 +409467,10 @@
      "c105ab09d9a41a7beae2e8f8f2ce32b12a555917",
      []
     ],
+    "pointerevent_touch-action-keyboard.html.ini": [
+     "76aaf43d9d6dd7075fd08e88d9bb04566badee83",
+     []
+    ],
     "pointerevent_touch-action-modified_touch.html.ini": [
      "ec197ae69953d39c452fcc41ac6ac9506faed906",
      []
@@ -412272,7 +412302,7 @@
      []
     ],
     "content-type-parsing.html.ini": [
-     "aeee57dfb8ae837995b141c866c63681ba6d0c7e",
+     "822380838c49d416bee4edd3e16332616fc3d0ce",
      []
     ],
     "frameset-timing.html": [
@@ -422310,7 +422340,7 @@
        []
       ],
       "mouseover-out.html.ini": [
-       "f5a4528bc84b8492f5a5b64f950124e8f6d9383c",
+       "291f052364511b730c5b52c945376a93c9e0e406",
        []
       ],
       "wheel-basic.html.ini": [
@@ -497830,6 +497860,13 @@
        {}
       ]
      ],
+     "factory-font-relative-length.html": [
+      "f7e41ee29768cde6a4ead585ebfdcd42d35ee525",
+      [
+       null,
+       {}
+      ]
+     ],
      "factory-frequency.html": [
       "56a544b32f4969d00a7299403d6c02393758ab39",
       [
@@ -501557,7 +501594,7 @@
       ]
      ],
      "sin-cos-tan-serialize.html": [
-      "c6a25e960252632646c521d4b9624f01594c7da8",
+      "59d682421da132840e3eb5519a756282b09be8bd",
       [
        null,
        {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
index 643232d..6da930a0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 910 tests; 898 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 910 tests; 907 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Property color value 'rgb(from rebeccapurple r g b)'
 PASS Property color value 'rgb(from rebeccapurple r g b / alpha)'
 PASS Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)'
@@ -896,19 +896,28 @@
 PASS Property color value 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)'
 PASS Property color value 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)'
 PASS Property color value 'rgb(from var(--bg-color) r g b / 80%)'
-FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 23.138971 +/- 0.0001, expected 23.138971 but got 23.1363
+PASS Property color value 'lch(from var(--color) calc(l / 2) c h)'
 PASS Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))'
-FAIL Property color value 'lch(from var(--color) l 0 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 46.277943 +/- 0.0001, expected 46.277943 but got 46.2725
+PASS Property color value 'lch(from var(--color) l 0 h)'
 PASS Property color value 'rgb(from indianred 255 g b)'
-FAIL Property color value 'hsl(from var(--accent) calc(h + 180deg) s l)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 178 +/- 0.0001, expected 178 but got 0
-FAIL Property color value 'lab(from var(--mycolor) l a b / 100%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
-FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha * 0.8))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
-FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha - 20%))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
-FAIL Property color value 'lab(from var(--mycolor) l 0 0)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
-FAIL Property color value 'lch(from peru calc(l * 0.8) c h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 49.80138 +/- 0.0001, expected 49.80138 but got 49.7972
-FAIL Property color value 'LCH(from var(--accent) l c calc(h + 180deg))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 65.49473 +/- 0.0001, expected 65.49473 but got 0
-FAIL Property color value 'lch(from var(--mycolor) l 0 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
-FAIL Property color value 'var(--mygray)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
-FAIL Property color value 'lch(from var(--mygray) l 30 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 62.746
+FAIL Property color value 'hsl(from var(--accent) calc(h + 180deg) s l)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: rgb(178, 32, 40).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 178 +/- 0.0001, expected 178 but got 0
+PASS Property color value 'lab(from var(--mycolor) l a b / 100%)'
+PASS Property color value 'lab(from var(--mycolor) l a b / calc(alpha * 0.8))'
+FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha - 20%))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lab(62.751923 52.45802 -34.117283 / 0.8).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
+PASS Property color value 'lab(from var(--mycolor) l 0 0)'
+PASS Property color value 'lch(from peru calc(l * 0.8) c h)'
+FAIL Property color value 'LCH(from var(--accent) l c calc(h + 180deg))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(65.49473 39.446903 10.114471).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 65.49473 +/- 0.0001, expected 65.49473 but got 0
+PASS Property color value 'lch(from var(--mycolor) l 0 h)'
+PASS Property color value 'var(--mygray)'
+PASS Property color value 'lch(from var(--mygray) l 30 h)'
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color.html
index 6982a49..44d29a0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-relative-color.html
@@ -676,17 +676,18 @@
       fuzzy_test_computed_color(`color(from color(${colorSpace} 7 -20.5 100 / none) ${colorSpace} x y z / alpha)`,               `color(${resultColorSpace} 7 -20.5 100 / 0)`);
   }
 
-    // Spec Examples
+    // Spec Examples. Many of these have multiple stages of calculations so minor disagreements in the values of keyword colors and other
+    // constants can compound. Thus some of these tests have wider epsilons.
 
     // Example 11.
     fuzzy_test_computed_color(`rgb(from var(--bg-color) r g b / 80%)`, `rgba(0, 0, 255, 0.8)`);
 
-    // Example 12.
-    fuzzy_test_computed_color(`lch(from var(--color) calc(l / 2) c h)`, `lch(23.138971 67.989716 134.39125)`);
+    // Example 12. This particular test does a lot of math so a wider epsilon is needed.
+    fuzzy_test_computed_color(`lch(from var(--color) calc(l / 2) c h)`, `lch(23.14 67.99 134.39)`, 0.02 /* epsilon */);
 
     // Example 13.
-    fuzzy_test_computed_color(`rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))`, `rgb(76, 76, 76)`)
-    fuzzy_test_computed_color(`lch(from var(--color) l 0 h)`, `lch(46.277943 0 134.39125)`)
+    fuzzy_test_computed_color(`rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))`, `rgb(76, 76, 76)`);
+    fuzzy_test_computed_color(`lch(from var(--color) l 0 h)`, `lch(46.28 0 134.39)`, 0.02 /* epsilon */);
 
     // Example 14.
     fuzzy_test_computed_color(`rgb(from indianred 255 g b)`, `rgb(255, 92, 92)`);
@@ -695,23 +696,23 @@
     fuzzy_test_computed_color(`hsl(from var(--accent) calc(h + 180deg) s l)`, `rgb(178, 32, 40)`);
 
     // Example 16.
-    fuzzy_test_computed_color(`lab(from var(--mycolor) l a b / 100%)`, `lab(62.751923 52.45802 -34.117283)`);
-    fuzzy_test_computed_color(`lab(from var(--mycolor) l a b / calc(alpha * 0.8))`, `lab(62.751923 52.45802 -34.117283 / 0.8)`);
+    fuzzy_test_computed_color(`lab(from var(--mycolor) l a b / 100%)`, `lab(62.75 52.46 -34.12)`, 0.02 /* epsilon */);
+    fuzzy_test_computed_color(`lab(from var(--mycolor) l a b / calc(alpha * 0.8))`, `lab(62.75 52.46 -34.12 / 0.8)`, 0.02 /* epsilon */);
     fuzzy_test_computed_color(`lab(from var(--mycolor) l a b / calc(alpha - 20%))`, `lab(62.751923 52.45802 -34.117283 / 0.8)`);
 
     // Example 17.
-    fuzzy_test_computed_color(`lab(from var(--mycolor) l 0 0)`, `lab(62.751923 0 0)`);
+    fuzzy_test_computed_color(`lab(from var(--mycolor) l 0 0)`, `lab(62.75 0 0)`, 0.02 /* epsilon */);
 
     // Example 18.
-    fuzzy_test_computed_color(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80138 54.003296 63.680317)`);
+    fuzzy_test_computed_color(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80 54 63.68)`, 0.02 /* epsilon */);
 
     // Example 19.
     fuzzy_test_computed_color(`LCH(from var(--accent) l c calc(h + 180deg))`, `lch(65.49473 39.446903 10.114471)`);
 
     // Example 20.
-    fuzzy_test_computed_color(`lch(from var(--mycolor) l 0 h)`, `lch(62.751923 0 326.96112)`);
-    fuzzy_test_computed_color(`var(--mygray)`, `lch(62.751923 0 326.96112)`);
-    fuzzy_test_computed_color(`lch(from var(--mygray) l 30 h)`, `lch(62.751923 30 326.96112)`);
+    fuzzy_test_computed_color(`lch(from var(--mycolor) l 0 h)`, `lch(62.75 0 326.96)`, 0.02 /* epsilon */);
+    fuzzy_test_computed_color(`var(--mygray)`, `lch(62.75 0 326.96)`, 0.02 /* epsilon */);
+    fuzzy_test_computed_color(`lch(from var(--mygray) l 30 h)`, `lch(62.75 30 326.96)`, 0.02 /* epsilon */);
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt
deleted file mode 100644
index a518847..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt
+++ /dev/null
@@ -1,158 +0,0 @@
-This is a testharness.js-based test.
-Found 154 tests; 130 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS e.style['color'] = "rgb(from rebeccapurple r 10deg 10)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 10 10deg)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 10deg g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) r 10deg 10)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10deg)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) 10deg g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple red g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple l g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "rgba(from rebeccapurple r g b)" should not set the property value
-PASS e.style['color'] = "rgba(from rgb(10%, 20%, 30%, 40%) r g b / alpha)" should not set the property value
-FAIL e.style['color'] = "hsl(from rebeccapurple s h l)" should not set the property value assert_equals: expected "" but got "rgb(255, 0, 0)"
-FAIL e.style['color'] = "hsl(from rebeccapurple s s s / s)" should not set the property value assert_equals: expected "" but got "rgba(191, 65, 64, 0.5)"
-FAIL e.style['color'] = "hsl(from rebeccapurple h h h / h)" should not set the property value assert_equals: expected "" but got "rgb(255, 255, 0)"
-FAIL e.style['color'] = "hsl(from rebeccapurple alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "rgb(255, 255, 255)"
-FAIL e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) s h l)" should not set the property value assert_equals: expected "" but got "rgba(255, 0, 0, 0.4)"
-FAIL e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)" should not set the property value assert_equals: expected "" but got "rgba(191, 65, 64, 0.5)"
-FAIL e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)" should not set the property value assert_equals: expected "" but got "rgb(255, 255, 0)"
-FAIL e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "rgba(143, 62, 61, 0.4)"
-PASS e.style['color'] = "hsl(from rebeccapurple h 10% 10)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h 10 10%)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 10% s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h 10% 10)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h 10 10%)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) 10% s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple hue s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple x s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "hsla(from rebeccapurple h s l)" should not set the property value
-PASS e.style['color'] = "hsla(from rgb(10%, 20%, 30%, 40%) h s l / alpha)" should not set the property value
-FAIL e.style['color'] = "hwb(from rebeccapurple w h b)" should not set the property value assert_equals: expected "" but got "rgb(255, 255, 255)"
-FAIL e.style['color'] = "hwb(from rebeccapurple b b b / b)" should not set the property value assert_equals: expected "" but got "rgba(153, 102, 102, 0.4)"
-FAIL e.style['color'] = "hwb(from rebeccapurple h h h / h)" should not set the property value assert_equals: expected "" but got "rgb(128, 128, 128)"
-FAIL e.style['color'] = "hwb(from rebeccapurple alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "rgb(128, 128, 128)"
-FAIL e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) w b h)" should not set the property value assert_equals: expected "" but got "rgba(1, 1, 1, 0.4)"
-FAIL e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)" should not set the property value assert_equals: expected "" but got "rgba(128, 128, 128, 0.7)"
-FAIL e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)" should not set the property value assert_equals: expected "" but got "rgb(128, 128, 128)"
-FAIL e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "rgba(153, 102, 102, 0.4)"
-PASS e.style['color'] = "hwb(from rebeccapurple h 10% 10)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h 10 10%)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 10% w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h 10% 10)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h 10 10%)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) 10% w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple hue w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple x w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) 10deg a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) 10deg a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) lightness a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) x a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) h g b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) 10deg a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) 10deg a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) lightness a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) x a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) h g b)" should not set the property value
-FAIL e.style['color'] = "lch(from lch(.70 45 30) h l c / alpha)" should not set the property value assert_equals: expected "" but got "lch(30 0.7 45)"
-FAIL e.style['color'] = "lch(from lch(.70 45 30) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "lch(1 1 1)"
-FAIL e.style['color'] = "lch(from lch(.70 45 30 / 40%) h l c / alpha)" should not set the property value assert_equals: expected "" but got "lch(30 0.7 45 / 0.4)"
-FAIL e.style['color'] = "lch(from lch(.70 45 30 / 40%) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "lch(0.4 0.4 0.4 / 0.4)"
-PASS e.style['color'] = "lch(from lch(.70 45 30) l 10deg h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) l c 10%)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) 10deg c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) l 10deg h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) l c 10%)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) 10deg c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) lightness c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) x c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) l g b)" should not set the property value
-FAIL e.style['color'] = "oklch(from oklch(.70 45 30) h l c / alpha)" should not set the property value assert_equals: expected "" but got "oklch(0.3 70 45)"
-FAIL e.style['color'] = "oklch(from oklch(.70 45 30) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "oklch(0.01 1 1)"
-FAIL e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) h l c / alpha)" should not set the property value assert_equals: expected "" but got "oklch(0.3 70 45 / 0.4)"
-FAIL e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) alpha alpha alpha / alpha)" should not set the property value assert_equals: expected "" but got "oklch(0.004 0.4 0.4 / 0.4)"
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l 10deg h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l c 10%)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) 10deg c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) l 10deg h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) l c 10%)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) 10deg c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) lightness c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) x c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz l y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 l y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 l y z)" should not set the property value
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color.html
index 1e95ef3..db0aa0b2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid-relative-color.html
@@ -35,16 +35,6 @@
 
     // hsl(from ...)
 
-    // Testing invalid permutation (types don't match).
-    test_invalid_value(`color`, `hsl(from rebeccapurple s h l)`);
-    test_invalid_value(`color`, `hsl(from rebeccapurple s s s / s)`);
-    test_invalid_value(`color`, `hsl(from rebeccapurple h h h / h)`);
-    test_invalid_value(`color`, `hsl(from rebeccapurple alpha alpha alpha / alpha)`);
-    test_invalid_value(`color`, `hsl(from rgb(10%, 20%, 30%, 40%) s h l)`);
-    test_invalid_value(`color`, `hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)`);
-    test_invalid_value(`color`, `hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)`);
-    test_invalid_value(`color`, `hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`);
-
     // Testing invalid values.
     test_invalid_value(`color`, `hsl(from rebeccapurple h 10% 10)`);
     test_invalid_value(`color`, `hsl(from rebeccapurple h 10 10%)`);
@@ -64,16 +54,6 @@
 
     // hwb(from ...)
 
-    // Testing invalid permutation (types don't match).
-    test_invalid_value(`color`, `hwb(from rebeccapurple w h b)`);
-    test_invalid_value(`color`, `hwb(from rebeccapurple b b b / b)`);
-    test_invalid_value(`color`, `hwb(from rebeccapurple h h h / h)`);
-    test_invalid_value(`color`, `hwb(from rebeccapurple alpha alpha alpha / alpha)`);
-    test_invalid_value(`color`, `hwb(from rgb(10%, 20%, 30%, 40%) w b h)`);
-    test_invalid_value(`color`, `hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)`);
-    test_invalid_value(`color`, `hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)`);
-    test_invalid_value(`color`, `hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)`);
-
     // Testing invalid values.
     test_invalid_value(`color`, `hwb(from rebeccapurple h 10% 10)`);
     test_invalid_value(`color`, `hwb(from rebeccapurple h 10 10%)`);
@@ -103,12 +83,6 @@
     }
 
     for (const colorSpace of [ "lch", "oklch" ]) {
-        // Testing invalid permutation (types don't match).
-        test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30) h l c / alpha)`);
-        test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30) alpha alpha alpha / alpha)`);
-        test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30 / 40%) h l c / alpha)`);
-        test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30 / 40%) alpha alpha alpha / alpha)`);
-
         // Testing invalid values.
         test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30) l 10deg h)`);
         test_invalid_value(`color`, `${colorSpace}(from ${colorSpace}(.70 45 30) l c 10%)`);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color-expected.txt
deleted file mode 100644
index 6dbd4fd..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color-expected.txt
+++ /dev/null
@@ -1,914 +0,0 @@
-This is a testharness.js-based test.
-Found 910 tests; 907 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS e.style['color'] = "rgb(from rebeccapurple r g b)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g b / 0)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 25 g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 25 b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g 25 / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g b / .25)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g b / 20%)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 25 g b / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 25 b / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g 25 / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple g b r)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple b alpha r / g)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r r r / r)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) g b r)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 20% 10)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 10 20%)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 0% 10 10)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r calc(g * 2) 10)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple b calc(r * .5) 10)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple none none none)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple none none none / none)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g none)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g none / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r g b / none)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g b / none)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(none none none) r g b)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(none none none / none) r g b / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20% none 60%) r g b)" should set the property value
-PASS e.style['color'] = "rgb(from rgb(20% 40% 60% / none) r g b / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s l)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0 0% 0% / 0)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0% / 0)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0 s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 0deg s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h 0% l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s 0% / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s l / 0)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 25 s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 25deg s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h 20% l / alpha)" should set the property value
-FAIL e.style['color'] = "hsl(from rebeccapurple h s 20% / alpha)" should set the property value assert_array_approx_equals: Numeric parameters are approximately equal. property 1, expected 25 +/- 0.0001, expected 25 but got 26
-PASS e.style['color'] = "hsl(from rebeccapurple h s l / .25)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)" should set the property value
-FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)" should set the property value assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 25 +/- 0.0001, expected 25 but got 26
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h l s)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h alpha l / s)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h l l / l)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l s)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha l / s)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l l / l)" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple calc(h) calc(s) calc(l))" should set the property value
-PASS e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple none none none)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple none none none / none)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s none)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s none / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h s l / none)" should set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple none s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / none)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(none none none) h s l)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(none none none / none) h s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg none 50% / .5) h s l)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)" should set the property value
-PASS e.style['color'] = "hsl(from hsl(none 20% 50% / .5) h s l / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w b)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0 0% 0% / 0)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0% / 0)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0 w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 0deg w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h 0% b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w 0% / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w b / 0)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 25 w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 25deg w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h 20% b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w 20% / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w b / .2)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h b w)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h alpha w / b)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w w / w)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h b w)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha w / b)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w w / w)" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple calc(h) calc(w) calc(b))" should set the property value
-PASS e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple none none none)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple none none none / none)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w none)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w none / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h w b / none)" should set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple none w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w b / none)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(none none none) h w b)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(none none none / none) h w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(120deg none 50% / .5) h w b)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)" should set the property value
-PASS e.style['color'] = "hwb(from hwb(none 20% 50% / .5) h w b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a b)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(200 300 400 / 500%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(-200 -300 -400 / -500%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(from lab(25 20 50) l a b) l a b)" should set the property value
-PASS e.style['color'] = "lab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) 0 0 0)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) 0 a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l 0 b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a 0 / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a b / 0)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) 0 a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l 0 b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a 0 / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a b / 0)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) 35 a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l 35 b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a 35 / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a b / .35)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) 35 a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l 35 b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a 35 / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a b / .35)" should set the property value
-PASS e.style['color'] = "lab(from lab(0.7 45 30 / 40%) 200 300 400 / 500)" should set the property value
-PASS e.style['color'] = "lab(from lab(0.7 45 30 / 40%) -200 -300 -400 / -500)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l b a)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a a / a)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l b a)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a a / a)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) calc(l) calc(a) calc(b))" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) none none none)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) none none none / none)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a none)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a none / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50) l a b / none)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a none / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / 40%) l a b / none)" should set the property value
-PASS e.style['color'] = "lab(from lab(none none none) l a b)" should set the property value
-PASS e.style['color'] = "lab(from lab(none none none / none) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 none 50) l a b)" should set the property value
-PASS e.style['color'] = "lab(from lab(25 20 50 / none) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a b)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(2 3 4 / 500%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(-2 -3 -4 / -500%) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(from oklab(0.25 0.2 0.5) l a b) l a b)" should set the property value
-PASS e.style['color'] = "oklab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) 0 0 0)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) 0 a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l 0 b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a 0 / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a b / 0)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) 0 a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l 0 b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a 0 / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a b / 0)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) 0.35 a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l 0.35 b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a 0.35 / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a b / .35)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) 0.35 a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l 0.35 b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a 0.35 / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a b / .35)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.7 0.45 0.3 / 40%) 2 3 4 / 500)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.7 0.45 0.3 / 40%) -2 -3 -4 / -500)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l b a)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a a / a)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l b a)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a a / a)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) calc(l) calc(a) calc(b))" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) none none none)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) none none none / none)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a none)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a none / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5) l a b / none)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a none / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / 40%) l a b / none)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(none none none) l a b)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(none none none / none) l a b / alpha)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 none 0.5) l a b)" should set the property value
-PASS e.style['color'] = "oklab(from oklab(0.25 0.2 0.5 / none) l a b / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c h)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(200 300 400 / 500%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(-200 -300 -400 / -500%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(from lch(0.7 45 30) l c h) l c h)" should set the property value
-PASS e.style['color'] = "lch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lab(0.7 45 30) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 0 0 0)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 0 0 0deg)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 0 0 0deg / 0)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 0 c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l 0 h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c 0 / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c 0deg / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c h / 0)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) 0 c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l 0 h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c 0 / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c 0deg / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c h / 0)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) 25 c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l 25 h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c 25 / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c 25deg / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c h / .25)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) 25 c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l 25 h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c 25 / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c 25deg / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c h / .25)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) 200 300 400 / 500)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) -200 -300 -400 / -500)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) 50 120 400deg / 500)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) 50 120 -400deg / -500)" should set the property value
-PASS e.style['color'] = "lch(from lch(.7 45 30) l c c / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(.7 45 30 / 40%) l c c / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) calc(l) calc(c) calc(h))" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) none none none)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) none none none / none)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c none)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c none / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30) l c h / none)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c none / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / 40%) l c h / none)" should set the property value
-PASS e.style['color'] = "lch(from lch(none none none) l c h)" should set the property value
-PASS e.style['color'] = "lch(from lch(none none none / none) l c h / alpha)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 none 30) l c h)" should set the property value
-PASS e.style['color'] = "lch(from lch(0.7 45 30 / none) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c h)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(2 3 400 / 500%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(-2 -3 -400 / -500%) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(from oklch(0.7 0.45 30) l c h) l c h)" should set the property value
-PASS e.style['color'] = "oklch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklab(0.7 45 30) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0 0 0)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0 0 0deg)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0 0 0deg / 0)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0 c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l 0 h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c 0 / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c 0deg / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c h / 0)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) 0 c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l 0 h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c 0 / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c 0deg / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c h / 0)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) 0.25 c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l 0.25 h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c 0.25 / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c 25deg / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c h / .25)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) 0.25 c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l 0.25 h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c 0.25 / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c 25deg / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c h / .25)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) 2 3 400 / 500)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) -2 -3 -400 / -500)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) 0.5 1.2 400deg / 500)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) 0.5 1.2 -400deg / -500)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(.7 0.45 30) l c c / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(.7 0.45 30 / 40%) l c c / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) calc(l) calc(c) calc(h))" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) none none none)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) none none none / none)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c none)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c none / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30) l c h / none)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c none / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / 40%) l c h / none)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(none none none) l c h)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(none none none / none) l c h / alpha)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 none 30) l c h)" should set the property value
-PASS e.style['color'] = "oklch(from oklch(0.7 0.45 30 / none) l c h / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(srgb 0.7 0.5 0.3) srgb r g b) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb none none none) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb none none none / none) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 none 0.3) srgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear g b r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear none none none) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)" should set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb none none none) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 g b r)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 none none none) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 none none none / none) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 none 0.3) rec2020 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb g b r)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb none none none) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)" should set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 0 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r 0 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b / 0)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 0.2 g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 20% g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r 0.2 b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r 20% b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g 20% / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 2 3 4)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 2 3 4 / 5)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 -2 -3 -4)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 -2 -3 -4 / -5)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 200% 300% 400%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 200% 300% 400% / 500%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 -200% -300% -400%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 -200% -300% -400% / -500%)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 g b r)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 g b r)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 b alpha r / g)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r r r / r)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 alpha alpha alpha / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 1.7 1.5 1.3) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 1.7 1.5 1.3) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 1.7 1.5 1.3 / 140%) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 1.7 1.5 1.3 / 140%) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 -0.7 -0.5 -0.3) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 -0.7 -0.5 -0.3) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 -0.7 -0.5 -0.3 / -40%) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 -0.7 -0.5 -0.3 / -40%) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 calc(r) calc(g) calc(b))" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 calc(r) calc(g) calc(b) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 none none none)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g none)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / 40%) display-p3 r g b / none)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 none none none) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 none none none / none) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 none 0.3) display-p3 r g b)" should set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3 / none) display-p3 r g b / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(xyz 7 -20.5 100) xyz x y z) xyz x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz none none none) xyz x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz none none none / none) xyz x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 none 100) xyz x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z) xyz-d50 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 none none none) xyz-d50 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 none 100) xyz-d50 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z) xyz-d65 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0 / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 20%)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0.2 y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0.2 z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0.2 / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0.2)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 y z x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 none none none) xyz-d65 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 none 100) xyz-d65 x y z)" should set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)" should set the property value
-PASS e.style['color'] = "rgb(from var(--bg-color) r g b / 80%)" should set the property value
-PASS e.style['color'] = "lch(from var(--color) calc(l / 2) c h)" should set the property value
-PASS e.style['color'] = "rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))" should set the property value
-PASS e.style['color'] = "lch(from var(--color) l 0 h)" should set the property value
-PASS e.style['color'] = "rgb(from indianred 255 g b)" should set the property value
-PASS e.style['color'] = "hsl(from var(--accent) calc(h + 180deg) s l)" should set the property value
-PASS e.style['color'] = "lab(from var(--mycolor) l a b / 100%)" should set the property value
-PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha * 0.8))" should set the property value
-PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha - 20%))" should set the property value
-PASS e.style['color'] = "lab(from var(--mycolor) l 0 0)" should set the property value
-FAIL e.style['color'] = "lch(from peru calc(l * 0.8) c h)" should set the property value assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 49.80138 +/- 0.0001, expected 49.80138 but got 49.7972
-PASS e.style['color'] = "LCH(from var(--accent) l c calc(h + 180deg))" should set the property value
-PASS e.style['color'] = "lch(from var(--mycolor) l 0 h)" should set the property value
-PASS e.style['color'] = "var(--mygray)" should set the property value
-PASS e.style['color'] = "lch(from var(--mygray) l 30 h)" should set the property value
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color.html
index f67264d0c..34c6dfb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-relative-color.html
@@ -145,16 +145,21 @@
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)`, `rgba(0, 0, 0, 0.8)`);
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)`, `rgba(51, 102, 153, 0)`);
 
-    // Testing replacement with a constant.
     fuzzy_test_valid_color(`hsl(from rebeccapurple 25 s l / alpha)`, `rgb(153, 94, 51)`);
     fuzzy_test_valid_color(`hsl(from rebeccapurple 25deg s l / alpha)`, `rgb(153, 94, 51)`);
     fuzzy_test_valid_color(`hsl(from rebeccapurple h 20% l / alpha)`, `rgb(102, 82, 122)`);
-    fuzzy_test_valid_color(`hsl(from rebeccapurple h s 20% / alpha)`, `rgb(51, 25, 77)`);
+    // hsl(from rebeccapurple h s 20% / alpha) is equivalent to color(srgb 0.2 0.1 0.3).
+    // For the green channel: 0.1 * 255 = 25.5. This should get rounded towards infinity to 26.
+    // https://www.w3.org/TR/css-color-4/#rgb-functions
+    fuzzy_test_valid_color(`hsl(from rebeccapurple h s 20% / alpha)`, `rgb(51, 26, 77)`);
     fuzzy_test_valid_color(`hsl(from rebeccapurple h s l / .25)`, `rgba(102, 51, 153, 0.25)`);
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)`, `rgba(153, 94, 51, 0.8)`);
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)`, `rgba(153, 94, 51, 0.8)`);
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)`, `rgba(82, 102, 122, 0.8)`);
-    fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)`, `rgba(25, 51, 77, 0.8)`);
+    // hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha) is equivalent to color(srgb 0.1 0.2 0.3).
+    // For the red channel: 0.1 * 255 = 25.5. This should get rounded towards infinity to 26.
+    // https://www.w3.org/TR/css-color-4/#rgb-functions
+    fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)`, `rgba(26, 51, 77, 0.8)`);
     fuzzy_test_valid_color(`hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)`, `rgba(51, 102, 153, 0.2)`);
 
     // Testing valid permutation (types match).
@@ -700,8 +705,8 @@
     // Example 17.
     fuzzy_test_valid_color(`lab(from var(--mycolor) l 0 0)`);
 
-    // Example 18.
-    fuzzy_test_valid_color(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80138 54.003296 63.680317)`);
+    // Example 18. This particular test does a lot of math so a wider epsilon is needed.
+    fuzzy_test_valid_color(`lch(from peru calc(l * 0.8) c h)`, `lch(49.80 54 63.68)`, 0.02 /* epsilon */);
 
     // Example 19.
     fuzzy_test_valid_color(`LCH(from var(--accent) l c calc(h + 180deg))`);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-page/page-name-fixed-pos-001-print.html.ini b/third_party/blink/web_tests/external/wpt/css/css-page/page-name-fixed-pos-001-print.html.ini
new file mode 100644
index 0000000..d73f303
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-page/page-name-fixed-pos-001-print.html.ini
@@ -0,0 +1,3 @@
+[page-name-fixed-pos-001-print.html]
+  expected:
+    if (product == "chrome") and not debug: [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length-expected.txt
new file mode 100644
index 0000000..02b6792
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+FAIL CSS.cap() produces cap length CSS[unit] is not a function
+PASS CSS.ch() produces ch length
+PASS CSS.em() produces em length
+PASS CSS.ex() produces ex length
+FAIL CSS.ic() produces ic length CSS[unit] is not a function
+FAIL CSS.lh() produces lh length CSS[unit] is not a function
+FAIL CSS.rcap() produces rcap length CSS[unit] is not a function
+FAIL CSS.rch() produces rch length CSS[unit] is not a function
+PASS CSS.rem() produces rem length
+FAIL CSS.rex() produces rex length CSS[unit] is not a function
+FAIL CSS.ric() produces ric length CSS[unit] is not a function
+FAIL CSS.rlh() produces rlh length CSS[unit] is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html
new file mode 100644
index 0000000..f7e41ee
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSSOM Test: Numeric Factory Functions for font relative length</title>
+    <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+    <link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#numeric-factory">
+    <meta name="assert" content="CSS factory functions produce expected CSSUnitValue">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+    <script>
+        "use strict";
+
+        let units = [
+            "cap",
+            "ch",
+            "em",
+            "ex",
+            "ic",
+            "lh",
+            "rcap",
+            "rch",
+            "rem",
+            "rex",
+            "ric",
+            "rlh"
+        ];
+        let counter = 1;
+        for (let unit of units) {
+            test(function(){
+                let length = CSS[unit](counter);
+                assert_true(length instanceof CSSUnitValue);
+                assert_equals(length.value, counter);
+                assert_equals(length.unit, unit);
+                counter++;
+            }, `CSS.${unit}() produces ${unit} length`);
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html.ini b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html.ini
new file mode 100644
index 0000000..5aeba07
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/factory-font-relative-length.html.ini
@@ -0,0 +1,40 @@
+[factory-font-relative-length.html]
+  [CSS.cap() produces cap length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.ic() produces ic length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.lh() produces lh length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.rcap() produces rcap length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.rch() produces rch length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.rex() produces rex length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.ric() produces ric length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
+
+  [CSS.rlh() produces rlh length]
+    expected:
+      if debug: PASS
+      [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
index 7f5d851b..3f0377fc0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 98 tests; 86 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 90 tests; 78 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS 'scale(cos(0))' as a specified value should serialize as 'scale(calc(1))'.
 PASS 'scale(calc(cos(0)))' as a specified value should serialize as 'scale(calc(1))'.
 PASS 'scale(sin(0))' as a specified value should serialize as 'scale(calc(0))'.
@@ -50,10 +50,6 @@
 PASS 'scale(calc(tan(0.78539816rad)))' as a specified value should serialize as 'scale(calc(1))'.
 PASS 'scale(tan(0.125turn))' as a specified value should serialize as 'scale(calc(1))'.
 PASS 'scale(calc(tan(0.125turn)))' as a specified value should serialize as 'scale(calc(1))'.
-PASS 'scale(tan(90deg))' as a specified value should serialize as 'scale(calc(infinity))'.
-PASS 'scale(calc(tan(90deg)))' as a specified value should serialize as 'scale(calc(infinity))'.
-PASS 'scale(tan(-90deg))' as a specified value should serialize as 'scale(calc(-infinity))'.
-PASS 'scale(calc(tan(-90deg)))' as a specified value should serialize as 'scale(calc(-infinity))'.
 FAIL 'scale(sin(180deg))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(sin(180deg))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(1.22465e-16))"
 FAIL 'scale(calc(sin(180deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(calc(sin(180deg)))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(1.22465e-16))"
 PASS 'scale(cos(180deg))' as a specified value should serialize as 'scale(calc(-1))'.
@@ -64,8 +60,6 @@
 PASS 'scale(calc(sin(270deg)))' as a specified value should serialize as 'scale(calc(-1))'.
 FAIL 'scale(cos(270deg))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(cos(270deg))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.83697e-16))"
 FAIL 'scale(calc(cos(270deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(calc(cos(270deg)))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.83697e-16))"
-PASS 'scale(tan(270deg))' as a specified value should serialize as 'scale(calc(-infinity))'.
-PASS 'scale(calc(tan(270deg)))' as a specified value should serialize as 'scale(calc(-infinity))'.
 FAIL 'scale(sin(-180deg))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(sin(-180deg))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.22465e-16))"
 FAIL 'scale(calc(sin(-180deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(calc(sin(-180deg)))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.22465e-16))"
 PASS 'scale(cos(-180deg))' as a specified value should serialize as 'scale(calc(-1))'.
@@ -76,8 +70,6 @@
 PASS 'scale(calc(sin(-270deg)))' as a specified value should serialize as 'scale(calc(1))'.
 FAIL 'scale(cos(-270deg))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(cos(-270deg))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.83697e-16))"
 FAIL 'scale(calc(cos(-270deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_equals: 'scale(calc(cos(-270deg)))' and 'scale(calc(0))' should serialize the same in specified values. expected "scale(calc(0))" but got "scale(calc(-1.83697e-16))"
-PASS 'scale(tan(-270deg))' as a specified value should serialize as 'scale(calc(infinity))'.
-PASS 'scale(calc(tan(-270deg)))' as a specified value should serialize as 'scale(calc(infinity))'.
 PASS 'scale(calc(sin(30deg) + cos(60deg) + tan(45deg)))' as a specified value should serialize as 'scale(calc(2))'.
 PASS 'scale(calc(calc(sin(30deg) + cos(60deg) + tan(45deg))))' as a specified value should serialize as 'scale(calc(2))'.
 PASS 'scale(calc(sin(infinity)))' as a specified value should serialize as 'scale(calc(NaN))'.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize.html
index c6a25e9..59d68242 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/sin-cos-tan-serialize.html
@@ -39,20 +39,16 @@
     "tan(0.78539816)"                                  :"calc(1)",
     "tan(0.78539816rad)"                               :"calc(1)",
     "tan(0.125turn)"                                   :"calc(1)",
-    "tan(90deg)"                                       :"calc(infinity)",
-    "tan(-90deg)"                                      :"calc(-infinity)",
     "sin(180deg)"                                      :"calc(0)",
     "cos(180deg)"                                      :"calc(-1)",
     "tan(180deg)"                                      :"calc(0)",
     "sin(270deg)"                                      :"calc(-1)",
     "cos(270deg)"                                      :"calc(0)",
-    "tan(270deg)"                                      :"calc(-infinity)",
     "sin(-180deg)"                                     :"calc(0)",
     "cos(-180deg)"                                     :"calc(-1)",
     "tan(-180deg)"                                     :"calc(0)",
     "sin(-270deg)"                                     :"calc(1)",
     "cos(-270deg)"                                     :"calc(0)",
-    "tan(-270deg)"                                     :"calc(infinity)",
     "calc(sin(30deg) + cos(60deg) + tan(45deg))"       :"calc(2)",
     "calc(sin(infinity))"                              :"calc(NaN)",
     "calc(cos(infinity))"                              :"calc(NaN)",
diff --git a/third_party/blink/web_tests/external/wpt/css/support/color-testcommon.js b/third_party/blink/web_tests/external/wpt/css/support/color-testcommon.js
index ab0c4ef..24cad1d 100644
--- a/third_party/blink/web_tests/external/wpt/css/support/color-testcommon.js
+++ b/third_party/blink/web_tests/external/wpt/css/support/color-testcommon.js
@@ -13,11 +13,11 @@
   }
 
   // The function
-  function fuzzy_compare_colors(color1, color2) {
+  function fuzzy_compare_colors(input, expected) {
     const colorElementDividers = /( |\(|,)/;
     // Return the string stripped of numbers.
     function getNonNumbers(color) {
-      return color.replace(/[0-9]/g, '');
+      return color.replace(/[0-9\.]/g, '');
     }
     // Return an array of all numbers in the color.
     function getNumbers(color) {
@@ -31,9 +31,13 @@
       return result;
     }
 
-    assert_array_approx_equals(getNumbers(color1), getNumbers(color2), epsilon, "Numeric parameters are approximately equal.");
-    // Assert that the text of the two colors are equal. i.e. colorSpace, colorFunction and format.
-    assert_equals(getNonNumbers(color1), getNonNumbers(color2), "Color format is correct.");
+    try {
+      assert_array_approx_equals(getNumbers(input), getNumbers(expected), epsilon, "Numeric parameters are approximately equal.");
+      // Assert that the text of the two colors are equal. i.e. colorSpace, colorFunction and format.
+      assert_equals(getNonNumbers(input), getNonNumbers(expected), "Color format is correct.");
+    } catch (error) {
+      throw `Colors do not match.\nActual:   ${input}\nExpected: ${expected}.\n${error}`
+    }
   }
 
   return fuzzy_compare_colors;
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html.ini b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html.ini
index ef3da60e..5f77484 100644
--- a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html.ini
+++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html.ini
@@ -1,2 +1,5 @@
 [scrollend-event-for-user-scroll.html]
   expected: ERROR
+  [Tests that the target_div gets scrollend event when sending DOWN key to the target.]
+    expected:
+      if (product == "chrome") and not debug: [TIMEOUT, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-scoring-signals.https.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-scoring-signals.https.sub.window.js.ini
index bd5b3d7..8aee48ab 100644
--- a/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-scoring-signals.https.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/trusted-scoring-signals.https.sub.window.js.ini
@@ -1,4 +1,16 @@
 [trusted-scoring-signals.https.sub.window.html]
+  [Component ads trusted scoring signals trusted scoring signals response is empty JSON object.]
+    expected:
+      if (product == "chrome") and not debug: [FAIL, PASS]
+
+  [Component ads trusted scoring signals, server closes the connection without sending anything.]
+    expected:
+      if (product == "chrome") and not debug: [FAIL, PASS]
+
+  [Component ads trusted scoring signals.]
+    expected:
+      if (product == "chrome") and not debug: [FAIL, PASS]
+
   [No trustedScoringSignalsURL.]
     expected:
       if product == "chrome": FAIL
@@ -15,6 +27,10 @@
     expected:
       if product == "chrome": FAIL
 
+  [Trusted scoring signals request without component ads in bid.]
+    expected:
+      if (product == "chrome") and not debug: [FAIL, PASS]
+
   [Trusted scoring signals response does not allow FLEDGE.]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
index 6b38ca4..bf36605f 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
@@ -1,14 +1,16 @@
 [sandbox-top-navigation-child-special-cases.tentative.sub.window.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == "disable-intersection-optimization"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == ""): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "win") and (port == "win11"): ERROR
     if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [TIMEOUT, OK, ERROR]
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): OK
     if product == "chrome": ERROR
     TIMEOUT
   [Allow top with user activation + user activation]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == "disable-intersection-optimization"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == ""): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative.html.ini
new file mode 100644
index 0000000..0d237c6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative.html.ini
@@ -0,0 +1,4 @@
+[selectlist-button-type-behavior.tentative.html]
+  [<button type=selectlist> should open the parent selectlist when clicked.]
+    expected:
+      if (product == "chrome") and not debug: [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-keyboard.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-keyboard.html.ini
new file mode 100644
index 0000000..76aaf43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-keyboard.html.ini
@@ -0,0 +1,6 @@
+[pointerevent_touch-action-keyboard.html]
+  expected:
+    if (product == "chrome") and not debug: [ERROR, OK]
+  [touch-action attribute test]
+    expected:
+      if (product == "chrome") and not debug: [NOTRUN, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
index aeee57d..8223808 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
@@ -10,34 +10,36 @@
   [content-type 10 : text/plain,*/*]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
-      if (product == "content_shell") and (os == "linux"): FAIL
-      if product == "chrome": FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac"): PASS
+      FAIL
 
   [content-type 11 : text/html,*/*]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): FAIL
-      if product == "chrome": FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac"): PASS
+      FAIL
 
   [content-type 12 : */*,text/html]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS]
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac"): FAIL
 
   [content-type 13 : text/plain,*/*;charset=gbk]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): FAIL
-      if product == "chrome": FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac"): PASS
+      FAIL
 
   [content-type 14 : text/html,*/*;charset=gbk]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): FAIL
-      if product == "chrome": FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac"): PASS
+      FAIL
 
   [content-type 15 : text/html;x=",text/plain]
     expected: FAIL
@@ -51,18 +53,14 @@
   [content-type 2 : text/html,text/plain]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac"): FAIL
 
   [content-type 3 : text/plain;charset=gbk,text/html]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac"): FAIL
 
   [content-type 4 : text/plain;charset=gbk,text/html;charset=windows-1254]
     expected: FAIL
@@ -81,10 +79,10 @@
 
   [content-type 9 : text/html;charset=gbk,text/plain,text/html]
     expected:
-      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL
       if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL]
-      if (product == "content_shell") and (os == "linux"): FAIL
-      if product == "chrome": FAIL
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac"): PASS
+      FAIL
 
   [mime-type 1 : text/html;charset=gbk]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/uievents/order-of-events/mouse-events/mouseover-out.html.ini b/third_party/blink/web_tests/external/wpt/uievents/order-of-events/mouse-events/mouseover-out.html.ini
index f5a4528..291f0523 100644
--- a/third_party/blink/web_tests/external/wpt/uievents/order-of-events/mouse-events/mouseover-out.html.ini
+++ b/third_party/blink/web_tests/external/wpt/uievents/order-of-events/mouse-events/mouseover-out.html.ini
@@ -1,9 +1,11 @@
 [mouseover-out.html]
   expected:
+    if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [OK, TIMEOUT]
     if (product == "content_shell") and (os == "mac") and (port == "mac13"): [OK, TIMEOUT]
   [Mouseover/out events]
     expected:
+      if (product == "content_shell") and (os == "win") and (port == "win11"): PASS
+      if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS]
       if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS
-      if (product == "content_shell") and (os == "win"): PASS
       if product == "chrome": PASS
       FAIL
diff --git a/third_party/blink/web_tests/fast/canvas/canvas-lost-gpu-context.html b/third_party/blink/web_tests/fast/canvas/canvas-lost-gpu-context.html
index 719d9e2..d3d26b0 100644
--- a/third_party/blink/web_tests/fast/canvas/canvas-lost-gpu-context.html
+++ b/third_party/blink/web_tests/fast/canvas/canvas-lost-gpu-context.html
@@ -7,24 +7,19 @@
 </head>
 <body>
 <script>
-var ctx;
 var lostEventHasFired = false;
 var contextLostTest;
 
-function contextLostWrapper() {
-    contextLost(lostEventHasFired, ctx);
-}
-
-function contextRestoredWrapper() {
-    contextRestored(lostEventHasFired, ctx);
-}
-
 async_test(function(t) {
     if (window.internals) {
-        var canvas = document.createElement('canvas');
-        canvas.addEventListener('contextlost', contextLostWrapper);
-        canvas.addEventListener('contextrestored', contextRestoredWrapper);
-        ctx = canvas.getContext('2d');
+        const canvas = document.createElement('canvas');
+        const ctx = canvas.getContext('2d');
+        canvas.addEventListener('contextlost', () => {
+            contextLost(lostEventHasFired, ctx);
+        });
+        canvas.addEventListener('contextrestored', () => {
+            contextRestored(lostEventHasFired, ctx);
+        });
         document.body.appendChild(ctx.canvas);
 
         ctx.fillRect(0, 0, 1, 1);
diff --git a/third_party/blink/web_tests/fast/canvas/canvas-oncontextlost.html b/third_party/blink/web_tests/fast/canvas/canvas-oncontextlost.html
index b87cc9c..dd55f83 100644
--- a/third_party/blink/web_tests/fast/canvas/canvas-oncontextlost.html
+++ b/third_party/blink/web_tests/fast/canvas/canvas-oncontextlost.html
@@ -8,24 +8,19 @@
 <body>
 <script>
 
-let ctx;
 let lostEventHasFired = false;
 
-function contextLostWrapper() {
-    contextLost(lostEventHasFired, ctx);
-}
-
-function contextRestoredWrapper() {
-    contextRestored(lostEventHasFired, ctx);
-}
-
 async_test(function(t) {
     var contextLostTest;
     if (window.internals) {
-        var canvas = document.createElement('canvas');
-        canvas.oncontextlost = contextLostWrapper;
-        canvas.oncontextrestored = contextRestoredWrapper;
-        ctx = canvas.getContext('2d');
+        const canvas = document.createElement('canvas');
+        const ctx = canvas.getContext('2d');
+        canvas.oncontextlost = () => {
+            contextLost(lostEventHasFired, ctx);
+        };
+        canvas.oncontextrestored = () => {
+            contextRestored(lostEventHasFired, ctx);
+        };
         document.body.appendChild(ctx.canvas);
 
         ctx.fillRect(0, 0, 1, 1);
diff --git a/third_party/blink/web_tests/fast/canvas/offscreencanvas-lost-gpu-context.html b/third_party/blink/web_tests/fast/canvas/offscreencanvas-lost-gpu-context.html
index e488bee..e35726f 100644
--- a/third_party/blink/web_tests/fast/canvas/offscreencanvas-lost-gpu-context.html
+++ b/third_party/blink/web_tests/fast/canvas/offscreencanvas-lost-gpu-context.html
@@ -7,16 +7,19 @@
 </head>
 <body>
 <script>
-var ctx;
 var lostEventHasFired = false;
 var contextLostTest;
 async_test(t => {
     if (window.internals) {
         try {
-            var canvas = new OffscreenCanvas(500, 500);
-            canvas.addEventListener('contextlost', contextLost);
-            canvas.addEventListener('contextrestored', contextRestored);
-            ctx = canvas.getContext('2d');
+            const canvas = new OffscreenCanvas(500, 500);
+            const ctx = canvas.getContext('2d');
+            canvas.addEventListener('contextlost', () => {
+                contextLost(lostEventHasFired, ctx);
+            });
+            canvas.addEventListener('contextrestored', () => {
+                contextRestored(lostEventHasFired, ctx);
+            });
 
             ctx.fillRect(0, 0, 1, 1);
             // setTimeout creates a frame barrier that locks the canvas into gpu
@@ -50,15 +53,6 @@
         t.done();
     }
 }, "Test the behavior of disconneced canvas recovery after a gpu context loss");
-
-function contextLost() {
-    contextLost(lostEventHasFired, ctx);
-}
-
-function contextRestored() {
-    contextRestored(lostEventHasFired, ctx);
-}
-
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/fast/canvas/offscreencanvas-oncontextlost.html b/third_party/blink/web_tests/fast/canvas/offscreencanvas-oncontextlost.html
index 98e2b7d3..938a9ff 100644
--- a/third_party/blink/web_tests/fast/canvas/offscreencanvas-oncontextlost.html
+++ b/third_party/blink/web_tests/fast/canvas/offscreencanvas-oncontextlost.html
@@ -7,15 +7,18 @@
 </head>
 <body>
 <script>
-var ctx;
 var lostEventHasFired = false;
 var contextLostTest;
 async_test(t => {
     if (window.internals) {
-        var canvas = new OffscreenCanvas(500, 500);
-        canvas.oncontextlost = contextLost;
-        canvas.oncontextrestored = contextRestored;
-        ctx = canvas.getContext('2d');
+        const canvas = new OffscreenCanvas(500, 500);
+        const ctx = canvas.getContext('2d');
+        canvas.oncontextlost = () => {
+            contextLost(lostEventHasFired, ctx);
+        };
+        canvas.oncontextrestored = () => {
+            contextRestored(lostEventHasFired, ctx);
+        };
 
         ctx.fillRect(0, 0, 1, 1);
         // setTimeout creates a frame barrier that locks the canvas into gpu
@@ -39,15 +42,6 @@
         t.done();
     }
 }, "Test the behavior of disconneced canvas recovery after a gpu context loss");
-
-function contextLost() {
-    contextLost(lostEventHasFired, ctx);
-}
-
-function contextRestored() {
-    contextRestored(lostEventHasFired, ctx);
-}
-
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/fast/canvas/resources/canvas-context-lost-events.js b/third_party/blink/web_tests/fast/canvas/resources/canvas-context-lost-events.js
index fe45d27..b67788e 100644
--- a/third_party/blink/web_tests/fast/canvas/resources/canvas-context-lost-events.js
+++ b/third_party/blink/web_tests/fast/canvas/resources/canvas-context-lost-events.js
@@ -24,7 +24,7 @@
     verifyContextLost(true, ctx);
 }
 
-function contextRestoredlostEventHasFired(lostEventHasFired, ctx) {
+function contextRestored(lostEventHasFired, ctx) {
     assert_true(lostEventHasFired, 'Context restored event dispatched after context lost.');
     verifyContextLost(false, ctx);
-}
\ No newline at end of file
+}
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async-expected.txt
deleted file mode 100644
index fa45bbb0..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async-expected.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Tests creating events with console.time and console.timeEnd
-Recording started
-Tracing complete
-Got ConsoleTime events:
-{
-    name : console-label1
-    ph : b
-}
-{
-    name : console-label2
-    ph : b
-}
-{
-    name : console-label1
-    ph : e
-}
-{
-    name : console-label2
-    ph : e
-}
-Event 0 (console-label1 b) ts is less than event 1 (console-label2 b): true
-Event 1 (console-label2 b) ts is less than event 2 (console-label1 e): true
-Event 2 (console-label1 e) ts is less than event 3 (console-label2 e): true
-
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async.js b/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async.js
deleted file mode 100644
index fd335091..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-async.js
+++ /dev/null
@@ -1,53 +0,0 @@
-(async function(testRunner) {
-  const {session, dp} =
-      await testRunner.startBlank('Tests creating events with console.time and console.timeEnd');
-
-  const TracingHelper =
-      await testRunner.loadScript('../resources/tracing-test.js');
-  const tracingHelper = new TracingHelper(testRunner, session);
-  const Phase = TracingHelper.Phase;
-  await dp.Page.enable();
-  await tracingHelper.startTracing(
-      'devtools.timeline,blink.console,blink.user_timing');
-
-  // Generate console events that should look like so:
-  // ================ console-label1
-  //     ==================== console-label2
-  await session.evaluateAsync(`
-      (async function () {
-        function delay(ms) {
-          return new Promise((r) => setTimeout(r, ms));
-        }
-        console.time("console-label1");
-        await delay(50);
-        console.time("console-label2");
-        await delay(50);
-        console.timeEnd("console-label1");
-        await delay(50);
-        console.timeEnd("console-label2");
-      })();
-  `)
-
-  const allEvents = await tracingHelper.stopTracing(
-      /devtools\.timeline|blink\.console|blink\.user_timing/);
-
-  const consoleTimeEvents =
-      allEvents.filter(event => event.name.startsWith('console-')).sort((a, b) => a.ts - b.ts)
-
-  testRunner.log('Got ConsoleTime events:');
-  for(event of consoleTimeEvents) {
-    testRunner.log({
-        name: event.name,
-        ph: event.ph,
-    });
-  }
-  for(let i = 0; i < consoleTimeEvents.length - 1; i++) {
-        const current = consoleTimeEvents[i];
-        const next = consoleTimeEvents[i+1];
-        testRunner.log(`Event ${i} (${current.name} ${current.ph}) ts is less than event ${i+1} (${next.name} ${next.ph}): ${current.ts < next.ts}`)
-        if(current.ts === next.ts) {
-            testRunner.log(`Events (${current.name} ${current.ph}) and (${next.name} ${next.ph}) have the same timestamp ${current.ts}`)
-        }
-    }
-  testRunner.completeTest();
-})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-expected.txt
deleted file mode 100644
index fa45bbb0..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing-expected.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Tests creating events with console.time and console.timeEnd
-Recording started
-Tracing complete
-Got ConsoleTime events:
-{
-    name : console-label1
-    ph : b
-}
-{
-    name : console-label2
-    ph : b
-}
-{
-    name : console-label1
-    ph : e
-}
-{
-    name : console-label2
-    ph : e
-}
-Event 0 (console-label1 b) ts is less than event 1 (console-label2 b): true
-Event 1 (console-label2 b) ts is less than event 2 (console-label1 e): true
-Event 2 (console-label1 e) ts is less than event 3 (console-label2 e): true
-
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing.js b/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing.js
deleted file mode 100644
index 587278f9..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/tracing/console-timing.js
+++ /dev/null
@@ -1,54 +0,0 @@
-(async function(testRunner) {
-  const {session, dp} =
-      await testRunner.startBlank('Tests creating events with console.time and console.timeEnd');
-
-  const TracingHelper =
-      await testRunner.loadScript('../resources/tracing-test.js');
-  const tracingHelper = new TracingHelper(testRunner, session);
-  const Phase = TracingHelper.Phase;
-  await dp.Page.enable();
-  await tracingHelper.startTracing(
-      'devtools.timeline,blink.console,blink.user_timing');
-
-  // Generate console events that should look like so:
-  // ================ console-label1
-  //     ==================== console-label2
-  await session.evaluateAsync(`
-      new Promise(resolve => {
-        console.time('console-label1');
-        window.setTimeout(function() {
-            console.time('console-label2');
-            window.setTimeout(function() {
-              console.timeEnd('console-label1');
-              window.setTimeout(function() {
-                console.timeEnd('console-label2');
-                  resolve()
-              }, 100);
-            }, 100);
-        }, 100);
-      });
-  `)
-
-  const allEvents = await tracingHelper.stopTracing(
-      /devtools\.timeline|blink\.console|blink\.user_timing/);
-
-  const consoleTimeEvents =
-      allEvents.filter(event => event.name.startsWith('console-')).sort((a, b) => a.ts - b.ts)
-
-  testRunner.log('Got ConsoleTime events:');
-  for(event of consoleTimeEvents) {
-    testRunner.log({
-        name: event.name,
-        ph: event.ph,
-    });
-  }
-  for(let i = 0; i < consoleTimeEvents.length - 1; i++) {
-        const current = consoleTimeEvents[i];
-        const next = consoleTimeEvents[i+1];
-        testRunner.log(`Event ${i} (${current.name} ${current.ph}) ts is less than event ${i+1} (${next.name} ${next.ph}): ${current.ts < next.ts}`)
-        if(current.ts === next.ts) {
-            testRunner.log(`Events (${current.name} ${current.ph}) and (${next.name} ${next.ph}) have the same timestamp ${current.ts}`)
-        }
-    }
-  testRunner.completeTest();
-})
diff --git a/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt b/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
index 1b1f07f..a3fd0e2 100644
--- a/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
+++ b/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/sin-cos-tan-serialize-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 98 tests; 0 PASS, 98 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 90 tests; 0 PASS, 90 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL 'scale(cos(0))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(cos(0))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(cos(0)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(cos(0)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(sin(0))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(sin(0))' should be valid in transform. got disallowed value ""
@@ -50,10 +50,6 @@
 FAIL 'scale(calc(tan(0.78539816rad)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(tan(0.78539816rad)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(tan(0.125turn))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(tan(0.125turn))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(tan(0.125turn)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(tan(0.125turn)))' should be valid in transform. got disallowed value ""
-FAIL 'scale(tan(90deg))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(tan(90deg))' should be valid in transform. got disallowed value ""
-FAIL 'scale(calc(tan(90deg)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(tan(90deg)))' should be valid in transform. got disallowed value ""
-FAIL 'scale(tan(-90deg))' as a specified value should serialize as 'scale(calc(-infinity))'. assert_not_equals: 'scale(tan(-90deg))' should be valid in transform. got disallowed value ""
-FAIL 'scale(calc(tan(-90deg)))' as a specified value should serialize as 'scale(calc(-infinity))'. assert_not_equals: 'scale(calc(tan(-90deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(sin(180deg))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(sin(180deg))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(sin(180deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(calc(sin(180deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(cos(180deg))' as a specified value should serialize as 'scale(calc(-1))'. assert_not_equals: 'scale(cos(180deg))' should be valid in transform. got disallowed value ""
@@ -64,8 +60,6 @@
 FAIL 'scale(calc(sin(270deg)))' as a specified value should serialize as 'scale(calc(-1))'. assert_not_equals: 'scale(calc(sin(270deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(cos(270deg))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(cos(270deg))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(cos(270deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(calc(cos(270deg)))' should be valid in transform. got disallowed value ""
-FAIL 'scale(tan(270deg))' as a specified value should serialize as 'scale(calc(-infinity))'. assert_not_equals: 'scale(tan(270deg))' should be valid in transform. got disallowed value ""
-FAIL 'scale(calc(tan(270deg)))' as a specified value should serialize as 'scale(calc(-infinity))'. assert_not_equals: 'scale(calc(tan(270deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(sin(-180deg))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(sin(-180deg))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(sin(-180deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(calc(sin(-180deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(cos(-180deg))' as a specified value should serialize as 'scale(calc(-1))'. assert_not_equals: 'scale(cos(-180deg))' should be valid in transform. got disallowed value ""
@@ -76,8 +70,6 @@
 FAIL 'scale(calc(sin(-270deg)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(sin(-270deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(cos(-270deg))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(cos(-270deg))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(cos(-270deg)))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(calc(cos(-270deg)))' should be valid in transform. got disallowed value ""
-FAIL 'scale(tan(-270deg))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(tan(-270deg))' should be valid in transform. got disallowed value ""
-FAIL 'scale(calc(tan(-270deg)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(tan(-270deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(sin(30deg) + cos(60deg) + tan(45deg)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sin(30deg) + cos(60deg) + tan(45deg)))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(calc(sin(30deg) + cos(60deg) + tan(45deg))))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(calc(sin(30deg) + cos(60deg) + tan(45deg))))' should be valid in transform. got disallowed value ""
 FAIL 'scale(calc(sin(infinity)))' as a specified value should serialize as 'scale(calc(NaN))'. assert_not_equals: 'scale(calc(sin(infinity)))' should be valid in transform. got disallowed value ""
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
index 8394d85..7bb2f02 100644
--- a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-computed-relative-color-expected.txt
@@ -895,20 +895,59 @@
 FAIL Property color value 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false
 FAIL Property color value 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' is a supported value for color. expected true got false
 FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false
-FAIL Property color value 'rgb(from var(--bg-color) r g b / 80%)' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
-FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 23.138971 +/- 0.0001, expected 23.138971 but got 0
-FAIL Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 76 +/- 0.0001, expected 76 but got 0
-FAIL Property color value 'lch(from var(--color) l 0 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 46.277943 +/- 0.0001, expected 46.277943 but got 0
+FAIL Property color value 'rgb(from var(--bg-color) r g b / 80%)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: rgba(0, 0, 255, 0.8).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
+FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(23.14 67.99 134.39).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 23.14 +/- 0.02, expected 23.14 but got 0
+FAIL Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: rgb(76, 76, 76).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 76 +/- 0.0001, expected 76 but got 0
+FAIL Property color value 'lch(from var(--color) l 0 h)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(46.28 0 134.39).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 46.28 +/- 0.02, expected 46.28 but got 0
 FAIL Property color value 'rgb(from indianred 255 g b)' assert_true: 'rgb(from indianred 255 g b)' is a supported value for color. expected true got false
-FAIL Property color value 'hsl(from var(--accent) calc(h + 180deg) s l)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 178 +/- 0.0001, expected 178 but got 0
-FAIL Property color value 'lab(from var(--mycolor) l a b / 100%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 0
-FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha * 0.8))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
-FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha - 20%))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
-FAIL Property color value 'lab(from var(--mycolor) l 0 0)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 0
+FAIL Property color value 'hsl(from var(--accent) calc(h + 180deg) s l)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: rgb(178, 32, 40).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 178 +/- 0.0001, expected 178 but got 0
+FAIL Property color value 'lab(from var(--mycolor) l a b / 100%)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lab(62.75 52.46 -34.12).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.75 +/- 0.02, expected 62.75 but got 0
+FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha * 0.8))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lab(62.75 52.46 -34.12 / 0.8).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
+FAIL Property color value 'lab(from var(--mycolor) l a b / calc(alpha - 20%))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lab(62.751923 52.45802 -34.117283 / 0.8).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 4 got 3
+FAIL Property color value 'lab(from var(--mycolor) l 0 0)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lab(62.75 0 0).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.75 +/- 0.02, expected 62.75 but got 0
 FAIL Property color value 'lch(from peru calc(l * 0.8) c h)' assert_true: 'lch(from peru calc(l * 0.8) c h)' is a supported value for color. expected true got false
-FAIL Property color value 'LCH(from var(--accent) l c calc(h + 180deg))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 65.49473 +/- 0.0001, expected 65.49473 but got 0
-FAIL Property color value 'lch(from var(--mycolor) l 0 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 0
-FAIL Property color value 'var(--mygray)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 0
-FAIL Property color value 'lch(from var(--mygray) l 30 h)' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.751923 +/- 0.0001, expected 62.751923 but got 0
+FAIL Property color value 'LCH(from var(--accent) l c calc(h + 180deg))' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(65.49473 39.446903 10.114471).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 65.49473 +/- 0.0001, expected 65.49473 but got 0
+FAIL Property color value 'lch(from var(--mycolor) l 0 h)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(62.75 0 326.96).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.75 +/- 0.02, expected 62.75 but got 0
+FAIL Property color value 'var(--mygray)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(62.75 0 326.96).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.75 +/- 0.02, expected 62.75 but got 0
+FAIL Property color value 'lch(from var(--mygray) l 30 h)' Colors do not match.
+Actual:   rgb(0, 0, 0)
+Expected: lch(62.75 30 326.96).
+Error: assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 62.75 +/- 0.02, expected 62.75 but got 0
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt
deleted file mode 100644
index 5d507e3c..0000000
--- a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-color/parsing/color-invalid-relative-color-expected.txt
+++ /dev/null
@@ -1,157 +0,0 @@
-This is a testharness.js-based test.
-PASS e.style['color'] = "rgb(from rebeccapurple r 10deg 10)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple r 10 10deg)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple 10deg g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) r 10deg 10)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) r 10 10deg)" should not set the property value
-PASS e.style['color'] = "rgb(from rgb(10%, 20%, 30%, 40%) 10deg g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple red g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple l g b)" should not set the property value
-PASS e.style['color'] = "rgb(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "rgba(from rebeccapurple r g b)" should not set the property value
-PASS e.style['color'] = "rgba(from rgb(10%, 20%, 30%, 40%) r g b / alpha)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple s h l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple s s s / s)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h h h / h)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) s h l)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) s s s / s)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h h h / h)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h 10% 10)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h 10 10%)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple 10% s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h 10% 10)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) h 10 10%)" should not set the property value
-PASS e.style['color'] = "hsl(from rgb(10%, 20%, 30%, 40%) 10% s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple hue s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple x s l)" should not set the property value
-PASS e.style['color'] = "hsl(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "hsla(from rebeccapurple h s l)" should not set the property value
-PASS e.style['color'] = "hsla(from rgb(10%, 20%, 30%, 40%) h s l / alpha)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple w h b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple b b b / b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h h h / h)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) w b h)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) b b b / b)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h h h / h)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h 10% 10)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h 10 10%)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple 10% w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h 10% 10)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) h 10 10%)" should not set the property value
-PASS e.style['color'] = "hwb(from rgb(10%, 20%, 30%, 40%) 10% w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple hue w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple x w b)" should not set the property value
-PASS e.style['color'] = "hwb(from rebeccapurple h g b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) 10deg a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50 / 40%) 10deg a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) lightness a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) x a b)" should not set the property value
-PASS e.style['color'] = "lab(from lab(.25 20 50) h g b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) 10deg a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) l 10deg 10)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) l 10 10deg)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50 / 40%) 10deg a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) lightness a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) x a b)" should not set the property value
-PASS e.style['color'] = "oklab(from oklab(.25 20 50) h g b)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) h l c / alpha)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) h l c / alpha)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) l 10deg h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) l c 10%)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) 10deg c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) l 10deg h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) l c 10%)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30 / 40%) 10deg c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) lightness c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) x c h)" should not set the property value
-PASS e.style['color'] = "lch(from lch(.70 45 30) l g b)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) h l c / alpha)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) h l c / alpha)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) alpha alpha alpha / alpha)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l 10deg h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l c 10%)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) 10deg c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) l 10deg h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) l c 10%)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30 / 40%) 10deg c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) lightness c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) x c h)" should not set the property value
-PASS e.style['color'] = "oklch(from oklch(.70 45 30) l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 10deg g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r 10deg b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 r g b / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 red g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 x g b)" should not set the property value
-PASS e.style['color'] = "color(from color(display-p3 0.7 0.5 0.3) display-p3 l g b)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz l y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 l y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 10deg y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 10deg z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 10deg)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 red y)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 r y z)" should not set the property value
-PASS e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 l y z)" should not set the property value
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https.html.ini b/third_party/blink/web_tests/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https.html.ini
new file mode 100644
index 0000000..84fdaf66
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https.html.ini
@@ -0,0 +1,3 @@
+[fedcm-3pc-blocked-with-iss-3p-ot.sub.https.html]
+  expected:
+    if (product == "chrome") and not debug: [ERROR, OK]
diff --git a/third_party/cros-components/src b/third_party/cros-components/src
index b6cc755..abc7235 160000
--- a/third_party/cros-components/src
+++ b/third_party/cros-components/src
@@ -1 +1 @@
-Subproject commit b6cc7558fa4230d674f8808304f2d174e034bd9f
+Subproject commit abc723520515cae61c172469d11b5c8b1cea1e2d
diff --git a/third_party/dawn b/third_party/dawn
index 7bb40bf..321c577d 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 7bb40bf80a1e94e24c29121214063d7baafdad8e
+Subproject commit 321c577d7732e0deae843267d84213477f03d1c2
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 6d52aa0..698aeff 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 6d52aa08d983d20ead0713e01e1fa77131302332
+Subproject commit 698aeffe4942c5018875c07800e939a3cac87c27
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index a49a95d..f5943cd8 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit a49a95dd95a964a380334ddfba99b395d645f51a
+Subproject commit f5943cd8a7ae161fbec5be57e76aa8fc37a69e76
diff --git a/third_party/ocmock/ocmock_extensions.h b/third_party/ocmock/ocmock_extensions.h
index 09bbc08..90ff1b6 100644
--- a/third_party/ocmock/ocmock_extensions.h
+++ b/third_party/ocmock/ocmock_extensions.h
@@ -50,4 +50,15 @@
 + (id)conformsToProtocol:(Protocol*)protocol;
 @end
 
+@interface OCMockObject (CrExtensions)
+// Recorded invocations can contain objects that clients expect to be
+// deallocated by now, and they can also have a strong reference to self,
+// creating a retain cycle. Get rid of all of the invocations to hopefully
+// let their objects deallocate, and to break any retain cycles involving self.
+// This is similar to `stopMocking`, but calling the latter will also cause the
+// mock object to no longer be usable, while sometimes it is desirable to
+// clear references while still keeping the mock object iself alive and usable.
+- (void)clearInvocations;
+@end
+
 #endif  // THIRD_PARTY_OCMOCK_OCMOCK_EXTENSIONS_H_
diff --git a/third_party/ocmock/ocmock_extensions.mm b/third_party/ocmock/ocmock_extensions.mm
index 8c953da..b124b8d 100644
--- a/third_party/ocmock/ocmock_extensions.mm
+++ b/third_party/ocmock/ocmock_extensions.mm
@@ -74,3 +74,13 @@
 }
 
 @end
+
+@implementation OCMockObject (CrExtensions)
+
+- (void)clearInvocations {
+  @synchronized(invocations) {
+    [invocations removeAllObjects];
+  }
+}
+
+@end
diff --git a/third_party/skia b/third_party/skia
index a2728a7..6f4fd97 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit a2728a7ad2a3471505475eedb485d46beb4b2e09
+Subproject commit 6f4fd97d2f7ef837b678787c2760854ebb838ee1
diff --git a/third_party/webrtc b/third_party/webrtc
index f43ca8d..675ef91 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit f43ca8da0bd572622360f284730c1742af5feabe
+Subproject commit 675ef918a89db571aac879c3df28805e0077f436
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index e7844f9c..4195ec56 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -23730,6 +23730,7 @@
 </action>
 
 <action name="NewIncognitoTabTipTargetSelected">
+  <obsolete>Deprecated 8/2023. Unused since a while ago.</obsolete>
   <owner>gambard@chromium.org</owner>
   <description>
     The user opened the tools menu while the 'New Incognito Tab' in-product help
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ae5f095..86c2cb6 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -110053,6 +110053,9 @@
   <int value="144" label="kWinMediaFoundationSourceCreationFailed"/>
   <int value="145" label="kWinDirectShowDeviceFilterCreationFailed"/>
   <int value="146" label="kWinDirectShowDeviceInitializationFailed"/>
+  <int value="147" label="kVideoCaptureDeviceFactorySecondCreateDenied"/>
+  <int value="148" label="kScreenCaptureKitResetStreamError"/>
+  <int value="149" label="kWinMediaFoundationCameraBusy"/>
 </enum>
 
 <enum name="VideoCaptureEvent">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index a1e6c62..f97feef 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -1151,7 +1151,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.AutoReauthn.BlockedByPreventSilentAccess"
-    enum="Boolean" expires_after="2023-10-08">
+    enum="Boolean" expires_after="2024-04-08">
   <owner>npm@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
index bb57e6e..967b9c5 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -632,6 +632,32 @@
   </summary>
 </histogram>
 
+<histogram name="CustomTabs.Startup.TimeToFirstCommitNavigation.{suffix}"
+    units="ms" expires_after="2024-08-25">
+  <owner>mthiesse@chromium.org</owner>
+  <owner>chrome-connective-tissue@google.com</owner>
+  <summary>
+    Time startup time for a Custom Tab from the earliest point in startup to the
+    first navigation commit. Split by varying degrees of warmness, from cold to
+    fully pre-loaded through mayLaunchUrl.
+
+    {suffix}.
+  </summary>
+  <token key="suffix">
+    <variant name="Cold"
+        summary="Measures from process creation to first commit"/>
+    <variant name="Speculated"
+        summary="Measures from intent received to first commit when the
+                 mayLaunchUrl speculation is used"/>
+    <variant name="Warm"
+        summary="Measures from intent received to first commit when
+                 CustomTabsConnection#warmUp is not used"/>
+    <variant name="WarmedUp"
+        summary="Measures from intent received to first commit when
+                 CustomTabsConnection#warmUp is used"/>
+  </token>
+</histogram>
+
 <histogram name="CustomTabs.TabCounts.OnClosingAllTabs" units="count"
     expires_after="2023-10-08">
   <owner>wenyufu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index e350fe5..cbc9a06 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -1327,7 +1327,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.{Origin}.FirstContentfulPaint" units="ms"
-    expires_after="2023-10-01">
+    expires_after="2024-02-29">
   <owner>chikamune@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
@@ -1341,7 +1341,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.{Origin}.InteractiveTiming.FirstInputDelay"
-    units="ms" expires_after="2023-10-01">
+    units="ms" expires_after="2024-02-29">
   <owner>chikamune@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
@@ -1355,7 +1355,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.{Origin}.LargestContentfulPaint" units="ms"
-    expires_after="2023-10-01">
+    expires_after="2024-02-29">
   <owner>chikamune@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
@@ -1370,7 +1370,7 @@
 
 <histogram
     name="PageLoad.Clients.{Origin}.LayoutInstability.CumulativeShiftScore"
-    units="ms" expires_after="2023-10-01">
+    units="ms" expires_after="2024-02-29">
   <owner>chikamune@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
@@ -1385,7 +1385,7 @@
 
 <histogram
     name="PageLoad.Clients.{Origin}.LayoutInstability.CumulativeShiftScore.MainFrame"
-    units="ms" expires_after="2023-10-01">
+    units="ms" expires_after="2024-02-29">
   <owner>chikamune@chromium.org</owner>
   <owner>loading-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml
index a1195bc..5f9e359 100644
--- a/tools/metrics/histograms/metadata/service/histograms.xml
+++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -104,6 +104,11 @@
   <variant name="SHOULD_FALLBACK"/>
 </variants>
 
+<variants name="ServiceWorkerFetchResponseFromName">
+  <variant name="ServiceWorker"/>
+  <variant name="WithoutServiceWorker"/>
+</variants>
+
 <variants name="ServiceWorkerResponseSource">
   <variant name="" summary=""/>
   <variant name=".CacheStorage" summary="The response came from CacheStorage."/>
@@ -625,6 +630,28 @@
 </histogram>
 
 <histogram
+    name="ServiceWorker.LoadTiming.MainFrame.MainResource.AutoPreloadResponseReceivedToFetchHandlerEnd.{ServiceWorkerFetchResponseFromName}"
+    units="ms" expires_after="2024-06-01">
+  <owner>sisidovski@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
+  <summary>
+    The time taken from (a) the response of the AutoPreload is received, to (b)
+    the fetch handler execution is completed.
+
+    Recorded for each navigation request (including redirects) where there is a
+    fetch event handler, the fetch event was successfully dispatched to the
+    service worker, and ServiceWorkerAutoPreload is enabled.
+
+    This is recorded even in the case when (b) is faster than (a). In this case
+    the value will be 0.
+
+    The response is from {ServiceWorkerFetchResponseFromName}
+  </summary>
+  <token key="ServiceWorkerFetchResponseFromName"
+      variants="ServiceWorkerFetchResponseFromName"/>
+</histogram>
+
+<histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FetchHandlerEndToFallbackNetwork{EmbeddedWorkerInitialStatus}"
     units="ms" expires_after="2024-06-01">
   <owner>yyanagisawa@chromium.org</owner>
@@ -908,6 +935,29 @@
 </histogram>
 
 <histogram
+    name="ServiceWorker.LoadTiming.Subresource.
+          AutoPreloadResponseReceivedToFetchHandlerEnd.{ServiceWorkerFetchResponseFromName}"
+    units="ms" expires_after="2024-06-01">
+  <owner>sisidovski@chromium.org</owner>
+  <owner>chrome-worker@google.com</owner>
+  <summary>
+    The time taken from (a) the response of the AutoPreload is received, to (b)
+    the fetch handler execution is completed.
+
+    Recorded for each subresource request where there is a fetch event handler,
+    the fetch event was successfully dispatched to the service worker, and
+    ServiceWorkerAutoPreload is enabled.
+
+    This is recorded even in the case when (b) is faster than (a). In this case
+    the value will be 0.
+
+    The response is from {ServiceWorkerFetchResponseFromName}
+  </summary>
+  <token key="ServiceWorkerFetchResponseFromName"
+      variants="ServiceWorkerFetchResponseFromName"/>
+</histogram>
+
+<histogram
     name="ServiceWorker.LoadTiming.Subresource.FetchHandlerEndToFallbackNetwork"
     units="ms" expires_after="2024-06-01">
   <owner>yyanagisawa@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index 639abe57..5ce8e9c5 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -295,17 +295,6 @@
   </summary>
 </histogram>
 
-<histogram name="Windows.UnpinShortcut.ProcessError" enum="BooleanError"
-    expires_after="2023-10-08">
-  <owner>davidbienvenu@chromium.org</owner>
-  <owner>grt@chromium.org</owner>
-  <summary>
-    Indicates whether a connection error occured between the browser and the
-    shell handler process. This is usually caused by a crash in the utility
-    process. This is logged every time shortcuts are unpinned from the taskbar.
-  </summary>
-</histogram>
-
 </histograms>
 
 </histogram-configuration>
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index c7c1496d..8f273246 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -1045,6 +1045,10 @@
   transfer_resource_ = resource;
   SetTextureSize(texture_size_in_dip);
 
+  // Incoming resource is assumed to have top-left origin which corresponds to
+  // TextureLayer::SetFlipped(false).
+  SetTextureFlipped(false);
+
   for (const auto& mirror : mirrors_) {
     // The release callbacks should be empty as only the source layer
     // should be able to release the texture resource.
diff --git a/ui/file_manager/integration_tests/file_manager/file_dialog.js b/ui/file_manager/integration_tests/file_manager/file_dialog.js
index 6d904f2..eb8cddc 100644
--- a/ui/file_manager/integration_tests/file_manager/file_dialog.js
+++ b/ui/file_manager/integration_tests/file_manager/file_dialog.js
@@ -211,7 +211,19 @@
   const fileEntry = `#file-list [file-name="${name}"]`;
   const closer = async (dialog) => {
     const element = await remoteCall.waitForElement(dialog, fileEntry);
-    chrome.test.assertTrue(element.attributes['class'].includes('dim'));
+    let dimmed = false;
+    for (const className of element.attributes['class'].split(' ')) {
+      if (className === 'dim-offline') {
+        // The 'dim-offline' class dims an element only if the connection
+        // status is 'OFFLINE', which is not something this test is verifying.
+        continue;
+      }
+      if (className.startsWith('dim')) {
+        dimmed = true;
+        break;
+      }
+    }
+    chrome.test.assertTrue(dimmed, 'The file entry should be dimmed');
     clickOpenFileDialogButton(name, cancelButton, dialog);
   };
 
diff --git a/ui/file_manager/integration_tests/test_util.js b/ui/file_manager/integration_tests/test_util.js
index 6fcc62c..085dffe5 100644
--- a/ui/file_manager/integration_tests/test_util.js
+++ b/ui/file_manager/integration_tests/test_util.js
@@ -757,7 +757,6 @@
     nameText: 'test-encrypted.txt',
     sizeText: '--',
     typeText: 'Plain text',
-    availableOffline: true,
   }),
 
   testDocument: new TestEntryInfo({
diff --git a/ui/ozone/platform/x11/x11_surface_factory.cc b/ui/ozone/platform/x11/x11_surface_factory.cc
index f883cca2..9f376176 100644
--- a/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -264,4 +264,17 @@
   return pixmap;
 }
 
+std::vector<gfx::BufferFormat>
+X11SurfaceFactory::GetSupportedFormatsForTexturing() const {
+  std::vector<gfx::BufferFormat> supported_buffer_formats;
+  for (int j = 0; j <= static_cast<int>(gfx::BufferFormat::LAST); ++j) {
+    const gfx::BufferFormat buffer_format = static_cast<gfx::BufferFormat>(j);
+    if (ui::GpuMemoryBufferSupportX11::GetInstance()
+            ->CanCreateNativePixmapForFormat(buffer_format)) {
+      supported_buffer_formats.push_back(buffer_format);
+    }
+  }
+  return supported_buffer_formats;
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_surface_factory.h b/ui/ozone/platform/x11/x11_surface_factory.h
index 3a44950..f0a8b534 100644
--- a/ui/ozone/platform/x11/x11_surface_factory.h
+++ b/ui/ozone/platform/x11/x11_surface_factory.h
@@ -56,6 +56,9 @@
       gfx::BufferFormat format,
       gfx::NativePixmapHandle handle) override;
 
+  std::vector<gfx::BufferFormat> GetSupportedFormatsForTexturing()
+      const override;
+
  private:
   std::unique_ptr<GLOzone> egl_implementation_;
 
diff --git a/v8 b/v8
index 93af443..389dcb03 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 93af4438d2bed525e6cb577274c208796d736b44
+Subproject commit 389dcb03ad1e7ee7f050248439e9ef296f859d3b