diff --git a/AUTHORS b/AUTHORS
index c7483e9..f7cce4e5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -188,6 +188,7 @@
 Ayush Khandelwal <k.ayush@samsung.com>
 Azhar Shaikh <azhar.shaikh@intel.com>
 Balazs Kelemen <b.kelemen@samsung.com>
+Baoyu Xu <xubaoyu@bytedance.com>
 Baul Eun <baul.eun@samsung.com>
 Behara Mani Shyam Patro <behara.ms@samsung.com>
 Bem Jones-Bey <bemajaniman@gmail.com>
diff --git a/DEPS b/DEPS
index 2af22dc5..0126e41 100644
--- a/DEPS
+++ b/DEPS
@@ -291,7 +291,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '2a2c52e2447fbdd311a095769463448ba2dc317d',
+  'src_internal_revision': '70b21a9e7529654dc682f591a19a27a5b999771a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
@@ -299,7 +299,7 @@
   # 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': '596261193b6c808f82e6bcd0150f39129793f1f3',
+  'v8_revision': 'eda6309abc2088b5d77b91470c3d971bdc5d962b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
@@ -343,7 +343,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '6c18a397cba160e659ae96c01a33871ad2b1704b',
+  'freetype_revision': '08805be530d6820d2bf8a1b7685826de40f06812',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
@@ -359,7 +359,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '4e4076a0d7a836b779a094989e911a65b2a3c1ee',
+  'catapult_revision': '0fd1415f0cf3219ba097d37336141897fab7c5e9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -407,7 +407,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': 'ae947216dca9cfc32bf61421849762c568682b8c',
+  'dawn_revision': '24eec2f88310a949c1de8e25f10ff410c38e537b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1193,7 +1193,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': '1JOR2RvG4uB1ILfTStX6COvCaLVxJhHk7QQH8tO8j7sC',
+              'version': 'H9AZhdhmfluw7cYEWgUfbiOJDqlMUAiSeyFRfNXMOxkC',
           },
       ],
       'condition': 'checkout_android',
@@ -1596,12 +1596,12 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'e2d261757af9a7a32cecbc192644aad81a29f51f',
+    'dc223ca45f40208adbfa36bb82127259ef6775bd',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'c5d4064bbf9dc71893bfa60db578e8f92995bd57',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'a89f6810f6a5b0e11e4ec00387e9f97e8f6c23ae',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -2478,7 +2478,7 @@
     Var('chromium_git') + '/webm/libwebp.git' + '@' +  '4fa21912338357f89e4fd51cf2368325b59e9bd9',
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '3ff31b2a5fd88d57fed619678da1708097c81504',
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'cdd3bae84818e78466fec1ce954eead8f403d10c',
 
   'src/third_party/lighttpd': {
       'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@@ -2618,7 +2618,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '4c0ba925d3304ab862e4e866d9b1ad6b451cc82f',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'd248102abcfb167da566d0ca45d2fa32652aa31c',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2789,7 +2789,7 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '66a656e6d9f8b78806c76201eb03038e85103e28',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '8451125897dd7816a5c118925e8e42309d598ecc',
 
   'src/third_party/r8/cipd': {
       'packages': [
@@ -2937,16 +2937,16 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@4c0ad3b279656534b70f5e1983bbf1fc50db5456',
-  'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@f43df42fe69bb38d43625b53e0706bbee43d74b4',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5755777e263c93928218fef6d1a0c3f6750efbf3',
+  'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@38f6708b6b6f213010c51ffa8f577a7751e12ce7',
   'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3',
-  'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@de1807b7cfa8e722979d5ab7b7445b258dbc1836',
-  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@ed173ab1848b82e19690e10ce8f2818c0ac78f8d',
-  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@89268a6d17fc87003b209a1422c17ab288be99a0',
-  'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@a1684e4bd23ab130c5e7c37ab72b07dd541897a9',
+  'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@97e96f9e9defeb4bba3cfbd034dec516671dd7a3',
+  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@3aeaaa088d37b86cff036eee1a9bf452abad7d9d',
+  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@37057b4756df4009ad85803bd2e06ec8a3bb1bca',
+  'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@f2389e27734347c1d9f40e03be53f69f969976b1',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@f766b30b2de3ffe2cf6b656d943720882617ec58',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@b0a40d2e50310e9f84327061290a390a061125a3',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@72c2c64b82c3fbd587f478c810363479cd011b6d',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@f113d73531fb6b82f6cb3aebc0e7c0915b3f611e',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50',
@@ -2989,7 +2989,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '22735d7b9726d04e6fb4ae7af92c0e5f0bc03380',
+    Var('webrtc_git') + '/src.git' + '@' + 'cdc641f20d7a1bffdbcdd59fa88706c5404f2c64',
 
   # 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.
@@ -3122,7 +3122,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'wtfqmVosUmQ9h1n7Omk1svGZt0ThuwPRGkxLCpwQABcC',
+        'version': 'Oa3_VTSyZHk0QvIsqyq_dNX5PPSgg3117tZl-ERitJcC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3133,7 +3133,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'QGlODNawFhhuEyC9rfuP4JKtZKVkKwLd0r3t9nfaaDsC',
+        'version': '5B7brZKhApiPiTdGixgXimFVcswhW-GvbKKjSOfJ4okC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3692,7 +3692,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        '76c30fcad7ac08d84c88ddc4df6a7b5f607822f8',
+        '265386bd2ef17a972139f26b14b0017887a043dd',
       'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 99c4701..f2288e8d 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2373,8 +2373,8 @@
         for s in ('3su6n15k.default', )) | set(
             '%s@chops-service-accounts.iam.gserviceaccount.com' % s
             for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
-                      'wpt-autoroller', 'chrome-weblayer-builder',
-                      'skylab-test-cros-roller', 'infra-try-recipes-tester',
+                      'wpt-autoroller', 'skylab-test-cros-roller',
+                      'infra-try-recipes-tester',
                       'chrome-automated-expectation',
                       'chromium-automated-expectation', 'chrome-branch-day',
                       'chrome-cherry-picker', 'chromium-autosharder')
@@ -4466,10 +4466,6 @@
         'third_party/win_build_output/*',
         # Enum-only mojoms used for web metrics, so no security review needed.
         'third_party/blink/public/mojom/use_counter/metrics/*',
-        # These files are just used to communicate between class loaders running
-        # in the same process.
-        'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
-        'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
     ]
 
     def IsMojoServiceManifestFile(input_api, file):
@@ -4996,8 +4992,7 @@
 
 def _CheckAndroidWebkitImports(input_api, output_api):
     """Checks that code uses org.chromium.base.Callback instead of
-       android.webview.ValueCallback except in the WebView glue layer
-       and WebLayer.
+       android.webview.ValueCallback except in the WebView glue layer.
     """
     valuecallback_import_pattern = input_api.re.compile(
         r'^import android\.webkit\.ValueCallback;$')
@@ -5010,7 +5005,6 @@
                        DEFAULT_FILES_TO_SKIP + (
                            r'^android_webview/glue/.*',
                            r'^android_webview/support_library/.*',
-                           r'^weblayer/.*',
                        )),
         files_to_check=[r'.*\.java$'])
 
diff --git a/agents/extensions/install.py b/agents/extensions/install.py
index ff57ce3..56dafeb0 100755
--- a/agents/extensions/install.py
+++ b/agents/extensions/install.py
@@ -234,8 +234,11 @@
 
     parser = argparse.ArgumentParser(
         description='Install and manage MCP server configurations.')
-    subparsers = parser.add_subparsers(dest='command',
-                                       help='Available commands.')
+    subparsers = parser.add_subparsers(
+        dest='command',
+        help='Available commands.',
+        description='Install and manage MCP server configurations.'
+        ' To get help for a specific command, run "install.py <command> -h".')
 
     # Add command
     add_parser = subparsers.add_parser('add', help='Add new MCP servers.')
@@ -308,4 +311,4 @@
 
 
 if __name__ == '__main__':
-    main()
\ No newline at end of file
+    main()
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc
index 1a1c64a..10d1850 100644
--- a/android_webview/common/crash_reporter/crash_keys.cc
+++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -167,6 +167,7 @@
 
     // sandbox/linux
     "seccomp-sigsys",
+    "seccomp-sigsys-ioctl",
 
     // Used to report switches/feature flags overridden in the DevUI
     "commandline-enabled-feature-*",
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 1126488fb..6d343bb 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -3090,6 +3090,9 @@
       <message name="IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_BSM_ON_ACCESSIBLE" desc="The message used by accessibility to show battery is being charged with battery saver enabled.">
         Battery at <ph name="percentage">$1<ex>56</ex></ph>% and charging. Battery Saver is on.
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ON_HOLD_ACCESSIBLE" desc="The message used by accessibility to show the battery percentage and that charging is currently paused." translateable="false">
+        Battery at <ph name="percentage">$1<ex>56</ex></ph>%. Charging on hold.
+      </message>
       <message name="IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING_ACCESSIBLE" desc="The message used by accessibility to show battery is calculating its time in short message.">
         Calculating battery time.
       </message>
diff --git a/ash/display/cursor_window_controller_unittest.cc b/ash/display/cursor_window_controller_unittest.cc
index 6b6c8e2..81deaed 100644
--- a/ash/display/cursor_window_controller_unittest.cc
+++ b/ash/display/cursor_window_controller_unittest.cc
@@ -460,7 +460,7 @@
       {SK_ColorBLUE, SK_ColorGREEN, SkColorSetRGB(172, 0, 0),
        CursorType::kNoDrop},
       // Similarly, the copy cursor has green in it.
-      {SK_ColorBLUE, SK_ColorRED, SkColorSetRGB(25, 140, 22),
+      {SK_ColorBLUE, SK_ColorRED, SkColorSetRGB(57, 149, 88),
        CursorType::kCopy},
   };
 
diff --git a/ash/system/power/power_status.cc b/ash/system/power/power_status.cc
index c407806..244a41a 100644
--- a/ash/system/power/power_status.cc
+++ b/ash/system/power/power_status.cc
@@ -391,30 +391,32 @@
   }
 
   int percentage_accessibility_token = -1;
-  if (features::IsBatterySaverAvailable()) {
-    if (IsBatteryCharging()) {
-      percentage_accessibility_token =
-          IsBatterySaverActive()
-              ? IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_BSM_ON_ACCESSIBLE
-              : IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE;
-    } else {
-      percentage_accessibility_token =
-          IsBatterySaverActive()
-              ? IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_BSM_ON_ACCESSIBLE
-              : IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ACCESSIBLE;
-    }
-  } else {  // Backwards compatibility with battery saver feature flag disabled.
+  if (ash::features::IsBatteryChargeLimitAvailable() &&
+      IsBatteryChargeLimited()) {
     percentage_accessibility_token =
-        IsBatteryCharging()
-            ? IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE
+        IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ON_HOLD_ACCESSIBLE;
+  } else if (IsBatteryCharging()) {
+    percentage_accessibility_token =
+        IsBatterySaverActive()
+            ? IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_BSM_ON_ACCESSIBLE
+            : IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ACCESSIBLE;
+  } else {
+    percentage_accessibility_token =
+        IsBatterySaverActive()
+            ? IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_BSM_ON_ACCESSIBLE
             : IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ACCESSIBLE;
   }
 
   std::u16string battery_percentage_accessible = l10n_util::GetStringFUTF16(
       percentage_accessibility_token,
       base::NumberToString16(GetRoundedBatteryPercent()));
-  if (!full_description)
+  // When Charge limit is enabled, the full description is simply the battery
+  // percentage and that charging is on hold. We don't show calculating,
+  // unreliable, or time to empty/full.
+  if (!full_description || (ash::features::IsBatteryChargeLimitAvailable() &&
+                            IsBatteryChargeLimited())) {
     return battery_percentage_accessible;
+  }
 
   std::u16string battery_time_accessible = std::u16string();
   const std::optional<base::TimeDelta> time =
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc
index f4fcbb2..00e3bf52 100644
--- a/ash/system/unified/unified_system_tray_unittest.cc
+++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -1406,6 +1406,46 @@
   }
 }
 
+// This tests the logic in `PowerStatus::GetAccessibleNameString` where
+// `features::IsBatteryChargeLimitAvailable()` and `IsBatteryChargeLimited()`
+// are both true.
+TEST_F(UnifiedSystemTrayAccessibilityTest, NameWithBatteryChargeLimitEnabled) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(ash::features::kBatteryChargeLimit);
+
+  std::vector<std::u16string> status;
+  CreateDefaultStatusForTesting(&status);
+
+  power_manager::PowerSupplyProperties prop;
+  prop.set_battery_state(
+      power_manager::PowerSupplyProperties_BatteryState_FULL);
+  prop.set_charge_limited(true);
+
+  FakePowerStatus* fake_power_status = GetFakePowerStatus();
+  fake_power_status->SetProtoForTesting(prop);
+  fake_power_status->SetBatteryPercent(80.0);
+
+  // `OnPowerStatusChanged` is called in an asynchronous method, but for the
+  // purpose of this test, it is called explicitly.
+  GetPrimaryUnifiedSystemTray()->OnPowerStatusChanged();
+
+  // The new logic should return just the percentage accessible string, not a
+  // full description with time, etc.
+  UpdatePartOfStatus(
+      &status,
+      FormatPowerPercentageString(
+          IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_CHARGING_ON_HOLD_ACCESSIBLE,
+          fake_power_status),
+      StatusType::kBattery);
+
+  ui::AXNodeData data;
+  GetPrimaryUnifiedSystemTray()->GetViewAccessibility().GetAccessibleNodeData(
+      &data);
+  EXPECT_EQ(data.GetString16Attribute(ax::mojom::StringAttribute::kName),
+            l10n_util::GetStringFUTF16(
+                IDS_ASH_STATUS_TRAY_ACCESSIBLE_DESCRIPTION, status, nullptr));
+}
+
 TEST_F(UnifiedSystemTrayAccessibilityTest, ChannelIndicatorUpdatesName) {
   ASSERT_TRUE(GetPrimaryUnifiedSystemTray()->ShouldChannelIndicatorBeShown());
   ASSERT_TRUE(channel_indicator_view());
diff --git a/ash/wm/base_state.cc b/ash/wm/base_state.cc
index 9ca0778..d5a1353 100644
--- a/ash/wm/base_state.cc
+++ b/ash/wm/base_state.cc
@@ -35,8 +35,9 @@
 void BaseState::OnWMEvent(WindowState* window_state, const WMEvent* event) {
   if (event->IsWorkspaceEvent()) {
     HandleWorkspaceEvents(window_state, event);
-    if (window_state->IsSnapped() && !window_state->CanSnap())
+    if (window_state->IsSnapped() && !window_state->CanSnap()) {
       window_state->Restore();
+    }
     return;
   }
   if ((window_state->IsTrustedPinned() || window_state->IsPinned()) &&
@@ -146,11 +147,20 @@
                                    : IDS_WM_SNAP_WINDOW_TO_RIGHT_ON_SHORTCUT);
     return;
   }
-  // If |window| is already in |desired_snap_state|, then unsnap |window|.
+  // If |window| is in a snap group, ungroup it. If it's not in a snap group and
+  // it's already snapped, restore it.
   if (window_state->IsSnapped()) {
-    window_state->Restore();
-    window_state->ReadOutWindowCycleSnapAction(
-        IDS_WM_RESTORE_SNAPPED_WINDOW_ON_SHORTCUT);
+    auto* snap_group_controller = Shell::Get()->snap_group_controller();
+    auto* snap_group = snap_group_controller->GetSnapGroupForGivenWindow(
+        window_state->window());
+    if (snap_group) {
+      snap_group_controller->RemoveSnapGroup(
+          snap_group, SnapGroupExitPoint::kToggleSnapGroupAccelerator);
+    } else {
+      window_state->Restore();
+      window_state->ReadOutWindowCycleSnapAction(
+          IDS_WM_RESTORE_SNAPPED_WINDOW_ON_SHORTCUT);
+    }
     return;
   }
   // If |window| cannot be snapped, then do a window bounce animation.
diff --git a/ash/wm/snap_group/snap_group_unittest.cc b/ash/wm/snap_group/snap_group_unittest.cc
index f7d4051..cd291652 100644
--- a/ash/wm/snap_group/snap_group_unittest.cc
+++ b/ash/wm/snap_group/snap_group_unittest.cc
@@ -573,19 +573,70 @@
 }
 
 TEST_F(FasterSplitScreenTest, CycleSnap) {
+  auto* snap_group_controller = SnapGroupController::Get();
   std::unique_ptr<aura::Window> w1(CreateAppWindow());
   auto* window_state = WindowState::Get(w1.get());
 
-  // Cycle snap to the left.
-  const WindowSnapWMEvent cycle_snap_primary(WM_EVENT_CYCLE_SNAP_PRIMARY);
-  window_state->OnWMEvent(&cycle_snap_primary);
-  auto* overview_controller = Shell::Get()->overview_controller();
-  EXPECT_FALSE(overview_controller->InOverviewSession());
+  for (auto event_type :
+       {WM_EVENT_CYCLE_SNAP_PRIMARY, WM_EVENT_CYCLE_SNAP_SECONDARY}) {
+    auto state_type = event_type == WM_EVENT_CYCLE_SNAP_PRIMARY
+                          ? chromeos::WindowStateType::kPrimarySnapped
+                          : chromeos::WindowStateType::kSecondarySnapped;
+    // Cycle snap to the left.
+    const WindowSnapWMEvent cycle_snap(event_type);
+    window_state->OnWMEvent(&cycle_snap);
+    auto* overview_controller = Shell::Get()->overview_controller();
+    EXPECT_FALSE(overview_controller->InOverviewSession());
+    EXPECT_EQ(window_state->GetStateType(), state_type);
+    EXPECT_FALSE(snap_group_controller->GetSnapGroupForGivenWindow(w1.get()));
 
-  // Cycle snap to the right.
-  const WindowSnapWMEvent cycle_snap_secondary(WM_EVENT_CYCLE_SNAP_SECONDARY);
-  window_state->OnWMEvent(&cycle_snap_secondary);
-  EXPECT_FALSE(overview_controller->InOverviewSession());
+    // Next cycle will restore the window.
+    window_state->OnWMEvent(&cycle_snap);
+    EXPECT_FALSE(overview_controller->InOverviewSession());
+    EXPECT_TRUE(window_state->IsNormalStateType());
+    EXPECT_FALSE(snap_group_controller->GetSnapGroupForGivenWindow(w1.get()));
+  }
+
+  std::unique_ptr<aura::Window> w2(CreateAppWindow());
+  auto* window_state2 = WindowState::Get(w2.get());
+
+  // Snapgroup test.
+  for (auto event_type :
+       {WM_EVENT_CYCLE_SNAP_PRIMARY, WM_EVENT_CYCLE_SNAP_SECONDARY}) {
+    {
+      const WindowSnapWMEvent snap(event_type == WM_EVENT_CYCLE_SNAP_PRIMARY
+                                       ? WM_EVENT_SNAP_SECONDARY
+                                       : WM_EVENT_SNAP_PRIMARY);
+      window_state2->OnWMEvent(&snap);
+      EXPECT_EQ(window_state2->GetStateType(),
+                event_type == WM_EVENT_CYCLE_SNAP_PRIMARY
+                    ? chromeos::WindowStateType::kSecondarySnapped
+                    : chromeos::WindowStateType::kPrimarySnapped);
+    }
+
+    auto state_type = event_type == WM_EVENT_CYCLE_SNAP_PRIMARY
+                          ? chromeos::WindowStateType::kPrimarySnapped
+                          : chromeos::WindowStateType::kSecondarySnapped;
+    // Cycle snap to the left.
+    const WindowSnapWMEvent cycle_snap(event_type);
+    window_state->OnWMEvent(&cycle_snap);
+    auto* overview_controller = Shell::Get()->overview_controller();
+    EXPECT_FALSE(overview_controller->InOverviewSession());
+    EXPECT_EQ(window_state->GetStateType(), state_type);
+    EXPECT_TRUE(snap_group_controller->GetSnapGroupForGivenWindow(w1.get()));
+
+    // Next cycle will remove snap group.
+    window_state->OnWMEvent(&cycle_snap);
+    EXPECT_FALSE(overview_controller->InOverviewSession());
+    EXPECT_EQ(window_state->GetStateType(), state_type);
+    EXPECT_FALSE(snap_group_controller->GetSnapGroupForGivenWindow(w1.get()));
+
+    // Next cycle will restore the window.
+    window_state->OnWMEvent(&cycle_snap);
+    EXPECT_FALSE(overview_controller->InOverviewSession());
+    EXPECT_TRUE(window_state->IsNormalStateType());
+    EXPECT_FALSE(snap_group_controller->GetSnapGroupForGivenWindow(w1.get()));
+  }
 }
 
 TEST_F(FasterSplitScreenTest, EndSplitViewOverviewSession) {
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h
index f37494f..96fa6891 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific.h
@@ -480,4 +480,32 @@
 #define PA_NOPROFILE
 #endif
 
+// Annotates a function or class data member indicating it can lead to
+// out-of-bounds accesses (OOB) if given incorrect inputs.
+#if PA_HAS_CPP_ATTRIBUTE(clang::unsafe_buffer_usage)
+#define PA_UNSAFE_BUFFER_USAGE [[clang::unsafe_buffer_usage]]
+#else
+#define PA_UNSAFE_BUFFER_USAGE
+#endif
+
+// Annotates code indicating that it should be permanently exempted from
+// `-Wunsafe-buffer-usage`. For temporary cases such as migrating callers to
+// safer patterns, use `UNSAFE_TODO()` instead;
+#if defined(__clang__)
+// Disabling `clang-format` allows each `_Pragma` to be on its own line, as
+// recommended by https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html.
+// clang-format off
+#define PA_UNSAFE_BUFFERS(...)                  \
+  _Pragma("clang unsafe_buffer_usage begin") \
+  __VA_ARGS__                                \
+  _Pragma("clang unsafe_buffer_usage end")
+// clang-format on
+#else
+#define PA_UNSAFE_BUFFERS(...) __VA_ARGS__
+#endif
+
+// Annotates code indicating that it should be temporarily exempted from
+// `-Wunsafe-buffer-usage`.
+#define PA_UNSAFE_TODO(...) PA_UNSAFE_BUFFERS(__VA_ARGS__)
+
 #endif  // PARTITION_ALLOC_PARTITION_ALLOC_BASE_COMPILER_SPECIFIC_H_
diff --git a/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java b/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
index a8a1f7a..a6390cf 100644
--- a/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
+++ b/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
@@ -10,6 +10,7 @@
 import android.graphics.RectF;
 import android.hardware.display.DisplayManager;
 import android.util.SparseArray;
+import android.view.Window;
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
@@ -83,4 +84,16 @@
             DisplayManager displayManager,
             Executor executor,
             DisplayTopologyListener displayTopologyListener) {}
+
+    /**
+     * Calls the {@link android.view.WindowManager.LayoutParams#setKeyboardCaptureEnabled(boolean
+     * hasCapture)} method if supported.
+     *
+     * @param window {@link android.view.Window} on which the method should be called.
+     * @param hasCapture whether keyboard capture should be enabled or disabled.
+     * @return boolean indicating whether the android API was invoked.
+     */
+    default boolean setKeyboardCaptureEnabled(Window window, boolean hasCapture) {
+        return false;
+    }
 }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java
index 659b9bd..47a7bf1 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java
@@ -4,6 +4,8 @@
 
 package org.chromium.base.test.transit;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.util.Pair;
 
 import androidx.annotation.IntDef;
@@ -231,8 +233,8 @@
      */
     @EnsuresNonNull({"mWaits", "mConditionsGuardingFactories"})
     void preCheck(boolean failOnAlreadyFulfilled) {
-        mWaits = createWaits();
-        mConditionsGuardingFactories = createFactories();
+        createWaits();
+        createFactories();
 
         if (mWaits.isEmpty()) {
             if (failOnAlreadyFulfilled) {
@@ -313,7 +315,8 @@
         }
     }
 
-    private List<ConditionWait> createWaits() {
+    @EnsuresNonNull("mWaits")
+    private void createWaits() {
         List<ConditionWait> allWaits = new ArrayList<>();
 
         Set<String> destinationElementIds = new HashSet<>();
@@ -354,22 +357,37 @@
             allWaits.add(new ConditionWait(condition, ConditionWaiter.ConditionOrigin.TRANSITION));
         }
 
-        return allWaits;
+        mWaits = allWaits;
     }
 
-    private Map<Condition, ElementFactory> createFactories() {
+    @EnsuresNonNull("mConditionsGuardingFactories")
+    private void createFactories() {
         Map<Condition, ElementFactory> allConditionsGuardingFactories = new HashMap<>();
 
         for (ConditionalState conditionalState : mTransition.getEnteredStates()) {
             final Elements destinationElements = conditionalState.getElements();
             for (Map.Entry<Element<?>, ElementFactory> entry :
                     destinationElements.getElementFactories().entrySet()) {
+                Element<?> elementToWait = entry.getKey();
+                ConditionalState elementOwner = elementToWait.getOwner();
+                assert elementOwner != null
+                        : String.format("Element \"%s\" is not bound", elementToWait);
+                int elementOwnerPhase = elementOwner.getPhase();
+                ElementFactory factory = entry.getValue();
+                assert elementOwnerPhase == ConditionalState.Phase.TRANSITIONING_TO
+                                || elementOwnerPhase == ConditionalState.Phase.ACTIVE
+                        : String.format(
+                                "Cannot create ElementFactory waiting for element \"%s\" owned by"
+                                        + " %s because the owner is in Phase %s",
+                                elementToWait,
+                                elementOwner,
+                                ConditionalState.phaseToShortString(elementOwnerPhase));
                 allConditionsGuardingFactories.put(
-                        entry.getKey().getEnterConditionChecked(), entry.getValue());
+                        elementToWait.getEnterConditionChecked(), factory);
             }
         }
 
-        return allConditionsGuardingFactories;
+        mConditionsGuardingFactories = allConditionsGuardingFactories;
     }
 
     /**
@@ -412,11 +430,11 @@
         List<ConditionWait> nextBatch = mWaits;
         mWaits = new ArrayList<>();
         while (!nextBatch.isEmpty()) {
-            List<ElementFactory> newFactories = new ArrayList<>();
+            List<Condition> conditionsToRemoveFromFactoryMap = new ArrayList<>();
+            List<ElementFactory> factoriesReadyToFabricate = new ArrayList<>();
             for (ConditionWait wait : nextBatch) {
                 // Check timeout before each Condition check; if multiple Conditions are taking
-                // long,
-                // the Transition can take too long to time out.
+                // long, the Transition can take too long to time out.
                 if (timeoutTimer.isTimedOut()) {
                     anyCriteriaMissing = true;
                     mWaits.addAll(nextBatch);
@@ -429,14 +447,33 @@
                 if (!stillNeedsWait && generator != null) {
                     // Remove from the map so that next time we check this wait
                     // we dont rerun the factory.
-                    mConditionsGuardingFactories.remove(wait.mCondition);
-                    newFactories.add(generator);
+                    conditionsToRemoveFromFactoryMap.add(wait.mCondition);
+                    factoriesReadyToFabricate.add(generator);
                 }
             }
 
+            // Call factories waiting for Conditions from past transitions
+            for (Map.Entry<Condition, ElementFactory> entry :
+                    mConditionsGuardingFactories.entrySet()) {
+                Condition conditionToWait = entry.getKey();
+                ElementFactory generator = entry.getValue();
+
+                // Already checked before adding to mConditionsGuardingFactories
+                assumeNonNull(conditionToWait.mOwnerState);
+
+                if (conditionToWait.mOwnerState.getPhase() == ConditionalState.Phase.ACTIVE) {
+                    conditionsToRemoveFromFactoryMap.add(conditionToWait);
+                    factoriesReadyToFabricate.add(generator);
+                }
+            }
+
+            for (Condition condition : conditionsToRemoveFromFactoryMap) {
+                mConditionsGuardingFactories.remove(condition);
+            }
+
             mWaits.addAll(nextBatch);
 
-            BaseElements newElements = fabricateElements(newFactories);
+            BaseElements newElements = fabricateElements(factoriesReadyToFabricate);
             nextBatch = createEnterConditionWaits(newElements);
 
             for (ConditionWait wait : nextBatch) {
diff --git a/build/build_config.h b/build/build_config.h
index 4768a6dc..9b40479 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -49,6 +49,10 @@
 //    ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
 //    ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
 
+// Mapping to some Rust conditionals:
+//
+// * `#[cfg(unix)]` ~= `BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)`
+
 #ifndef BUILD_BUILD_CONFIG_H_
 #define BUILD_BUILD_CONFIG_H_
 
diff --git a/build/config/unsafe_buffers_paths.txt b/build/config/unsafe_buffers_paths.txt
index 94ce1c6..561dd55 100644
--- a/build/config/unsafe_buffers_paths.txt
+++ b/build/config/unsafe_buffers_paths.txt
@@ -23,7 +23,9 @@
 -testing/iossim/
 -third_party/
 +third_party/blink/
++third_party/jni_zero/
 +third_party/ipcz/
++third_party/liburlpattern/
 -tools/
 -ui/gl/  # Unsafe generated files.
 -url/third_party/
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index c9656dae..b7789cb 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -66,6 +66,7 @@
 
     layer_impl->UpdateRasterSource(CreateRasterSource(),
                                    &last_updated_invalidation_.Write(*this));
+    layer_impl->set_should_batch_updated_tiles();
   }
 
   DCHECK(last_updated_invalidation_.Read(*this).IsEmpty());
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index e9bd13a0..6da78628 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -197,6 +197,11 @@
     // updates, so replacement is safe.
     layer_impl->updated_tiles_ = std::move(updated_tiles_);
     updated_tiles_.clear();
+
+    // Since the layer has been activated, all the active tree tile updates
+    // from this point must be batched until all the layer updates has been
+    // serialized and sent to viz via LayerTreeHostImpl::UpdateDisplayTree().
+    layer_impl->should_batch_updated_tiles_ = true;
   }
 
   layer_impl->SanityCheckTilingState();
@@ -948,10 +953,13 @@
   }
 
   if (layer_tree_impl()->settings().TreesInVizInClientProcess() &&
-      (!IsActive() || layer_tree_impl()->settings().commit_to_active_tree)) {
-    // Tiles for the tree currently being committed to (Pending or Active)
-    // are pushed to the display during UpdateDisplayTree. Accumulate those
-    // changes. These are pushed to the active tree in PushPropertiesTo().
+      should_batch_updated_tiles_) {
+    // This layer's tile updates are being batched. For a pending layer, this is
+    // always true. For an active layer, this means it was just activated and is
+    // waiting for its state to be sent to Viz via UpdateDisplayTree. The
+    // accumulated updates are pushed to the active tree on activation and
+    // active layer can continue to accumulate the tile updates until
+    // UpdateDisplayTree.
     updated_tiles_[tile->contents_scale_key()].emplace(tile->tiling_i_index(),
                                                        tile->tiling_j_index());
   }
@@ -2181,6 +2189,12 @@
 PictureLayerImpl::TileUpdateSet PictureLayerImpl::TakeUpdatedTiles() {
   TileUpdateSet updates;
   updates.swap(updated_tiles_);
+
+  // Reset this flag since the tile updates are now being serialized to viz. All
+  // future tile updates can be sent immediately as a part of active tree tile
+  // update via LayerTreeHostImpl::UpdateDisplayTile() rather than batching
+  // them.
+  should_batch_updated_tiles_ = false;
   return updates;
 }
 
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 5f73dd7..2a4f696 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -205,6 +205,12 @@
   bool IsDirectlyCompositedImage() const;
   bool nearest_neighbor() const { return nearest_neighbor_; }
 
+  void set_should_batch_updated_tiles() { should_batch_updated_tiles_ = true; }
+
+  bool should_batch_updated_tiles() const {
+    return should_batch_updated_tiles_;
+  }
+
  protected:
   friend class RasterizeAndRecordBenchmarkImpl;
 
@@ -279,6 +285,21 @@
   // Tracks tiles changed since the last call to TakeUpdatedTiles().
   TileUpdateSet updated_tiles_;
 
+  // When true, tile updates for this layer are batched in |updated_tiles_|
+  // instead of being sent to Viz immediately. This is necessary to prevent a
+  // race condition in TreesInViz mode where tile updates could arrive at Viz
+  // before the layer itself, causing the updates to be dropped. This flag is
+  // set during activation and cleared after the layer's properties (and batched
+  // tile updates) are sent to Viz during UpdateDisplayTree.
+  // Note that while we set this flag on active tree at activation and clear
+  // after the layer is sent to viz, for pending tree we always keep this flag
+  // set and never reset it. This is because all the pending tree updates must
+  // be batched.
+  // We also need to set it when there is a commit from PictureLayer
+  // to PictureLayerImpl to cover the commit directly to active tree cases where
+  // this flag will be reset again.
+  bool should_batch_updated_tiles_ = true;
+
   std::unique_ptr<PictureLayerTilingSet> tilings_ =
       CreatePictureLayerTilingSet();
   scoped_refptr<RasterSource> raster_source_;
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc
index 1a42010..fec14f9 100644
--- a/cc/paint/oop_pixeltest.cc
+++ b/cc/paint/oop_pixeltest.cc
@@ -2793,7 +2793,8 @@
       ri, sii, options, viz::SinglePlaneFormat::kRGBA_8888, dest_color_space);
 
   scoped_refptr<gpu::ClientSharedImage> yuv_client_si =
-      CreateClientSharedImage(ri, sii, options, viz::MultiPlaneFormat::kI420);
+      CreateClientSharedImage(ri, sii, options, viz::MultiPlaneFormat::kI420,
+                              gfx::ColorSpace::CreateREC709());
 
   SkPixmap pixmaps[SkYUVAInfo::kMaxPlanes] = {};
 
diff --git a/cc/paint/paint_op.cc b/cc/paint/paint_op.cc
index 6373bac3..9399a12 100644
--- a/cc/paint/paint_op.cc
+++ b/cc/paint/paint_op.cc
@@ -1271,7 +1271,7 @@
 static float ComputeEffectiveHdrHeadroom(const PaintFlags* flags,
                                          const PlaybackParams& params) {
   if (!flags) {
-    return 1.f;
+    return params.destination_hdr_headroom;
   }
   return flags->getDynamicRangeLimit().ComputeEffectiveHdrHeadroom(
       params.destination_hdr_headroom);
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index b366c59..3e9ca11 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -88,7 +88,7 @@
   bool is_analyzing = false;
 
   // The HDR headroom to tone map to.
-  float destination_hdr_headroom = 1.f;
+  float destination_hdr_headroom = 0.f;
 };
 
 class CC_PAINT_EXPORT SharedImageProvider {
diff --git a/cc/tiles/software_image_decode_cache_unittest.cc b/cc/tiles/software_image_decode_cache_unittest.cc
index 0ebfa0e..cb04dae 100644
--- a/cc/tiles/software_image_decode_cache_unittest.cc
+++ b/cc/tiles/software_image_decode_cache_unittest.cc
@@ -2258,7 +2258,9 @@
       PaintImage::kDefaultFrameIndex, TargetColorParams(raster_color_space));
 
   DecodedDrawImage decoded_image = cache_.GetDecodedImageForDraw(draw_image);
-  EXPECT_NE(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
+  EXPECT_EQ(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
+  EXPECT_TRUE(SkColorSpace::Equals(decoded_image.image()->colorSpace(),
+                                   image_color_space.ToSkColorSpace().get()));
   cache_.DrawWithImageFinished(draw_image, decoded_image);
 }
 
diff --git a/cc/tiles/software_image_decode_cache_unittest_combinations.cc b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
index e5277dc..5db40db0 100644
--- a/cc/tiles/software_image_decode_cache_unittest_combinations.cc
+++ b/cc/tiles/software_image_decode_cache_unittest_combinations.cc
@@ -77,7 +77,8 @@
   }
   virtual void VerifyEntryExists(int line,
                                  const DrawImage& draw_image,
-                                 const gfx::Size& expected_size) = 0;
+                                 const gfx::Size& expected_size,
+                                 bool expect_color_converted = true) = 0;
 
  private:
   std::unique_ptr<SoftwareImageDecodeCache> cache_;
@@ -119,7 +120,8 @@
   }
   void VerifyEntryExists(int line,
                          const DrawImage& draw_image,
-                         const gfx::Size& expected_size) override {
+                         const gfx::Size& expected_size,
+                         bool expect_color_converted = true) override {
     auto decoded = cache().GetDecodedImageForDraw(draw_image);
     SCOPED_TRACE(base::StringPrintf("Failure from line %d", line));
     EXPECT_EQ(decoded.image()->width(), expected_size.width());
@@ -142,11 +144,17 @@
 
   void VerifyEntryExists(int line,
                          const DrawImage& draw_image,
-                         const gfx::Size& expected_size) override {
+                         const gfx::Size& expected_size,
+                         bool expect_color_converted = true) override {
     auto decoded = cache().GetDecodedImageForDraw(draw_image);
-    EXPECT_TRUE(SkColorSpace::Equals(
-        decoded.image()->colorSpace(),
-        draw_image.target_color_space().ToSkColorSpace().get()));
+    if (expect_color_converted) {
+      EXPECT_TRUE(SkColorSpace::Equals(
+          decoded.image()->colorSpace(),
+          draw_image.target_color_space().ToSkColorSpace().get()));
+    } else {
+      EXPECT_TRUE(SkColorSpace::Equals(decoded.image()->colorSpace(),
+                                       draw_image.paint_image().color_space()));
+    }
     SCOPED_TRACE(base::StringPrintf("Failure from line %d", line));
     EXPECT_EQ(decoded.image()->width(), expected_size.width());
     EXPECT_EQ(decoded.image()->height(), expected_size.height());
@@ -531,7 +539,8 @@
 TEST_F(SoftwareImageDecodeCacheTest_N32HDR, DontForceF16Decode) {
   auto draw_image = CreateDrawImageForScale(1.f);
   GenerateCacheEntry(draw_image);
-  VerifyEntryExists(__LINE__, draw_image, gfx::Size(512, 512));
+  VerifyEntryExists(__LINE__, draw_image, gfx::Size(512, 512),
+                    /*expect_color_converted=*/false);
   EXPECT_EQ(kN32_SkColorType, draw_image.paint_image().GetColorType());
   EXPECT_EQ(1u, cache().GetNumCacheEntriesForTesting());
 
@@ -557,7 +566,8 @@
 TEST_F(SoftwareImageDecodeCacheTest_F16HDR, AllowF16Decode) {
   auto draw_image = CreateDrawImageForScale(1.f);
   GenerateCacheEntry(draw_image);
-  VerifyEntryExists(__LINE__, draw_image, gfx::Size(512, 512));
+  VerifyEntryExists(__LINE__, draw_image, gfx::Size(512, 512),
+                    /*expect_color_converted=*/false);
   EXPECT_EQ(kRGBA_F16_SkColorType, draw_image.paint_image().GetColorType());
   EXPECT_EQ(1u, cache().GetNumCacheEntriesForTesting());
 
diff --git a/cc/tiles/software_image_decode_cache_utils.cc b/cc/tiles/software_image_decode_cache_utils.cc
index 0d52b8d..d2cf8c2 100644
--- a/cc/tiles/software_image_decode_cache_utils.cc
+++ b/cc/tiles/software_image_decode_cache_utils.cc
@@ -16,6 +16,7 @@
 #include "base/process/memory.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/paint/paint_flags.h"
+#include "cc/paint/tone_map_util.h"
 #include "cc/tiles/mipmap_util.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/core/SkImage.h"
@@ -74,14 +75,27 @@
   DCHECK(target_size == paint_image.GetSupportedDecodeSize(target_size));
   sk_sp<SkColorSpace> target_color_space =
       key.target_color_params().color_space.ToSkColorSpace();
+
+  // Temporary workaround for migrating HLG and PQ color spaces. The round-trip
+  // through gfx::ColorSpace destroys the distinction between HLG and HLGish,
+  // and PQ and PQish. Ensure that the decode of these spaces does no
+  // conversion. https://issues.skia.org/issues/420956739
+  sk_sp<SkColorSpace> decode_color_space = target_color_space;
+  if (key.target_color_params().color_space.GetTransferID() ==
+          gfx::ColorSpace::TransferID::PQ ||
+      key.target_color_params().color_space.GetTransferID() ==
+          gfx::ColorSpace::TransferID::HLG) {
+    decode_color_space = paint_image.GetSkImageInfo().refColorSpace();
+  }
+
   SkImageInfo target_info = SkImageInfo::Make(
       target_size, color_type, kPremul_SkAlphaType, target_color_space);
   std::unique_ptr<base::DiscardableMemory> target_pixels =
       AllocateDiscardable(target_info, std::move(on_no_memory));
   if (!target_pixels->data())
     return nullptr;
-  SkPixmap target_pixmap(target_info, target_pixels->data(),
-                         target_info.minRowBytes());
+  SkPixmap target_pixmap(target_info.makeColorSpace(decode_color_space),
+                         target_pixels->data(), target_info.minRowBytes());
 
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "SoftwareImageDecodeCacheUtils::DoDecodeImage - "
@@ -169,8 +183,30 @@
                                                        SkColorType color_type) {
   DCHECK(!image.paint_image().IsTextureBacked());
 
+  const auto& paint_image = image.paint_image();
   const PaintImage::FrameKey frame_key = image.frame_key();
-  const PaintImage::Id stable_id = image.paint_image().stable_id();
+  const PaintImage::Id stable_id = paint_image.stable_id();
+
+  // If the image will be tone mapped or contains a gain map, then do not bake
+  // the tone mapping or color conversion in at decode time. This is an explicit
+  // trade-off to:
+  // * Avoid re-decoding an image every time it is drawn with a different HDR
+  //   headroom (improving performance when transitioning to HDR).
+  // * Require running tone mapping shader at every draw (degrading performance
+  //   when drawing repeatedly at the same target headroom).
+  // * Maximize the code sharing between the software and GPU raster path. This
+  //   is the honest motivation for making the trade-off in this direction.
+  // * A better solution could be to separately cache decode and tone map
+  //   results (and only ever cache one tone mapping for a given image).
+  TargetColorParams target_color_params = image.target_color_params();
+  target_color_params.hdr_headroom = std::nullopt;
+  if (ToneMapUtil::UseGainmapShader(paint_image) ||
+      ToneMapUtil::UseGlobalToneMapFilter(paint_image.color_space())) {
+    if (paint_image.color_space()) {
+      target_color_params.color_space =
+          gfx::ColorSpace(*paint_image.color_space());
+    }
+  }
 
   const SkSize& scale = image.scale();
   // If the src_rect falls outside of the image, we need to clip it since
@@ -190,8 +226,8 @@
   // the filter quality doesn't matter. Early out instead.
   if (target_size.IsEmpty()) {
     return CacheKey(frame_key, stable_id, kSubrectAndScale, false,
-                    image.paint_image().may_be_lcp_candidate(), src_rect,
-                    target_size, image.target_color_params());
+                    paint_image.may_be_lcp_candidate(), src_rect, target_size,
+                    target_color_params);
   }
 
   ProcessingType type = kOriginal;
@@ -209,8 +245,7 @@
       !image.matrix_is_decomposable()) {
     type = kOriginal;
     // Update the size to be the original image size.
-    target_size =
-        gfx::Size(image.paint_image().width(), image.paint_image().height());
+    target_size = gfx::Size(paint_image.width(), paint_image.height());
   } else {
     type = kSubrectAndScale;
     // Update the target size to be a mip level size.
@@ -219,12 +254,11 @@
 
   // If the original image is large, we might want to do a subrect instead if
   // the subrect would be kMemoryRatioToSubrect times smaller.
-  if (type == kOriginal &&
-      (image.paint_image().width() >= kMinDimensionToSubrect ||
-       image.paint_image().height() >= kMinDimensionToSubrect)) {
+  if (type == kOriginal && (paint_image.width() >= kMinDimensionToSubrect ||
+                            paint_image.height() >= kMinDimensionToSubrect)) {
     base::CheckedNumeric<size_t> checked_original_size = 4u;
-    checked_original_size *= image.paint_image().width();
-    checked_original_size *= image.paint_image().height();
+    checked_original_size *= paint_image.width();
+    checked_original_size *= paint_image.height();
     size_t original_size = checked_original_size.ValueOrDefault(
         std::numeric_limits<size_t>::max());
 
@@ -246,7 +280,7 @@
 
   return CacheKey(frame_key, stable_id, type, is_nearest_neighbor,
                   image.paint_image().may_be_lcp_candidate(), src_rect,
-                  target_size, image.target_color_params());
+                  target_size, target_color_params);
 }
 
 SoftwareImageDecodeCacheUtils::CacheKey::CacheKey(
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 8daa07c..db1b564 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2154,12 +2154,13 @@
 
   layer_impl->NotifyTileStateChanged(tile, update_damage);
 
-  if (settings_.TreesInVizInClientProcess() && !is_pending_tree &&
-      !CommitsToActiveTree()) {
-    // Tiles for the tree currently being committed to (Pending or Active)
-    // are pushed to the display during UpdateDisplayTree. For active tree,
-    // if we're not committing to Active, tiles are pushed immediately via
-    // UpdateDisplayTile.
+  if (settings_.TreesInVizInClientProcess() &&
+      !static_cast<PictureLayerImpl&>(*layer_impl)
+           .should_batch_updated_tiles()) {
+    // In TreesInViz mode, send this tile update directly to Viz only if the
+    // layer is not batching its updates. A layer stops batching updates
+    // (should_batch_updated_tiles() becomes false) after it has been
+    // successfully sent to Viz via UpdateDisplayTree().
     layer_context_->UpdateDisplayTile(
         static_cast<PictureLayerImpl&>(*layer_impl), *tile,
         *resource_provider(), *layer_tree_frame_sink_->context_provider(),
diff --git a/chrome/android/expectations/trichrome_chrome_32_64_bundle__base.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_32_64_bundle__base.AndroidManifest.expected
index 531ae800..85fd5c4 100644
--- a/chrome/android/expectations/trichrome_chrome_32_64_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_32_64_bundle__base.AndroidManifest.expected
@@ -35,6 +35,7 @@
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.CAPTURE_KEYBOARD"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"/>
diff --git a/chrome/android/expectations/trichrome_chrome_32_bundle__base.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_32_bundle__base.AndroidManifest.expected
index 89b07d2d..c4d126c 100644
--- a/chrome/android/expectations/trichrome_chrome_32_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_32_bundle__base.AndroidManifest.expected
@@ -35,6 +35,7 @@
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.CAPTURE_KEYBOARD"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"/>
diff --git a/chrome/android/expectations/trichrome_chrome_64_32_bundle__base.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_64_32_bundle__base.AndroidManifest.expected
index f629cee..e73dfc7 100644
--- a/chrome/android/expectations/trichrome_chrome_64_32_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_64_32_bundle__base.AndroidManifest.expected
@@ -35,6 +35,7 @@
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.CAPTURE_KEYBOARD"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"/>
diff --git a/chrome/android/expectations/trichrome_chrome_64_bundle__base.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_64_bundle__base.AndroidManifest.expected
index e17df71..01df435 100644
--- a/chrome/android/expectations/trichrome_chrome_64_bundle__base.AndroidManifest.expected
+++ b/chrome/android/expectations/trichrome_chrome_64_bundle__base.AndroidManifest.expected
@@ -35,6 +35,7 @@
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.CAPTURE_KEYBOARD"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS"/>
   <uses-permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"/>
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryIphUtils.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryIphUtils.java
index d70c2c2f..fe7c6b3 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryIphUtils.java
+++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryIphUtils.java
@@ -222,8 +222,7 @@
             case FeatureConstants.KEYBOARD_ACCESSORY_PAYMENT_OFFER_FEATURE:
                 return R.string.iph_keyboard_accessory_payment_offer;
             case FeatureConstants.KEYBOARD_ACCESSORY_EXTERNAL_ACCOUNT_PROFILE_FEATURE:
-                return org.chromium.chrome.R.string
-                        .autofill_iph_external_account_profile_suggestion;
+                return R.string.autofill_iph_external_account_profile_suggestion;
             case FeatureConstants.KEYBOARD_ACCESSORY_VIRTUAL_CARD_CVC_FILL_FEATURE:
                 return R.string.iph_keyboard_accessory_virtual_card_cvc_fill_feature;
             case FeatureConstants.KEYBOARD_ACCESSORY_PLUS_ADDRESS_CREATE_SUGGESTION:
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 3c65c16..3bc5db74 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -124,6 +124,7 @@
   deps = [
     ":java_strings_grd",
     "//chrome/android:chrome_app_java_resources",
+    "//chrome/android/features/tab_ui/public:ui_java_resources",
     "//chrome/browser/data_sharing:java_resources",
   ]
 }
@@ -236,5 +237,6 @@
     "//third_party/hamcrest:hamcrest_library_java",
     "//third_party/junit",
     "//ui/android:ui_no_recycler_view_java",
+    "//url:url_java",
   ]
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
index b1a838f..6a72f146 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -51,8 +51,7 @@
             return AppCompatResources.getColorStateList(
                     context, R.color.incognito_tab_bg_selected_color);
         }
-        return ColorStateList.valueOf(
-                MaterialColors.getColor(context, org.chromium.chrome.R.attr.colorPrimary, TAG));
+        return ColorStateList.valueOf(MaterialColors.getColor(context, R.attr.colorPrimary, TAG));
     }
 
     /**
@@ -103,9 +102,7 @@
         } else {
             if (isSelected) {
                 @ColorInt
-                int baseColor =
-                        MaterialColors.getColor(
-                                context, org.chromium.chrome.R.attr.colorPrimary, TAG);
+                int baseColor = MaterialColors.getColor(context, R.attr.colorPrimary, TAG);
                 int alpha =
                         context.getResources()
                                 .getInteger(
@@ -175,9 +172,7 @@
                             : R.color.incognito_tab_grid_dialog_ungroup_bar_text_color);
         } else {
             return MaterialColors.getColor(
-                    context,
-                    isTabHovered ? R.attr.colorOnPrimary : org.chromium.chrome.R.attr.colorPrimary,
-                    TAG);
+                    context, isTabHovered ? R.attr.colorOnPrimary : R.attr.colorPrimary, TAG);
         }
     }
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java
index 616c13a..64b6df3d 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java
@@ -15,6 +15,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 
+import static org.chromium.chrome.test.util.ChromeTabUtils.getTabCountOnUiThread;
 import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;
 
 import android.os.SystemClock;
@@ -154,8 +155,8 @@
     }
 
     private void navigateToCloseAllTabsDialog(TabModelSelector selector) {
-
-        assertThat(selector.getModel(mIsIncognito).getCount(), greaterThanOrEqualTo(1));
+        int tabCount = getTabCountOnUiThread(selector.getModel(mIsIncognito));
+        assertThat(tabCount, greaterThanOrEqualTo(1));
 
         // Open the AppMenu in the Tab Switcher and ensure it shows.
         TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
index 2eba47c..c0f13883 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
@@ -420,18 +420,21 @@
      * @param isIncognito   indicates the tab model that we are creating tab group in.
      */
     static void mergeAllTabsToAGroup(ChromeTabbedActivity cta, boolean isIncognito) {
-        List<Tab> tabGroup = new ArrayList<>();
-        TabModel tabModel = cta.getTabModelSelector().getModel(isIncognito);
-        for (int i = 0; i < tabModel.getCount(); i++) {
-            tabGroup.add(tabModel.getTabAt(i));
-        }
-        createTabGroup(cta, isIncognito, tabGroup);
-        TabGroupModelFilter filter =
-                cta.getTabModelSelector()
-                        .getTabGroupModelFilterProvider()
-                        .getTabGroupModelFilter(isIncognito);
-        assertEquals(1, filter.getTabGroupCount());
-        assertEquals(1, filter.getIndividualTabAndGroupCount());
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    List<Tab> tabGroup = new ArrayList<>();
+                    TabModel tabModel = cta.getTabModelSelector().getModel(isIncognito);
+                    for (int i = 0; i < tabModel.getCount(); i++) {
+                        tabGroup.add(tabModel.getTabAt(i));
+                    }
+                    createTabGroup(cta, isIncognito, tabGroup);
+                    TabGroupModelFilter filter =
+                            cta.getTabModelSelector()
+                                    .getTabGroupModelFilterProvider()
+                                    .getTabGroupModelFilter(isIncognito);
+                    assertEquals(1, filter.getTabGroupCount());
+                    assertEquals(1, filter.getIndividualTabAndGroupCount());
+                });
     }
 
     /**
@@ -532,8 +535,8 @@
         assertTrue(numTabs >= 1);
         assertTrue(numIncognitoTabs >= 0);
 
-        assertEquals(1, rule.getActivity().getTabModelSelector().getModel(false).getCount());
-        assertEquals(0, rule.getActivity().getTabModelSelector().getModel(true).getCount());
+        assertEquals(1, rule.tabsCount(false));
+        assertEquals(0, rule.tabsCount(true));
 
         if (url != null) rule.loadUrl(url);
         if (numTabs > 1) {
@@ -542,10 +545,8 @@
         }
         if (numIncognitoTabs > 0) createTabsWithThumbnail(rule, numIncognitoTabs, url, true);
 
-        assertEquals(numTabs, rule.getActivity().getTabModelSelector().getModel(false).getCount());
-        assertEquals(
-                numIncognitoTabs,
-                rule.getActivity().getTabModelSelector().getModel(true).getCount());
+        assertEquals(numTabs, rule.tabsCount(false));
+        assertEquals(numIncognitoTabs, rule.tabsCount(true));
         if (url != null) {
             verifyAllTabsHaveUrl(rule.getActivity().getTabModelSelector().getModel(false), url);
             verifyAllTabsHaveUrl(rule.getActivity().getTabModelSelector().getModel(true), url);
@@ -553,9 +554,14 @@
     }
 
     private static void verifyAllTabsHaveUrl(TabModel tabModel, String url) {
-        for (int i = 0; i < tabModel.getCount(); i++) {
-            assertEquals(url, ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(i)));
-        }
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    int tabCount = tabModel.getCount();
+                    for (int i = 0; i < tabCount; i++) {
+                        String tabUrl = tabModel.getTabAt(i).getUrl().getSpec();
+                        assertEquals(url, tabUrl);
+                    }
+                });
     }
 
     /**
@@ -576,13 +582,15 @@
             boolean isIncognito) {
         ChromeTabbedActivity cta = rule.getActivity();
         assertTrue(numTabs >= 1);
-        int previousTabCount =
-                rule.getActivity().getTabModelSelector().getModel(isIncognito).getCount();
+        int previousTabCount = rule.tabsCount(isIncognito);
 
         for (int i = 0; i < numTabs; i++) {
             TabModel previousTabModel = cta.getTabModelSelector().getCurrentModel();
-            int previousTabIndex = previousTabModel.index();
-            Tab previousTab = previousTabModel.getTabAt(previousTabIndex);
+            int previousTabIndex =
+                    ThreadUtils.runOnUiThreadBlocking(() -> previousTabModel.index());
+            Tab previousTab =
+                    ThreadUtils.runOnUiThreadBlocking(
+                            () -> previousTabModel.getTabAt(previousTabIndex));
 
             boolean urlIsNull = url == null;
             if (urlIsNull) {
@@ -594,8 +602,10 @@
             }
 
             TabModel currentTabModel = cta.getTabModelSelector().getCurrentModel();
-            int currentTabIndex = currentTabModel.index();
-            Tab currentTab = currentTabModel.getTabAt(currentTabIndex);
+            int currentTabIndex = ThreadUtils.runOnUiThreadBlocking(() -> currentTabModel.index());
+            Tab currentTab =
+                    ThreadUtils.runOnUiThreadBlocking(
+                            () -> currentTabModel.getTabAt(currentTabIndex));
 
             waitForThumbnailsToCapture(cta, previousTab, currentTab);
         }
@@ -603,9 +613,7 @@
         ChromeTabUtils.waitForTabPageLoaded(
                 rule.getActivity().getActivityTab(), null, null, WAIT_TIMEOUT_SECONDS * 3);
 
-        assertEquals(
-                numTabs + previousTabCount,
-                rule.getActivity().getTabModelSelector().getModel(isIncognito).getCount());
+        assertEquals(numTabs + previousTabCount, rule.tabsCount(isIncognito));
 
         // Don't wait on the current tab to fetch. It should be fetched either when entering the
         // tab switcher or as a side-effect of unsticking the last tab.
@@ -652,8 +660,11 @@
     }
 
     public static void verifyAllTabsHaveThumbnail(TabModel tabModel) {
-        for (int i = 0; i < tabModel.getCount(); i++) {
-            checkThumbnailsExist(tabModel.getTabAt(i));
+        int tabCount = ThreadUtils.runOnUiThreadBlocking(() -> tabModel.getCount());
+        for (int i = 0; i < tabCount; i++) {
+            int j = i;  // Effectively final for the lambda.
+            Tab tab = ThreadUtils.runOnUiThreadBlocking(() -> tabModel.getTabAt(j));
+            checkThumbnailsExist(tab);
         }
     }
 
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
index 8a307705..1510588c2 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
@@ -519,16 +519,14 @@
 
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         assertEquals(
-                cta.getResources()
-                        .getDimensionPixelSize(org.chromium.chrome.R.dimen.ntp_search_box_height),
-                cta.findViewById(org.chromium.chrome.R.id.search_box).getLayoutParams().height);
+                cta.getResources().getDimensionPixelSize(R.dimen.ntp_search_box_height),
+                cta.findViewById(R.id.search_box).getLayoutParams().height);
 
         // Drag the Feed header title to scroll the toolbar to the top.
         int toY =
                 -getFakeboxTop(mNtp)
                         + cta.getResources()
-                                .getDimensionPixelSize(
-                                        org.chromium.chrome.R.dimen.modern_toolbar_background_size);
+                                .getDimensionPixelSize(R.dimen.modern_toolbar_background_size);
         TestTouchUtils.dragCompleteView(
                 InstrumentationRegistry.getInstrumentation(),
                 cta.findViewById(R.id.header_title),
@@ -543,8 +541,7 @@
             // There might be a rounding issue for some devices.
             assertEquals(
                     toolbar.getLocationBarBackgroundHeightForTesting(),
-                    cta.getResources()
-                            .getDimension(org.chromium.chrome.R.dimen.ntp_search_box_height),
+                    cta.getResources().getDimension(R.dimen.ntp_search_box_height),
                     0.5);
         }
     }
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 37fd15d9..1ede201 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -67,6 +67,7 @@
     <uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
 
     <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.CAPTURE_KEYBOARD" />
     <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     {% set is_desktop_android = is_desktop_android|default(0) %}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
index 325447c1..0d2fedf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
@@ -8,6 +8,7 @@
 
 import static org.chromium.chrome.browser.base.SplitCompatApplication.CHROME_SPLIT_NAME;
 
+import android.app.Activity;
 import android.app.ActivityManager.TaskDescription;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -57,17 +58,20 @@
 import org.chromium.chrome.browser.night_mode.GlobalNightModeStateProviderHolder;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
+import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController;
+import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeControllerCreator;
 import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeFieldTrialImpl;
 import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeUtils;
+import org.chromium.chrome.browser.ui.edge_to_edge.SimpleEdgeToEdgeController;
 import org.chromium.components.browser_ui.edge_to_edge.EdgeToEdgeManager;
 import org.chromium.components.browser_ui.edge_to_edge.EdgeToEdgeStateProvider;
 import org.chromium.components.browser_ui.edge_to_edge.EdgeToEdgeSystemBarColorHelper;
 import org.chromium.components.browser_ui.edge_to_edge.SystemBarColorHelper;
 import org.chromium.components.browser_ui.edge_to_edge.layout.EdgeToEdgeLayoutCoordinator;
-import org.chromium.ui.base.UiAndroidFeatureList;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 import org.chromium.components.browser_ui.util.AutomotiveUtils;
 import org.chromium.ui.base.ImmutableWeakReference;
+import org.chromium.ui.base.UiAndroidFeatureList;
 import org.chromium.ui.display.DisplaySwitches;
 import org.chromium.ui.display.DisplayUtil;
 import org.chromium.ui.insets.InsetObserver;
@@ -78,6 +82,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.LinkedHashSet;
 
 /**
@@ -120,6 +125,9 @@
             new ObservableSupplierImpl<>();
     protected final OneshotSupplierImpl<SystemBarColorHelper> mSystemBarColorHelperSupplier =
             new OneshotSupplierImpl<>();
+    // TODO(crbug.com/435269657): Update this and the ChromeActivity equivalent to OneShotSupplier
+    protected final ObservableSupplierImpl<EdgeToEdgeController> mEdgeToEdgeControllerSupplier =
+            new ObservableSupplierImpl<>();
 
     private NightModeStateProvider mNightModeStateProvider;
     private final LinkedHashSet<Integer> mThemeResIds = new LinkedHashSet<>();
@@ -130,6 +138,7 @@
     // Created in #onCreate
     private @Nullable EdgeToEdgeManager mEdgeToEdgeManager;
     private @Nullable EdgeToEdgeLayoutCoordinator mEdgeToEdgeLayoutCoordinator;
+    private @Nullable EdgeToEdgeControllerCreator mEdgeToEdgeControllerCreator;
 
     @Override
     protected void attachBaseContext(Context newBase) {
@@ -236,6 +245,32 @@
         return mSystemBarColorHelperSupplier;
     }
 
+    /**
+     * Returns an observable supplier providing an {@link EdgeToEdgeController} for observing the
+     * bottom system bar inset and drawing edge-to-edge. This also creates an EdgeToEdgeController
+     * instance for that supplier, or creates a controller creator that will create and supply an
+     * EdgeToEdgeController when all conditions are met for the device to draw edge-to-edge.
+     */
+    protected ObservableSupplier<EdgeToEdgeController> getEdgeToEdgeSupplier() {
+        if (ChromeFeatureList.sEdgeToEdgeMonitorConfigurations.isEnabled()) {
+            if (mEdgeToEdgeControllerCreator == null) {
+                mEdgeToEdgeControllerCreator =
+                        new EdgeToEdgeControllerCreator(
+                                new WeakReference<Activity>(this),
+                                getInsetObserver(),
+                                this::ensureEdgeToEdgeController);
+            }
+        } else {
+            ensureEdgeToEdgeController();
+        }
+        return mEdgeToEdgeControllerSupplier;
+    }
+
+    private void ensureEdgeToEdgeController() {
+        if (mEdgeToEdgeControllerSupplier.get() != null) return;
+        mEdgeToEdgeControllerSupplier.set(new SimpleEdgeToEdgeController(this, getInsetObserver()));
+    }
+
     /** Set the default colors of the system bars for this activity. */
     protected void initializeSystemBarColors(
             EdgeToEdgeSystemBarColorHelper edgeToEdgeSystemBarColorHelper) {
@@ -271,6 +306,13 @@
         if (mEdgeToEdgeManager != null) {
             mEdgeToEdgeManager.destroy();
         }
+        if (mEdgeToEdgeControllerSupplier.get() != null) {
+            mEdgeToEdgeControllerSupplier.get().destroy();
+        }
+        if (mEdgeToEdgeControllerCreator != null) {
+            mEdgeToEdgeControllerCreator.destroy();
+            mEdgeToEdgeControllerCreator = null;
+        }
         super.onDestroy();
     }
 
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 c5d00bd..d07e57f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -30,6 +30,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.PackageManagerUtils;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browserservices.SessionDataHolder;
 import org.chromium.chrome.browser.browserservices.intents.SessionHolder;
 import org.chromium.chrome.browser.browserservices.ui.splashscreen.trustedwebactivity.TwaSplashController;
@@ -550,7 +551,7 @@
             if (isContentScheme) {
                 Toast.makeText(
                                 mActivity,
-                                org.chromium.chrome.R.string.external_app_restricted_access_error,
+                                R.string.external_app_restricted_access_error,
                                 Toast.LENGTH_LONG)
                         .show();
             } else {
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 985b213..a01eccc 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
@@ -1983,12 +1983,13 @@
     }
 
     /**
-     * TODO: remove this method after InfoBar is deprecated.
+     * TODO: this method no longer needs to be public after InfoBar is deprecated.
      *
-     * @return a supplier for the {@link EdgeToEdgeController} that supports drawing to the edge of
-     *     the screen.
+     * <p>Returns a supplier for the {@link EdgeToEdgeController} that supports drawing to the edge
+     * of the screen.
      */
-    public final ObservableSupplier<EdgeToEdgeController> getEdgeToEdgeSupplier() {
+    @Override
+    public ObservableSupplier<EdgeToEdgeController> getEdgeToEdgeSupplier() {
         return mEdgeToEdgeControllerSupplier;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java
index 4cd389e7..933894e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java
@@ -203,6 +203,38 @@
     }
 
     @Override
+    public void requestKeyboardLock(boolean escKeyLocked) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.ENABLE_EXCLUSIVE_ACCESS_MANAGER)) {
+            return;
+        }
+        // It may happen that the tab does not have valid WebContents object. In Android
+        // the New Tab Page is not the actual web but the native views.
+        if (mTab.getWebContents() == null) {
+            return;
+        }
+        if (mExclusiveAccessManager == null) {
+            return;
+        }
+        mExclusiveAccessManager.requestKeyboardLock(mTab.getWebContents(), escKeyLocked);
+    }
+
+    @Override
+    public void cancelKeyboardLockRequest() {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.ENABLE_EXCLUSIVE_ACCESS_MANAGER)) {
+            return;
+        }
+        // It may happen that the tab does not have valid WebContents object. In Android
+        // the New Tab Page is not the actual web but the native views.
+        if (mTab.getWebContents() == null) {
+            return;
+        }
+        if (mExclusiveAccessManager == null) {
+            return;
+        }
+        mExclusiveAccessManager.cancelKeyboardLockRequest(mTab.getWebContents());
+    }
+
+    @Override
     protected boolean shouldResumeRequestsForCreatedWindow() {
         return true;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingMultiTabTask.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingMultiTabTask.java
index 458a538..0cf37a69 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingMultiTabTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingMultiTabTask.java
@@ -96,7 +96,7 @@
 
         Bundle multiTabBundle = new Bundle();
         multiTabBundle.putIntegerArrayList(IntentHandler.MULTI_TAB_KEY_TAB_IDS, tabIdsToReparent);
-        multiTabBundle.putStringArrayList(IntentHandler.MULTI_TAB_KEY_TAB_IDS, urlsToReparent);
+        multiTabBundle.putStringArrayList(IntentHandler.MULTI_TAB_KEY_TAB_URLS, urlsToReparent);
 
         intent.putExtra(IntentHandler.EXTRA_MULTI_TAB_REPARENTING_METADATA, multiTabBundle);
         IntentUtils.addTrustedIntentExtras(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabbedModeTabModelOrchestrator.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabbedModeTabModelOrchestrator.java
index 5f9c03dab..1b097c4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabbedModeTabModelOrchestrator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabbedModeTabModelOrchestrator.java
@@ -17,6 +17,7 @@
 import org.chromium.build.annotations.Initializer;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.DeferredStartupHandler;
 import org.chromium.chrome.browser.app.tabwindow.TabWindowManagerSingleton;
 import org.chromium.chrome.browser.crypto.CipherFactory;
@@ -143,8 +144,7 @@
             markTabModelsInitialized();
             Toast.makeText(
                             activity,
-                            activity.getString(
-                                    org.chromium.chrome.R.string.unsupported_number_of_windows),
+                            activity.getString(R.string.unsupported_number_of_windows),
                             Toast.LENGTH_LONG)
                     .show();
             return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
index 9626a12..edbb3a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.compositor;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -27,6 +29,9 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
+import org.chromium.build.annotations.Initializer;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutProvider;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
@@ -50,6 +55,7 @@
 /**
  * The is the {@link View} displaying the ui compositor results; including webpages and tabswitcher.
  */
+@NullMarked
 @JNINamespace("android")
 public class CompositorView extends FrameLayout
         implements CompositorSurfaceManager.SurfaceManagerCallbackTarget,
@@ -77,9 +83,9 @@
     private WindowAndroid mWindowAndroid;
     private TabContentManager mTabContentManager;
 
-    private View mRootView;
+    private @Nullable View mRootView;
     private boolean mPreloadedResources;
-    private Runnable mDrawingFinishedCallback;
+    private @Nullable Runnable mDrawingFinishedCallback;
 
     // True while in a WebXR "immersive-ar" session with DOM Overlay enabled. This disables
     // SurfaceControl while active.
@@ -92,7 +98,7 @@
 
     private boolean mHaveSwappedFramesSinceSurfaceCreated;
 
-    private Integer mSurfaceId;
+    private @Nullable Integer mSurfaceId;
 
     // On P and above, toggling the screen off gets us in a state where the Surface is destroyed but
     // it is never recreated when it is turned on again. This is the only workaround that seems to
@@ -113,7 +119,7 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)
+            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())
                     && mCompositorSurfaceManager != null
                     && !mIsInXr
                     && mNativeCompositorView != 0) {
@@ -272,7 +278,7 @@
     /**
      * @return The active {@link SurfaceView} of this compositor.
      */
-    public View getActiveSurfaceView() {
+    public @Nullable View getActiveSurfaceView() {
         return mCompositorSurfaceManager.getActiveSurfaceView();
     }
 
@@ -291,10 +297,12 @@
 
     /**
      * Initializes the {@link CompositorView}'s native parts (e.g. the rendering parts).
-     * @param lowMemDevice         If this is a low memory device.
-     * @param windowAndroid        A {@link WindowAndroid} instance.
-     * @param tabContentManager    A {@link TabContentManager} instance.
+     *
+     * @param lowMemDevice If this is a low memory device.
+     * @param windowAndroid A {@link WindowAndroid} instance.
+     * @param tabContentManager A {@link TabContentManager} instance.
      */
+    @Initializer
     public void initNativeCompositor(
             boolean lowMemDevice,
             WindowAndroid windowAndroid,
@@ -466,6 +474,7 @@
             Window window = mWindowAndroid.getWindow();
             if (window != null) {
                 AttachedSurfaceControl rootSurfaceControl = window.getRootSurfaceControl();
+                assumeNonNull(rootSurfaceControl);
                 browserInputToken = rootSurfaceControl.getInputTransferToken();
             }
         }
@@ -803,7 +812,7 @@
                 int height,
                 boolean backedBySurfaceTexture,
                 Surface surface,
-                InputTransferToken browserInputToken);
+                @Nullable InputTransferToken browserInputToken);
 
         void onPhysicalBackingSizeChanged(
                 long nativeCompositorView, WebContents webContents, int width, int height);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index 3ff814f..f7f1765 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -6,6 +6,8 @@
 
 import static androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 
+import static org.chromium.build.NullUtil.assertNonNull;
+import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.ui.accessibility.KeyboardFocusUtil.setFocus;
 import static org.chromium.ui.accessibility.KeyboardFocusUtil.setFocusOnFirstFocusableDescendant;
 import static org.chromium.ui.base.KeyNavigationUtil.isButtonActivate;
@@ -33,8 +35,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.WindowCompat;
@@ -51,6 +51,8 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.build.annotations.EnsuresNonNullIf;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
@@ -112,6 +114,7 @@
  * available on {@link android.view.ViewGroup}s. This class also holds the {@link LayoutManagerImpl}
  * responsible to describe the items to be drawn by the UI compositor on the native side.
  */
+@NullMarked
 public class CompositorViewHolder extends FrameLayout
         implements LayoutManagerHost,
                 LayoutRenderHost,
@@ -165,24 +168,24 @@
     private boolean mCanBeFocusable;
 
     /** A task to be performed after a resize event. */
-    private Runnable mPostHideKeyboardTask;
+    private @Nullable Runnable mPostHideKeyboardTask;
 
     private TabModelSelector mTabModelSelector;
     private @Nullable BrowserControlsManager mBrowserControlsManager;
-    @VisibleForTesting View mAccessibilityView;
-    private CompositorAccessibilityProvider mNodeProvider;
+    @VisibleForTesting @Nullable View mAccessibilityView;
+    private @Nullable CompositorAccessibilityProvider mNodeProvider;
 
     /** The toolbar control container. */
     private @Nullable ControlContainer mControlContainer;
 
     private boolean mShowingFullscreen;
-    private Runnable mSystemUiFullscreenResizeRunnable;
+    private @Nullable Runnable mSystemUiFullscreenResizeRunnable;
 
     /** The currently visible Tab. */
-    @VisibleForTesting Tab mTabVisible;
+    @VisibleForTesting @Nullable Tab mTabVisible;
 
     /** The currently attached View. */
-    private View mView;
+    private @Nullable View mView;
 
     /** The index of the {@link VirtualView} that has keyboard focus. */
     private int mKeyboardFocusIndex;
@@ -194,7 +197,7 @@
      * Current ContentView. Updates when active tab is switched or WebContents is swapped in the
      * current Tab.
      */
-    private ContentView mContentView;
+    private @Nullable ContentView mContentView;
 
     // Cache objects that should not be created frequently.
     private final Rect mCacheRect = new Rect();
@@ -209,10 +212,10 @@
     // TODO(crbug.com/265479149): We will remove |mInGesture| if we enable the
     // SUPPRESS_TOOLBAR_CAPTURES_AT_GESTURE_END feature.
     private int mNumGestureActiveTouches;
-    private ApplicationViewportInsetSupplier mApplicationBottomInsetSupplier;
+    private @Nullable ApplicationViewportInsetSupplier mApplicationBottomInsetSupplier;
 
     // Handler for changes to viewport insets.
-    private Callback<ViewportInsets> mOnViewportInsetsChanged;
+    private @Nullable Callback<ViewportInsets> mOnViewportInsetsChanged;
 
     /**
      * Tracks whether geometrychange event is fired for the active tab when the keyboard
@@ -228,25 +231,25 @@
     @VirtualKeyboardMode.EnumType
     private int mVirtualKeyboardMode = VirtualKeyboardMode.RESIZES_VISUAL;
 
-    private OnscreenContentProvider mOnscreenContentProvider;
+    private @Nullable OnscreenContentProvider mOnscreenContentProvider;
 
     private final Set<Runnable> mOnCompositorLayoutCallbacks = new HashSet<>();
     private final Set<Runnable> mDidSwapFrameCallbacks = new HashSet<>();
     private final Set<Runnable> mDidSwapBuffersCallbacks = new HashSet<>();
 
     /** Used to remove the temporary tab strip on startup, once the composited one is ready. */
-    private Runnable mSetBackgroundRunnable;
+    private @Nullable Runnable mSetBackgroundRunnable;
 
     private boolean mHasDrawnOnce;
 
-    private TopUiThemeColorProvider mTopUiThemeColorProvider;
+    private @Nullable TopUiThemeColorProvider mTopUiThemeColorProvider;
 
     // Permissions are requested on a drop event, and are released when another drag starts
     // (drag-started event) or when the current page navigates to a new URL or the tab changes.
-    private DragAndDropPermissions mDragAndDropPermissions;
+    private @Nullable DragAndDropPermissions mDragAndDropPermissions;
     // The URI when a drop contains a single URI. If the tab changes and is loading this URI, we do
     // not clear the permissions.
-    private Uri mDropUri;
+    private @Nullable Uri mDropUri;
 
     private final EventOffsetHandler mEventOffsetHandler =
             new EventOffsetHandler(
@@ -274,7 +277,7 @@
                             if (forwarder != null) forwarder.setDragDispatchingOffset(dx, dy);
                         }
 
-                        private EventForwarder getEventForwarder() {
+                        private @Nullable EventForwarder getEventForwarder() {
                             if (mTabVisible == null) return null;
                             WebContents webContents = mTabVisible.getWebContents();
                             if (webContents == null) return null;
@@ -337,12 +340,12 @@
                 }
             };
 
-    private View mUrlBar;
+    private @Nullable View mUrlBar;
 
     private PrefService mPrefService;
 
     @Override
-    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
+    public @Nullable PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
         View activeView = getContentView();
         if (activeView == null || !ViewCompat.isAttachedToWindow(activeView)) return null;
         return activeView.onResolvePointerIcon(event, pointerIndex);
@@ -359,6 +362,7 @@
         internalInit();
     }
 
+    @org.chromium.build.annotations.Initializer
     private void internalInit() {
         addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
@@ -462,7 +466,7 @@
         if (mSystemUiFullscreenResizeRunnable == null) {
             mSystemUiFullscreenResizeRunnable = this::handleWindowInsetChanged;
         } else {
-            getHandler().removeCallbacks(mSystemUiFullscreenResizeRunnable);
+            assumeNonNull(getHandler()).removeCallbacks(mSystemUiFullscreenResizeRunnable);
         }
 
         // If SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN is set, defer updating the viewport to allow
@@ -619,11 +623,12 @@
     }
 
     /** This is called when the native library are ready. */
+    @org.chromium.build.annotations.Initializer
     public void onNativeLibraryReady(
             WindowAndroid windowAndroid,
             TabContentManager tabContentManager,
             PrefService prefService) {
-        mActivity = windowAndroid.getActivity().get();
+        mActivity = assumeNonNull(windowAndroid.getActivity().get());
         mCompositorView.initNativeCompositor(
                 SysUtils.isLowEndDevice(), windowAndroid, tabContentManager);
 
@@ -822,19 +827,19 @@
     /**
      * @return The SurfaceView proxy used by the Compositor.
      */
-    public CompositorView getCompositorView() {
+    public @Nullable CompositorView getCompositorView() {
         return mCompositorView;
     }
 
     /**
      * @return The active {@link android.view.SurfaceView} of the Compositor.
      */
-    public View getActiveSurfaceView() {
+    public @Nullable View getActiveSurfaceView() {
         return mCompositorView.getActiveSurfaceView();
     }
 
     @VisibleForTesting
-    Tab getCurrentTab() {
+    @Nullable Tab getCurrentTab() {
         if (mLayoutManager == null || mTabModelSelector == null) return null;
         Tab currentTab = mTabModelSelector.getCurrentTab();
 
@@ -845,12 +850,12 @@
     }
 
     @VisibleForTesting
-    ViewGroup getContentView() {
+    @Nullable ViewGroup getContentView() {
         Tab tab = getCurrentTab();
         return tab != null ? tab.getContentView() : null;
     }
 
-    protected WebContents getWebContents() {
+    protected @Nullable WebContents getWebContents() {
         Tab tab = getCurrentTab();
         return tab != null ? tab.getWebContents() : null;
     }
@@ -873,15 +878,15 @@
     /**
      * Ensures the tab-backed webContents' size is up to date.
      *
-     * Using this view's current size, taking into account the current state of UI like the virtual
-     * keyboard and browser controls and resizes as well as the virtual keyboard resizing mode,
-     * updates the size of the given Tab's WebContents. If the given view isn't attached to the
-     * Window, this method will force it to layout and use that size.
+     * <p>Using this view's current size, taking into account the current state of UI like the
+     * virtual keyboard and browser controls and resizes as well as the virtual keyboard resizing
+     * mode, updates the size of the given Tab's WebContents. If the given view isn't attached to
+     * the Window, this method will force it to layout and use that size.
      *
      * @param tab {@link Tab} for which the size of the view is set.
      */
     @VisibleForTesting
-    void updateWebContentsSize(Tab tab) {
+    void updateWebContentsSize(@Nullable Tab tab) {
         if (tab == null) return;
 
         WebContents webContents = tab.getWebContents();
@@ -909,7 +914,8 @@
 
         int keyboardInset =
                 mApplicationBottomInsetSupplier != null
-                        ? mApplicationBottomInsetSupplier.get().webContentsHeightInset
+                        ? assumeNonNull(mApplicationBottomInsetSupplier.get())
+                                .webContentsHeightInset
                         : 0;
 
         int viewportInsets = controlsInsets + keyboardInset;
@@ -940,7 +946,7 @@
         }
     }
 
-    private static boolean isAttachedToWindow(View view) {
+    private static boolean isAttachedToWindow(@Nullable View view) {
         return view != null && view.getWindowToken() != null;
     }
 
@@ -996,7 +1002,8 @@
         }
     }
 
-    private void onControlsResizeViewChanged(WebContents webContents, boolean controlsResizeView) {
+    private void onControlsResizeViewChanged(
+            @Nullable WebContents webContents, boolean controlsResizeView) {
         if (webContents != null && mCompositorView != null) {
             mCompositorView.onControlsResizeViewChanged(webContents, controlsResizeView);
         }
@@ -1200,7 +1207,8 @@
         getWindowViewport(outRect);
 
         if (mApplicationBottomInsetSupplier != null) {
-            outRect.bottom -= mApplicationBottomInsetSupplier.get().viewVisibleHeightInset;
+            outRect.bottom -=
+                    assumeNonNull(mApplicationBottomInsetSupplier.get()).viewVisibleHeightInset;
         }
 
         // mApplicationBottomInsetSupplier doesn't include browser controls.
@@ -1217,7 +1225,8 @@
         getWindowViewport(outRect);
 
         if (mApplicationBottomInsetSupplier != null) {
-            outRect.bottom -= mApplicationBottomInsetSupplier.get().viewVisibleHeightInset;
+            outRect.bottom -=
+                    assumeNonNull(mApplicationBottomInsetSupplier.get()).viewVisibleHeightInset;
         }
 
         // mApplicationBottomInsetSupplier doesn't include browser controls.
@@ -1231,7 +1240,7 @@
     }
 
     @Override
-    public void requestRender(Runnable onUpdateEffective) {
+    public void requestRender(@Nullable Runnable onUpdateEffective) {
         if (onUpdateEffective != null) {
             mOnCompositorLayoutCallbacks.add(onUpdateEffective);
             updateNeedsSwapBuffersCallback();
@@ -1321,11 +1330,12 @@
 
     @Override
     public BrowserControlsManager getBrowserControlsManager() {
-        return mBrowserControlsManager;
+        return assertNonNull(mBrowserControlsManager);
     }
 
     @Override
     public FullscreenManager getFullscreenManager() {
+        assumeNonNull(mBrowserControlsManager);
         return mBrowserControlsManager.getFullscreenManager();
     }
 
@@ -1370,6 +1380,7 @@
 
         // Removes the accessibility node provider from this view.
         if (mNodeProvider != null) {
+            assumeNonNull(mAccessibilityView);
             mAccessibilityView.setAccessibilityDelegate(null);
             mNodeProvider = null;
             removeView(mAccessibilityView);
@@ -1409,11 +1420,13 @@
      * @param bottomControlsOffsetSupplier Supplier of the offset, relative to the bottom of the
      *     viewport, of the bottom-anchored toolbar.
      */
+    @org.chromium.build.annotations.Initializer
     public void onFinishNativeInitialization(
             TabModelSelector tabModelSelector,
             TabCreatorManager tabCreatorManager,
             ObservableSupplier<Integer> bottomControlsOffsetSupplier) {
         assert mLayoutManager != null;
+        assert mTopUiThemeColorProvider != null;
         mLayoutManager.init(
                 tabModelSelector,
                 tabCreatorManager,
@@ -1444,7 +1457,9 @@
         if (mView == null) return;
         WebContents webContents = getWebContents();
         if (show) {
-            if (mView != getCurrentTab().getView() || mView.getParent() == this) return;
+            if (mView != assumeNonNull(getCurrentTab()).getView() || mView.getParent() == this) {
+                return;
+            }
             // During tab creation, we temporarily add the new tab's view to a FrameLayout to
             // measure and lay it out. This way we could show the animation in the stack view.
             // Therefore we should remove the view from that temporary FrameLayout here.
@@ -1452,7 +1467,7 @@
 
             if (webContents != null) {
                 assert !webContents.isDestroyed();
-                getContentView().setVisibility(View.VISIBLE);
+                assumeNonNull(getContentView()).setVisibility(View.VISIBLE);
                 tryUpdateControlsAndWebContentsSizing();
             }
 
@@ -1471,7 +1486,7 @@
                 setFocusableInTouchMode(mCanBeFocusable);
 
                 if (webContents != null && !webContents.isDestroyed()) {
-                    getContentView().setVisibility(View.INVISIBLE);
+                    assumeNonNull(getContentView()).setVisibility(View.INVISIBLE);
                 }
                 removeView(mView);
             }
@@ -1507,7 +1522,7 @@
         onControlsResizeViewChanged(getWebContents(), mControlsResizeView);
     }
 
-    private void setTab(Tab tab) {
+    private void setTab(@Nullable Tab tab) {
         if (tab != null) {
             tab.loadIfNeeded(TabLoadIfNeededCaller.SET_TAB);
         }
@@ -1539,9 +1554,10 @@
 
         if (mOnscreenContentProvider == null) {
             mOnscreenContentProvider =
-                    new OnscreenContentProvider(getContext(), this, getWebContents());
+                    new OnscreenContentProvider(
+                            getContext(), this, assumeNonNull(getWebContents()));
         } else {
-            mOnscreenContentProvider.onWebContentsChanged(getWebContents());
+            mOnscreenContentProvider.onWebContentsChanged(assumeNonNull(getWebContents()));
         }
 
         // Clear drop permissions when tab changes unless this is a new tab loading from the drop.
@@ -1552,7 +1568,7 @@
         }
     }
 
-    private void updateViewStateListener(ContentView newContentView) {
+    private void updateViewStateListener(@Nullable ContentView newContentView) {
         if (mContentView != null) {
             mContentView.removeOnHierarchyChangeListener(this);
             mContentView.setDeferKeepScreenOnChanges(false);
@@ -1661,7 +1677,9 @@
 
                         @Override
                         public void onFocusChanged(
-                                boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+                                boolean gainFocus,
+                                int direction,
+                                @Nullable Rect previouslyFocusedRect) {
                             super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
                             // Clear focus ring indicators.
                             if (!gainFocus) resetKeyboardFocus();
@@ -1683,7 +1701,8 @@
     // KeyListener and VirtualView management.
 
     @Override
-    public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+    public void onFocusChanged(
+            boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
         // Clear focus ring indicators.
         if (!gainFocus) resetKeyboardFocus();
@@ -1697,14 +1716,14 @@
     }
 
     @Override
-    public void requestKeyboardFocus(@NonNull SceneOverlay sceneOverlay) {
+    public void requestKeyboardFocus(SceneOverlay sceneOverlay) {
         mSceneOverlay = sceneOverlay;
         mKeyboardFocusIndex = 0;
         updateKeyboardFocus(getVirtualViewsForCurrentSceneOverlay());
     }
 
     @Override
-    public boolean containsKeyboardFocus(@NonNull SceneOverlay sceneOverlay) {
+    public boolean containsKeyboardFocus(SceneOverlay sceneOverlay) {
         return sceneOverlay.equals(mSceneOverlay)
                 && (isA11ySetUp() ? mAccessibilityView.hasFocus() : hasFocus());
     }
@@ -1806,7 +1825,8 @@
     public void setFocusOnFirstContentViewItem() {
         // We are no longer focusing on a scene overlay b/c we are focus on main content
         resetKeyboardFocus();
-        View view = getCurrentTab().getView();
+        View view = assumeNonNull(getCurrentTab()).getView();
+        assumeNonNull(view);
         if (view instanceof ViewGroup viewGroup) {
             setFocusOnFirstFocusableDescendant(viewGroup);
         } else {
@@ -1857,7 +1877,7 @@
 
         @Override
         protected boolean onPerformActionForVirtualView(
-                int virtualViewId, int action, Bundle arguments) {
+                int virtualViewId, int action, @Nullable Bundle arguments) {
             switch (action) {
                 case AccessibilityNodeInfoCompat.ACTION_CLICK:
                     mVirtualViews
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index 215a3f2..39e0a022 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -1138,7 +1138,7 @@
         ViewGroup result = mContainerView;
         assumeNonNull(mContainerView);
         // Use the coordinator inside of the container if we can get it. See crbug.com/1258902.
-        ViewGroup coordinator = mContainerView.findViewById(org.chromium.chrome.R.id.coordinator);
+        ViewGroup coordinator = mContainerView.findViewById(R.id.coordinator);
         // Returns null in tests. TODO(donnd): figure out why - tests should have the same views.
         if (coordinator != null) result = coordinator;
         return result;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java
index 0b3b94e..dfaf2af4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java
@@ -191,10 +191,10 @@
 
             if (tabId == Tab.INVALID_TAB_ID) return;
 
-            if (menuId == org.chromium.chrome.R.id.ungroup_tab) {
+            if (menuId == R.id.ungroup_tab) {
                 TabUiUtils.ungroupTabGroup(tabGroupModelFilter, tabGroupId);
                 RecordUserAction.record("MobileToolbarTabGroupMenu.Ungroup");
-            } else if (menuId == org.chromium.chrome.R.id.close_tab_group) {
+            } else if (menuId == R.id.close_tab_group) {
                 boolean allowUndo = TabClosureParamsUtils.shouldAllowUndo(listViewTouchTracker);
                 TabUiUtils.closeTabGroup(
                         tabGroupModelFilter,
@@ -204,7 +204,7 @@
                         /* hideTabGroups= */ true,
                         /* didCloseCallback= */ null);
                 RecordUserAction.record("MobileToolbarTabGroupMenu.CloseGroup");
-            } else if (menuId == org.chromium.chrome.R.id.delete_tab_group) {
+            } else if (menuId == R.id.delete_tab_group) {
                 boolean allowUndo = TabClosureParamsUtils.shouldAllowUndo(listViewTouchTracker);
                 TabUiUtils.closeTabGroup(
                         tabGroupModelFilter,
@@ -214,7 +214,7 @@
                         /* hideTabGroups= */ false,
                         /* didCloseCallback= */ null);
                 RecordUserAction.record("MobileToolbarTabGroupMenu.DeleteGroup");
-            } else if (menuId == org.chromium.chrome.R.id.open_new_tab_in_group) {
+            } else if (menuId == R.id.open_new_tab_in_group) {
                 TabGroupUtils.openUrlInGroup(
                         tabGroupModelFilter,
                         UrlConstants.NTP_URL,
@@ -238,7 +238,7 @@
                 if (tabGroupMetadata != null) {
                     multiInstanceManager.moveTabGroupToOtherWindow(tabGroupMetadata);
                 }
-            } else if (menuId == org.chromium.chrome.R.id.share_group) {
+            } else if (menuId == R.id.share_group) {
                 // Create the group share flow and display the share bottom sheet.
                 dataSharingTabManager.createOrManageFlow(
                         eitherId,
@@ -520,8 +520,7 @@
         if (isIncognito) {
             mGroupTitleEditText.setBackgroundTintList(
                     AppCompatResources.getColorStateList(
-                            context,
-                            org.chromium.chrome.R.color.menu_edit_text_bg_tint_list_baseline));
+                            context, R.color.menu_edit_text_bg_tint_list_baseline));
             mGroupTitleEditText.setTextAppearance(
                     R.style.TextAppearance_TextLarge_Primary_Baseline_Light);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandler.java
index dcb322d..cae8d7c4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandler.java
@@ -1,3 +1,7 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 package org.chromium.chrome.browser.customtabs;
 
 import android.app.Activity;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabCompositorContentInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabCompositorContentInitializer.java
index 3cb82cb..c18f187f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabCompositorContentInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabCompositorContentInitializer.java
@@ -10,6 +10,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
@@ -76,8 +77,8 @@
 
         mCompositorViewHolderInitializer.initializeCompositorContent(
                 layoutDriver,
-                mActivity.findViewById(org.chromium.chrome.R.id.url_bar),
-                mActivity.findViewById(org.chromium.chrome.R.id.control_container));
+                mActivity.findViewById(R.id.url_bar),
+                mActivity.findViewById(R.id.control_container));
 
         for (Callback<LayoutManagerImpl> listener : mListeners) {
             listener.onResult(layoutDriver);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabFullSizeStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabFullSizeStrategy.java
index 6b305ff..974826f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabFullSizeStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabFullSizeStrategy.java
@@ -137,7 +137,7 @@
     @Override
     protected void setTopMargins(int shadowOffset, int handleOffset) {
         // No offset as we will not have handle view in full-screen
-        View handleView = mActivity.findViewById(org.chromium.chrome.R.id.custom_tabs_handle_view);
+        View handleView = mActivity.findViewById(R.id.custom_tabs_handle_view);
         ViewGroup.MarginLayoutParams lp =
                 (ViewGroup.MarginLayoutParams) handleView.getLayoutParams();
         lp.setMargins(0, 0, 0, 0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java
index 2131e84..ecd553e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java
@@ -13,6 +13,7 @@
 import org.chromium.base.Callback;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.R;
 import org.chromium.components.permissions.AndroidPermissionRequester;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
@@ -108,9 +109,7 @@
         if (windowAndroid.getModalDialogManager() != null) {
             AndroidPermissionRequester.showMissingPermissionDialog(
                     windowAndroid,
-                    context.getString(
-                            org.chromium.chrome.R.string
-                                    .missing_storage_permission_download_education_text),
+                    context.getString(R.string.missing_storage_permission_download_education_text),
                     requestPermissions,
                     callback.bind(Pair.create(false, null)));
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index 310edab..595186c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -231,13 +231,6 @@
     }
 
     @Override
-    public boolean shouldEmbedderInitiatedNavigationsStayInBrowser() {
-        // The initial navigation off of things like typed navigations or bookmarks should stay in
-        // the browser.
-        return true;
-    }
-
-    @Override
     public String getSelfScheme() {
         return IntentHandler.GOOGLECHROME_SCHEME;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
index f17c4e0..4b3bca72b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
@@ -40,6 +40,7 @@
 import org.chromium.build.BuildConfig;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.app.tab_activity_glue.ReparentingMultiTabTask;
@@ -165,7 +166,7 @@
 
     @Override
     public boolean handleMenuOrKeyboardAction(int id, boolean fromMenu) {
-        if (id == org.chromium.chrome.R.id.manage_all_windows_menu_id) {
+        if (id == R.id.manage_all_windows_menu_id) {
             showInstanceSwitcherDialog();
 
             if (AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManagerSupplier.get())) {
@@ -204,6 +205,7 @@
                         cleanupSyncedTabGroupsIfLastInstance();
                     }
                 },
+                (pair) -> writeTitle(pair.first, pair.second),
                 () -> openNewWindow("Android.WindowManager.NewWindow", /* incognito= */ false),
                 MultiWindowUtils.getMaxInstances(),
                 info);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerImpl.java
index ad34cbb4..02c630df 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerImpl.java
@@ -30,6 +30,7 @@
 import org.chromium.build.BuildConfig;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.app.tab_activity_glue.ReparentingMultiTabTask;
 import org.chromium.chrome.browser.app.tab_activity_glue.ReparentingTask;
@@ -329,7 +330,7 @@
 
     @Override
     public boolean handleMenuOrKeyboardAction(int id, boolean fromMenu) {
-        if (id == org.chromium.chrome.R.id.move_to_other_window_menu_id) {
+        if (id == R.id.move_to_other_window_menu_id) {
             TabModelOrchestrator tabModelOrchestrator = mTabModelOrchestratorSupplier.get();
             if (tabModelOrchestrator == null) return true;
             TabModelSelector tabModelSelector = tabModelOrchestrator.getTabModelSelector();
@@ -338,10 +339,10 @@
             Tab currentTab = tabModelSelector.getCurrentTab();
             if (currentTab != null) moveTabsToOtherWindow(Collections.singletonList(currentTab));
             return true;
-        } else if (id == org.chromium.chrome.R.id.new_window_menu_id) {
+        } else if (id == R.id.new_window_menu_id) {
             openNewWindow("MobileMenuNewWindow", /* incognito= */ false);
             return true;
-        } else if (id == org.chromium.chrome.R.id.new_incognito_window_menu_id) {
+        } else if (id == R.id.new_incognito_window_menu_id) {
             // TODO(crbug.com/429518328): Hook up with incognito window.
             openNewWindow("MobileMenuNewIncognitoWindow", /* incognito= */ true);
             return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
index e1dfb75..be3cfb8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -176,14 +176,11 @@
         super(context, attrs);
         mContext = context;
         Resources resources = getResources();
-        mTileViewWidth =
-                resources.getDimensionPixelOffset(org.chromium.chrome.R.dimen.tile_view_width);
+        mTileViewWidth = resources.getDimensionPixelOffset(R.dimen.tile_view_width);
         mTileViewIntervalPaddingTablet =
-                resources.getDimensionPixelOffset(
-                        org.chromium.chrome.R.dimen.tile_view_padding_interval_tablet);
+                resources.getDimensionPixelOffset(R.dimen.tile_view_padding_interval_tablet);
         mTileViewEdgePaddingTablet =
-                resources.getDimensionPixelOffset(
-                        org.chromium.chrome.R.dimen.tile_view_padding_edge_tablet);
+                resources.getDimensionPixelOffset(R.dimen.tile_view_padding_edge_tablet);
 
         mNtpSearchBoxTopMarginWithoutLogo =
                 resources.getDimensionPixelSize(R.dimen.mvt_container_top_margin);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/search/SearchBoxViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/search/SearchBoxViewBinder.java
index 71d6557..331d5e82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/search/SearchBoxViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/search/SearchBoxViewBinder.java
@@ -30,11 +30,9 @@
         implements PropertyModelChangeProcessor.ViewBinder<PropertyModel, View, PropertyKey> {
     @Override
     public final void bind(PropertyModel model, View view, PropertyKey propertyKey) {
-        ImageView voiceSearchButton =
-                view.findViewById(org.chromium.chrome.R.id.voice_search_button);
-        ImageView lensButton = view.findViewById(org.chromium.chrome.R.id.lens_camera_button);
-        LottieAnimationView composeplateButton =
-                view.findViewById(org.chromium.chrome.R.id.composeplate_button);
+        ImageView voiceSearchButton = view.findViewById(R.id.voice_search_button);
+        ImageView lensButton = view.findViewById(R.id.lens_camera_button);
+        LottieAnimationView composeplateButton = view.findViewById(R.id.composeplate_button);
         View searchBoxContainer = view;
         final TextView searchBoxTextView = searchBoxContainer.findViewById(R.id.search_box_text);
 
@@ -95,8 +93,7 @@
             boolean isHintVisible = model.get(SearchBoxProperties.SEARCH_HINT_VISIBILITY);
             searchBoxTextView.setHint(
                     isHintVisible
-                            ? view.getContext()
-                                    .getString(org.chromium.chrome.R.string.omnibox_empty_hint)
+                            ? view.getContext().getString(R.string.omnibox_empty_hint)
                             : null);
         } else if (SearchBoxProperties.VOICE_SEARCH_CLICK_CALLBACK == propertyKey) {
             voiceSearchButton.setOnClickListener(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
index 16147ba..5f9a032 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.segmentation_platform;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import android.os.Handler;
 import android.os.Looper;
 
@@ -16,6 +18,8 @@
 import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.bookmarks.BookmarkModel;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.CurrentTabObserver;
@@ -39,6 +43,7 @@
  * segmentation platform for on-demand model execution on page load triggers. Provides updated
  * button data to the toolbar when asked for it.
  */
+@NullMarked
 public class ContextualPageActionController {
     /**
      * The interface to be implemented by the individual feature backends to provide signals
@@ -60,17 +65,17 @@
          * @param tab The current tab for which the action was shown.
          * @param action Enum value of the action shown.
          */
-        default void onActionShown(Tab tab, @AdaptiveToolbarButtonVariant int action) {}
+        default void onActionShown(@Nullable Tab tab, @AdaptiveToolbarButtonVariant int action) {}
 
         @Override
         default void destroy() {}
     }
 
     private final ObservableSupplier<Profile> mProfileSupplier;
-    private final ObservableSupplier<Tab> mTabSupplier;
+    private final ObservableSupplier<@Nullable Tab> mTabSupplier;
     private final AdaptiveToolbarButtonController mAdaptiveToolbarButtonController;
-    private CurrentTabObserver mCurrentTabObserver;
-    private SignalAccumulator mSignalAccumulator;
+    private @Nullable CurrentTabObserver mCurrentTabObserver;
+    private @Nullable SignalAccumulator mSignalAccumulator;
     private BooleanSupplier mButtonVisibilitySupplier = () -> true;
 
     // The action provider backends.
@@ -86,7 +91,7 @@
      */
     public ContextualPageActionController(
             ObservableSupplier<Profile> profileSupplier,
-            ObservableSupplier<Tab> tabSupplier,
+            ObservableSupplier<@Nullable Tab> tabSupplier,
             AdaptiveToolbarButtonController adaptiveToolbarButtonController,
             Supplier<ShoppingService> shoppingServiceSupplier,
             Supplier<BookmarkModel> bookmarkModelSupplier) {
@@ -154,15 +159,16 @@
                     new DiscountsActionProvider(shoppingServiceSupplier));
         }
         if (AdaptiveToolbarFeatures.isTabGroupingPageActionEnabled()) {
-            Supplier<GroupSuggestionsButtonController> groupSuggestionButtonControllerSupplier =
-                    () -> {
-                        if (!mProfileSupplier.hasValue()
-                                || mProfileSupplier.get().isOffTheRecord()) {
-                            return null;
-                        }
-                        return GroupSuggestionsButtonControllerFactory.getForProfile(
-                                mProfileSupplier.get());
-                    };
+            Supplier<@Nullable GroupSuggestionsButtonController>
+                    groupSuggestionButtonControllerSupplier =
+                            () -> {
+                                if (!mProfileSupplier.hasValue()
+                                        || mProfileSupplier.get().isOffTheRecord()) {
+                                    return null;
+                                }
+                                return GroupSuggestionsButtonControllerFactory.getForProfile(
+                                        mProfileSupplier.get());
+                            };
             mActionProviders.put(
                     AdaptiveToolbarButtonVariant.TAB_GROUPING,
                     new TabGroupingActionProvider(groupSuggestionButtonControllerSupplier));
@@ -195,7 +201,7 @@
         mActionProviders.clear();
     }
 
-    private void activeTabChanged(Tab tab) {
+    private void activeTabChanged(@Nullable Tab tab) {
         // If the tab is loading or if it's going to load later then we'll also get a call to
         // onPageLoadFinished.
         if (tab != null && !tab.isLoading() && !tab.isFrozen()) {
@@ -224,6 +230,7 @@
         Tab tab = getValidActiveTab();
         if (tab == null) return;
         InputContext inputContext = new InputContext();
+        assumeNonNull(mSignalAccumulator);
         inputContext.addEntry(
                 Constants.CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING_INPUT,
                 ProcessedValue.fromFloat(
@@ -282,7 +289,7 @@
     }
 
     /** @return The active regular tab. Null for incognito. */
-    private Tab getValidActiveTab() {
+    private @Nullable Tab getValidActiveTab() {
         if (mProfileSupplier == null || mProfileSupplier.get().isOffTheRecord()) return null;
         Tab tab = mTabSupplier.get();
         if (tab == null || tab.isIncognito() || tab.isDestroyed()) return null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/DiscountsActionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/DiscountsActionProvider.java
index dd45e97..e948cde 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/DiscountsActionProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/DiscountsActionProvider.java
@@ -4,13 +4,17 @@
 
 package org.chromium.chrome.browser.segmentation_platform;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.components.commerce.core.ShoppingService;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 
 /** Provides Discounts signal for showing contextual page action for a given tab. */
+@NullMarked
 public class DiscountsActionProvider implements ContextualPageActionController.ActionProvider {
     private final Supplier<ShoppingService> mShoppingServiceSupplier;
 
@@ -35,7 +39,7 @@
                 tab.getUrl(),
                 (url, info) -> {
                     signalAccumulator.setSignal(
-                            AdaptiveToolbarButtonVariant.DISCOUNTS, !info.isEmpty());
+                            AdaptiveToolbarButtonVariant.DISCOUNTS, !assumeNonNull(info).isEmpty());
                 });
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceInsightsActionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceInsightsActionProvider.java
index 6d4c8a3..25f8aba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceInsightsActionProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceInsightsActionProvider.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.segmentation_platform;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
 import org.chromium.components.commerce.core.ShoppingService;
@@ -12,6 +14,7 @@
 import org.chromium.components.embedder_support.util.UrlUtilities;
 
 /** Provides price insights signal for showing contextual page action for a given tab. */
+@NullMarked
 public class PriceInsightsActionProvider implements ContextualPageActionController.ActionProvider {
     private final Supplier<ShoppingService> mShoppingServiceSupplier;
 
@@ -41,7 +44,7 @@
                 });
     }
 
-    private boolean hasPriceInsightsInfoData(PriceInsightsInfo info) {
+    private boolean hasPriceInsightsInfoData(@Nullable PriceInsightsInfo info) {
         return info != null
                 && !info.currencyCode.isEmpty()
                 && info.catalogHistoryPrices != null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProvider.java
index 74a9a20..87b589375 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProvider.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.segmentation_platform;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.bookmarks.BookmarkModel;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
@@ -13,6 +14,7 @@
 import org.chromium.components.embedder_support.util.UrlUtilities;
 
 /** Provides price tracking signal for showing contextual page action for a given tab. */
+@NullMarked
 public class PriceTrackingActionProvider implements ContextualPageActionController.ActionProvider {
     private final Supplier<ShoppingService> mShoppingServiceSupplier;
     private final Supplier<BookmarkModel> mBookmarkModelSupplier;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ReaderModeActionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ReaderModeActionProvider.java
index dc3ef7de..9f26c4d00 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ReaderModeActionProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ReaderModeActionProvider.java
@@ -178,7 +178,7 @@
     }
 
     @Override
-    public void onActionShown(Tab tab, @AdaptiveToolbarButtonVariant int action) {
+    public void onActionShown(@Nullable Tab tab, @AdaptiveToolbarButtonVariant int action) {
         if (tab == null || tab.isLoading()) return;
         final boolean isReaderMode =
                 action == AdaptiveToolbarButtonVariant.READER_MODE
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/TabGroupingActionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/TabGroupingActionProvider.java
index 96aae5d..dd920ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/TabGroupingActionProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/TabGroupingActionProvider.java
@@ -4,10 +4,13 @@
 
 package org.chromium.chrome.browser.segmentation_platform;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
+
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.app.tabwindow.TabWindowManagerSingleton;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab_group_suggestion.toolbar.GroupSuggestionsButtonController;
@@ -17,24 +20,25 @@
 @NullMarked
 public class TabGroupingActionProvider implements ContextualPageActionController.ActionProvider {
 
-    private final Supplier<GroupSuggestionsButtonController>
+    private final Supplier<@Nullable GroupSuggestionsButtonController>
             mGroupSuggestionsButtonControllerSupplier;
 
     public TabGroupingActionProvider(
-            Supplier<GroupSuggestionsButtonController> groupSuggestionsButtonController) {
+            Supplier<@Nullable GroupSuggestionsButtonController> groupSuggestionsButtonController) {
         mGroupSuggestionsButtonControllerSupplier = groupSuggestionsButtonController;
     }
 
     @Override
-    public void onActionShown(Tab tab, @AdaptiveToolbarButtonVariant int action) {
+    public void onActionShown(@Nullable Tab tab, @AdaptiveToolbarButtonVariant int action) {
         if (!mGroupSuggestionsButtonControllerSupplier.hasValue()) {
             return;
         }
 
+        var controller = assumeNonNull(mGroupSuggestionsButtonControllerSupplier.get());
         if (action == AdaptiveToolbarButtonVariant.TAB_GROUPING) {
-            mGroupSuggestionsButtonControllerSupplier.get().onButtonShown(tab);
+            controller.onButtonShown(tab);
         } else {
-            mGroupSuggestionsButtonControllerSupplier.get().onButtonHidden();
+            controller.onButtonHidden();
         }
     }
 
@@ -69,11 +73,10 @@
 
                     var windowId = TabWindowManagerSingleton.getInstance().getIdForWindow(activity);
 
+                    var controller = assumeNonNull(mGroupSuggestionsButtonControllerSupplier.get());
                     signalAccumulator.setSignal(
                             AdaptiveToolbarButtonVariant.TAB_GROUPING,
-                            mGroupSuggestionsButtonControllerSupplier
-                                    .get()
-                                    .shouldShowButton(tab, windowId));
+                            controller.shouldShowButton(tab, windowId));
                 });
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroidImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroidImpl.java
index f7f61da..77a48781 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroidImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroidImpl.java
@@ -297,6 +297,16 @@
     }
 
     @Override
+    public void requestKeyboardLock(boolean escKeyLocked) {
+        mDelegate.requestKeyboardLock(escKeyLocked);
+    }
+
+    @Override
+    public void cancelKeyboardLockRequest() {
+        mDelegate.cancelKeyboardLockRequest();
+    }
+
+    @Override
     public void navigationStateChanged(int flags) {
         RewindableIterator<TabObserver> observers = mTab.getTabObservers();
         while (observers.hasNext()) observers.next().onNavigationStateChanged();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessManager.java
index b5582bc2..402aad4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/ExclusiveAccessManager.java
@@ -83,6 +83,29 @@
                         mExclusiveAccessManagerAndroidNativePointer, nativeKeyEvent);
     }
 
+    /**
+     * EAM frontend for WebContentsDelegate to request keyboard lock
+     *
+     * @param webContents the WebContents that requested keyboard load
+     * @param escKeyLocked whether the escape key is to be locked.
+     */
+    public void requestKeyboardLock(WebContents webContents, boolean escKeyLocked) {
+        ExclusiveAccessManagerJni.get()
+                .requestKeyboardLock(
+                        mExclusiveAccessManagerAndroidNativePointer, webContents, escKeyLocked);
+    }
+
+    /**
+     * EAM frontend for WebContentsDelegate to cancel keyboard lock
+     *
+     * @param webContents the WebContents cancelling keyboard lock
+     */
+    public void cancelKeyboardLockRequest(WebContents webContents) {
+        ExclusiveAccessManagerJni.get()
+                .cancelKeyboardLockRequest(
+                        mExclusiveAccessManagerAndroidNativePointer, webContents);
+    }
+
     /** Cleanup function which should be called when owning object is destroyed. */
     @Override
     public void destroy() {
@@ -114,6 +137,14 @@
         boolean preHandleKeyboardEvent(
                 long nativeExclusiveAccessManagerAndroid, long nativeKeyEvent);
 
+        void requestKeyboardLock(
+                long nativeExclusiveAccessManagerAndroid,
+                WebContents webContents,
+                boolean escKeyLocked);
+
+        void cancelKeyboardLockRequest(
+                long nativeExclusiveAccessManagerAndroid, WebContents webContents);
+
         void destroy(long nativeExclusiveAccessManagerAndroid);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
index 7842e7ce..8c34eaf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
@@ -104,7 +104,7 @@
     }
 
     private void navigateAndObserve(final String url) throws Exception {
-        new TabLoadObserver(mActivityTestRule.getActivity().getActivityTab()).fullyLoadUrl(url);
+        new TabLoadObserver(mActivityTestRule.getActivityTab()).fullyLoadUrl(url);
 
         // Note: Omnibox does not present the scheme.
         mOmnibox.checkText(equalTo(expectedLocation(url)), null);
@@ -137,8 +137,7 @@
 
         // Loads the url.
         TabLoadObserver observer =
-                new TabLoadObserver(
-                        mActivityTestRule.getActivity().getActivityTab(), expectedTitle, null);
+                new TabLoadObserver(mActivityTestRule.getActivityTab(), expectedTitle, null);
         mOmnibox.sendKey(KeyEvent.KEYCODE_ENTER);
         observer.assertLoaded();
 
@@ -237,15 +236,12 @@
         navigateAndObserve(url1);
         mActivityTestRule.assertWaitForPageScaleFactorMatch(0.5f);
 
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
 
         DOMUtils.clickNode(tab.getWebContents(), "aboutLink");
         ChromeTabUtils.waitForTabPageLoaded(tab, url2);
         Assert.assertEquals(
-                "Desired Link not open",
-                url2,
-                ChromeTabUtils.getUrlStringOnUiThread(
-                        mActivityTestRule.getActivity().getActivityTab()));
+                "Desired Link not open", url2, ChromeTabUtils.getUrlStringOnUiThread(tab));
     }
 
     /** Test 'Request Desktop Site' option properly affects UA client hints */
@@ -324,7 +320,7 @@
             throws Exception {
         String url1 = mTestServer.getURL(setHeaderString);
         String url2 = mTestServer.getURL(echoHeaderString);
-        final Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mActivityTestRule.getActivityTab();
 
         navigateAndObserve(url1);
         ChromeTabUtils.waitForTabPageLoaded(tab, url1);
@@ -352,7 +348,7 @@
         // TODO(crbug.com/40153192): Move EchoCriticalHeader request handler here when
         // implemented
         String url = mTestServer.getURL("/echocriticalheader");
-        final Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mActivityTestRule.getActivityTab();
         navigateAndObserve(url);
         ThreadUtils.runOnUiThreadBlocking(
                 () ->
@@ -390,15 +386,14 @@
                         Assert.assertEquals(url2, newUrl.getSpec());
                     }
                 };
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(() -> tab.addObserver(onPageLoadStartedObserver));
         DOMUtils.clickNode(tab.getWebContents(), "aboutLink");
         ChromeTabUtils.waitForTabPageLoaded(tab, url2);
         Assert.assertEquals(
                 "Desired Link not open",
                 url2,
-                ChromeTabUtils.getUrlStringOnUiThread(
-                        mActivityTestRule.getActivity().getActivityTab()));
+                ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab()));
     }
 
     /** Test re-direct functionality for a web-page. */
@@ -416,7 +411,7 @@
                 () -> {
                     Criteria.checkThat(
                             ChromeTabUtils.getUrlStringOnUiThread(
-                                    mActivityTestRule.getActivity().getActivityTab()),
+                                    mActivityTestRule.getActivityTab()),
                             Matchers.is(redirectedUrl));
                 });
     }
@@ -453,8 +448,7 @@
 
         // We should start on the homepage, which is something other than our test page.
         String originalUrl =
-                ChromeTabUtils.getUrlStringOnUiThread(
-                        mActivityTestRule.getActivity().getActivityTab());
+                ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab());
         Criteria.checkThat(originalUrl, Matchers.not(targetUrl));
 
         typeInOmniboxAndNavigate(initialUrl, null);
@@ -464,7 +458,7 @@
                 () -> {
                     Criteria.checkThat(
                             ChromeTabUtils.getUrlStringOnUiThread(
-                                    mActivityTestRule.getActivity().getActivityTab()),
+                                    mActivityTestRule.getActivityTab()),
                             Matchers.is(targetUrl));
                 });
 
@@ -475,7 +469,6 @@
         // TODO(changwan): figure out why we cannot go back on this test.
         int index =
                 mActivityTestRule
-                        .getActivity()
                         .getActivityTab()
                         .getWebContents()
                         .getNavigationController()
@@ -483,7 +476,6 @@
         Assert.assertEquals(1, index);
         String previousNavigationUrl =
                 mActivityTestRule
-                        .getActivity()
                         .getActivityTab()
                         .getWebContents()
                         .getNavigationController()
@@ -568,8 +560,7 @@
                                     + "%d.",
                             i),
                     urls[1],
-                    ChromeTabUtils.getUrlStringOnUiThread(
-                            mActivityTestRule.getActivity().getActivityTab()));
+                    ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab()));
 
             TouchCommon.singleClickView(
                     mActivityTestRule.getActivity().findViewById(R.id.back_button));
@@ -581,8 +572,7 @@
                                     + "%d.",
                             i),
                     urls[0],
-                    ChromeTabUtils.getUrlStringOnUiThread(
-                            mActivityTestRule.getActivity().getActivityTab()));
+                    ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab()));
 
             TouchCommon.singleClickView(
                     mActivityTestRule.getActivity().findViewById(R.id.forward_button));
@@ -594,8 +584,7 @@
                                     + "%d.",
                             i),
                     urls[1],
-                    ChromeTabUtils.getUrlStringOnUiThread(
-                            mActivityTestRule.getActivity().getActivityTab()));
+                    ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab()));
 
             TouchCommon.singleClickView(
                     mActivityTestRule.getActivity().findViewById(R.id.forward_button));
@@ -607,8 +596,7 @@
                                     + "%d.",
                             i),
                     urls[2],
-                    ChromeTabUtils.getUrlStringOnUiThread(
-                            mActivityTestRule.getActivity().getActivityTab()));
+                    ChromeTabUtils.getUrlStringOnUiThread(mActivityTestRule.getActivityTab()));
         }
 
         for (int i = 0; i < repeats; i++) {
@@ -639,7 +627,7 @@
         };
         navigateAndObserve(urls[0]);
 
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
         // Record FORWARD if the first gesture triggered by gesture and second gesture is FORWARD.
         navigateAndObserve(urls[1]);
         ThreadUtils.runOnUiThreadBlocking(tab::goBack);
@@ -683,7 +671,7 @@
         };
         navigateAndObserve(urls[0]);
 
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
         // Record FORWARD if the first gesture triggered by gesture and second gesture is FORWARD.
         navigateAndObserve(urls[1]);
         ThreadUtils.runOnUiThreadBlocking(tab::goBack);
@@ -749,7 +737,7 @@
             mTestServer.getURL("/chrome/test/data/android/navigate/two.html"),
         };
         navigateAndObserve(urls[0]);
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
 
         // Not record when the first navigation is not triggered by gesture.
         HistogramWatcher watcher =
@@ -903,7 +891,7 @@
                         }
                     }
                 };
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
+        Tab tab = mActivityTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(() -> tab.addObserver(onPageLoadStartedObserver));
         DOMUtils.clickNode(tab.getWebContents(), "rendererInitiated");
         ChromeTabUtils.waitForTabPageLoaded(tab, finalUrl);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ToolbarSwipeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ToolbarSwipeTest.java
index c9074d0..a0a6c383 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ToolbarSwipeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ToolbarSwipeTest.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser;
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+import static org.chromium.chrome.test.util.ChromeTabUtils.getIndexOnUiThread;
+import static org.chromium.chrome.test.util.ChromeTabUtils.getTabCountOnUiThread;
 import static org.chromium.ui.test.util.ViewUtils.createMotionEvent;
 
 import android.content.pm.ActivityInfo;
@@ -144,7 +146,8 @@
 
         final TabModel tabModel =
                 mActivityTestRule.getActivity().getTabModelSelector().getModel(false);
-        Assert.assertEquals("Incorrect tab index after first swipe.", 1, tabModel.index());
+        Assert.assertEquals(
+                "Incorrect tab index after first swipe.", 1, getIndexOnUiThread(tabModel));
 
         runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, true);
     }
@@ -160,7 +163,8 @@
 
         final TabModel tabModel =
                 mActivityTestRule.getActivity().getTabModelSelector().getModel(true);
-        Assert.assertEquals("Incorrect tab index after first swipe.", 1, tabModel.index());
+        Assert.assertEquals(
+                "Incorrect tab index after first swipe.", 1, getIndexOnUiThread(tabModel));
 
         runToolbarSideSwipeTestOnCurrentModel(ScrollDirection.RIGHT, 0, true);
     }
@@ -177,7 +181,8 @@
         if (incognito) {
             // If incognito, there is no default tab, so open a new one and switch to it.
             mActivityTestRule.loadUrlInNewTab(generateSolidColorUrl("#00ff00"), true);
-            mActivityTestRule.getActivity().getTabModelSelector().selectModel(true);
+            ThreadUtils.runOnUiThreadBlocking(
+                    () -> mActivityTestRule.getActivity().getTabModelSelector().selectModel(true));
         } else {
             // If not incognito, use the tab the test started on.
             mActivityTestRule.loadUrl(generateSolidColorUrl("#00ff00"));
@@ -198,8 +203,9 @@
                 "Incorrect model selected.",
                 incognito,
                 tabModelSelector.getCurrentModel().isIncognito());
-        Assert.assertEquals("Incorrect starting index.", selectedTab, tabModel.index());
-        Assert.assertEquals("Incorrect tab count.", useTwoTabs ? 2 : 1, tabModel.getCount());
+        Assert.assertEquals("Incorrect starting index.", selectedTab, getIndexOnUiThread(tabModel));
+        Assert.assertEquals(
+                "Incorrect tab count.", useTwoTabs ? 2 : 1, getTabCountOnUiThread(tabModel));
     }
 
     private void runToolbarSideSwipeTestOnCurrentModel(
@@ -207,7 +213,9 @@
             throws TimeoutException {
         final CallbackHelper selectCallback = new CallbackHelper();
         final ChromeTabbedActivity activity = mActivityTestRule.getActivity();
-        final int id = activity.getCurrentTabModel().getTabAt(finalIndex).getId();
+        final int id =
+                ThreadUtils.runOnUiThreadBlocking(
+                        () -> activity.getCurrentTabModel().getTabAt(finalIndex).getId());
         final TabModelSelectorTabModelObserver observer =
                 ThreadUtils.runOnUiThreadBlocking(
                         () -> {
@@ -250,7 +258,7 @@
         Assert.assertEquals(
                 "Index after toolbar side swipe is incorrect",
                 finalIndex,
-                activity.getCurrentTabModel().index());
+                getIndexOnUiThread(activity.getCurrentTabModel()));
     }
 
     private void performToolbarSideSwipe(@ScrollDirection int direction) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewTransitionPixelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewTransitionPixelTest.java
index 9ab894f..4eb56c6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewTransitionPixelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewTransitionPixelTest.java
@@ -281,6 +281,7 @@
     @Test
     @MediumTest
     @Feature({"RenderTest"})
+    @DisabledTest(message = "crbug.com/435692206")
     public void testVirtualKeyboardResizesVisual() throws Throwable {
         startKeyboardTest(VirtualKeyboardMode.RESIZES_VISUAL);
 
@@ -323,6 +324,7 @@
     @Test
     @MediumTest
     @Feature({"RenderTest"})
+    @DisabledTest(message = "crbug.com/435692206")
     public void testVirtualKeyboardResizesContent() throws Throwable {
         doTestVirtualKeyboardResizesContent();
     }
@@ -338,6 +340,7 @@
     @MinAndroidSdkLevel(VERSION_CODES.R)
     @EnableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION)
     @Restriction(DeviceFormFactor.TABLET_OR_DESKTOP)
+    @DisabledTest(message = "crbug.com/435692206")
     public void testVirtualKeyboardResizesContent_TSLOEnabled() throws Throwable {
         // Simulate fullscreen window behavior in an environment that supports Android V custom app
         // header APIs.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewportTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewportTestUtils.java
index a1b2b15..0115bb5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewportTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewportTestUtils.java
@@ -68,8 +68,7 @@
         // animation has completed is flaky.
         waitForBrowserControlsState(/* shown= */ true);
 
-        FullscreenManagerTestUtils.waitForPageToBeScrollable(
-                mActivityTestRule.getActivity().getActivityTab());
+        FullscreenManagerTestUtils.waitForPageToBeScrollable(mActivityTestRule.getActivityTab());
         waitForFramePresented();
         int initialPageHeight = getPageInnerHeightPx();
         int initialBottomMargin = getBottomMargins();
@@ -182,6 +181,6 @@
     }
 
     private WebContents getWebContents() {
-        return mActivityTestRule.getActivity().getActivityTab().getWebContents();
+        return mActivityTestRule.getWebContents();
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
index 2919d4f..42ee9163 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -219,7 +219,7 @@
         mTestUrl = mTestServer.getURL(TEST_PATH);
         deleteTestFiles();
         sDownloadTestRule.loadUrl(mTestUrl);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         CriteriaHelper.pollUiThread(() -> tab.isUserInteractable() && !tab.isLoading());
         setupLensChipDelegate();
         DownloadUtils.setIsDownloadRestrictedByPolicyForTesting(false);
@@ -250,7 +250,7 @@
         // Clear the clipboard.
         Clipboard.getInstance().setText("");
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow DiskWrites temporarily in main thread to avoid
         // violation during copying under emulator environment.
         try (CloseableOnMainThread ignored = CloseableOnMainThread.StrictMode.allowDiskWrites()) {
@@ -277,7 +277,7 @@
         // Clear the clipboard.
         Clipboard.getInstance().setText("");
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow DiskWrites temporarily in main thread to avoid
         // violation during copying under emulator environment.
         try (CloseableOnMainThread ignored = CloseableOnMainThread.StrictMode.allowDiskWrites()) {
@@ -296,7 +296,7 @@
     @MediumTest
     @Feature({"Browser"})
     public void testCopyImageLinkCopiesLinkURL() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow DiskWrites temporarily in main thread to avoid
         // violation during copying under emulator environment.
         try (CloseableOnMainThread ignored = CloseableOnMainThread.StrictMode.allowDiskWrites()) {
@@ -346,7 +346,7 @@
         ContextMenuUtils.selectContextMenuItem(
                 InstrumentationRegistry.getInstrumentation(),
                 sDownloadTestRule.getActivity(),
-                sDownloadTestRule.getActivity().getActivityTab(),
+                sDownloadTestRule.getActivityTab(),
                 "testImage",
                 R.id.contextmenu_open_image_in_new_tab);
 
@@ -381,7 +381,7 @@
         ContextMenuUtils.selectContextMenuItem(
                 InstrumentationRegistry.getInstrumentation(),
                 sDownloadTestRule.getActivity(),
-                sDownloadTestRule.getActivity().getActivityTab(),
+                sDownloadTestRule.getActivityTab(),
                 "testImage",
                 R.id.contextmenu_open_image_in_ephemeral_tab);
 
@@ -400,7 +400,7 @@
 
     private void checkOpenImageInNewTab(String domId, final String expectedPath)
             throws TimeoutException {
-        final Tab activityTab = sDownloadTestRule.getActivity().getActivityTab();
+        final Tab activityTab = sDownloadTestRule.getActivityTab();
 
         final CallbackHelper newTabCallback = new CallbackHelper();
         final AtomicReference<Tab> newTab = new AtomicReference<>();
@@ -455,7 +455,7 @@
     @Test
     @MediumTest
     public void testDismissContextMenuOnBack() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
         Assert.assertNotNull("Context menu was not properly created", mMenuCoordinator);
         CriteriaHelper.pollUiThread(
@@ -478,7 +478,7 @@
     @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_TRANSLATE_WITH_GOOGLE_LENS})
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     public void testLensTranslateChipNotShowingIfNotEnabled() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
 
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
@@ -496,7 +496,7 @@
     @Feature({"Browser"})
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     public void testSelectLensTranslateChip() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
 
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
@@ -522,7 +522,7 @@
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     @DisabledTest(message = "https://crbug.com/430777988")
     public void testLensChipNotShowingAfterMenuDismissed() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
 
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
@@ -555,7 +555,7 @@
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     @DisabledTest(message = "https://crbug.com/430777988")
     public void testDismissContextMenuOnClickLensTranslateChipEnabled() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
         // Needs to run on UI thread so creation happens on same thread as dismissal.
         ThreadUtils.runOnUiThreadBlocking(
@@ -585,7 +585,7 @@
     @Feature({"Browser"})
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     public void testSelectLensShoppingChip() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
 
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
@@ -611,7 +611,7 @@
     @DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU})
     @DisabledTest(message = "https://crbug.com/430777988")
     public void testDismissContextMenuOnClickShoppingLensChipEnabled() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
         // Needs to run on UI thread so creation happens on same thread as dismissal.
         ThreadUtils.runOnUiThreadBlocking(
@@ -640,7 +640,7 @@
     @MediumTest
     @DisabledTest(message = "https://crbug.com/430777988")
     public void testDismissContextMenuOnClick() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
         Assert.assertNotNull("Context menu was not properly created", mMenuCoordinator);
         CriteriaHelper.pollUiThread(
@@ -665,7 +665,7 @@
     @Test
     @MediumTest
     public void testCopyEmailAddress() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow all thread policies temporarily in main thread to avoid
         // DiskWrite and UnBufferedIo violations during copying under
         // emulator environment.
@@ -688,7 +688,7 @@
     @Test
     @MediumTest
     public void testCopyTelNumber() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow DiskWrites temporarily in main thread to avoid
         // violation during copying under emulator environment.
         try (CloseableOnMainThread ignored = CloseableOnMainThread.StrictMode.allowDiskWrites()) {
@@ -710,7 +710,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testSavePageLongPress() throws TimeoutException {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         int callCount = sDownloadTestRule.getChromeDownloadCallCount();
         ContextMenuUtils.selectContextMenuItem(
                 InstrumentationRegistry.getInstrumentation(),
@@ -731,7 +731,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testSavePageRightClick() throws TimeoutException {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         int callCount = sDownloadTestRule.getChromeDownloadCallCount();
         ContextMenuUtils.selectContextMenuItemFromRightClick(
                 InstrumentationRegistry.getInstrumentation(),
@@ -769,7 +769,7 @@
             throws TimeoutException, SecurityException, IOException {
         DownloadUtils.setIsDownloadRestrictedByPolicyForTesting(true);
         int downloadCount = sDownloadTestRule.getAllDownloads().size();
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
 
         // Click should not trigger any download
@@ -797,7 +797,7 @@
     public void testOpenLinksInNewTabsAndVerifyTabIndexOrdering() throws TimeoutException {
         TabModel tabModel = sDownloadTestRule.getActivity().getCurrentTabModel();
         int numOpenedTabs = tabModel.getCount();
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ContextMenuUtils.selectContextMenuItem(
                 InstrumentationRegistry.getInstrumentation(),
                 sDownloadTestRule.getActivity(),
@@ -847,8 +847,7 @@
         // Verify the Url is still the same of Parent page.
         Assert.assertEquals(
                 mTestUrl,
-                ChromeTabUtils.getUrlStringOnUiThread(
-                        sDownloadTestRule.getActivity().getActivityTab()));
+                ChromeTabUtils.getUrlStringOnUiThread(sDownloadTestRule.getActivityTab()));
 
         // Verify that the background tabs were opened in the expected order.
         String newTabUrl =
@@ -869,7 +868,7 @@
     @DisableIf.Device(DeviceFormFactor.ONLY_TABLET) // https://crbug.com/338969612
     @Feature({"Browser", "ContextMenu"})
     public void testContextMenuRetrievesLinkOptions() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testLink");
 
         Integer[] expectedItems = {
@@ -897,7 +896,7 @@
     public void testContextMenuRetrievesImageOptions() throws TimeoutException {
         LensUtils.setFakePassableLensEnvironmentForTesting(true);
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
 
         Integer[] expectedItems = {
@@ -919,7 +918,7 @@
     @Policies.Add({@Policies.Item(key = "DefaultSearchProviderEnabled", string = "false")})
     public void testContextMenuRetrievesImageOptions_NoDefaultSearchEngine()
             throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
 
         Integer[] expectedItems = {
@@ -942,7 +941,7 @@
             throws TimeoutException {
         LensUtils.setFakePassableLensEnvironmentForTesting(true);
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImage");
 
         // Search with Google Lens is only supported when Google is the default search provider.
@@ -965,7 +964,7 @@
     public void testContextMenuRetrievesImageLinkOptions() throws TimeoutException {
         LensUtils.setFakePassableLensEnvironmentForTesting(true);
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "testImageLink");
 
         Integer[] expectedItems = {
@@ -993,7 +992,7 @@
     @SmallTest
     @Feature({"Browser", "ContextMenu"})
     public void testContextMenuRetrievesVideoOptions() throws TimeoutException {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         DOMUtils.clickNode(
                 sDownloadTestRule.getActivity().getCurrentWebContents(), "videoDOMElement");
         mMenuCoordinator = ContextMenuUtils.openContextMenu(tab, "videoDOMElement");
@@ -1006,7 +1005,7 @@
     @SmallTest
     @Feature({"Browser", "ContextMenu"})
     public void testSearchImageWithGoogleLensMenuItemName() throws Throwable {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
 
         LensUtils.setFakePassableLensEnvironmentForTesting(true);
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
@@ -1044,7 +1043,7 @@
         Clipboard.getInstance().setText("");
 
         hardcodeTestImageForSharing(TEST_GIF_IMAGE_FILE_EXTENSION);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow all thread policies temporarily in main thread to avoid
         // DiskWrite and UnBufferedIo violations during copying under
         // emulator environment.
@@ -1091,7 +1090,7 @@
         Clipboard.getInstance().setText("");
 
         hardcodeTestImageForSharing(TEST_GIF_IMAGE_FILE_EXTENSION);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Allow all thread policies temporarily in main thread to avoid
         // DiskWrite and UnBufferedIo violations during copying under
         // emulator environment.
@@ -1117,7 +1116,7 @@
         when(mItemDelegate.isIncognito()).thenReturn(false);
         when(mItemDelegate.getPageTitle()).thenReturn("");
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ContextMenuHelper contextMenuHelper =
                 ContextMenuHelper.createForTesting(0, tab.getWebContents());
         ContextMenuParams params =
@@ -1176,7 +1175,7 @@
     public void testShareImage() throws Exception {
         hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION);
 
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         // Set share delegate before triggering context menu, so the mocked share delegate is used.
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
@@ -1221,7 +1220,7 @@
     @Test
     @SmallTest
     public void testShareLink() throws Exception {
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
 
         // Set share delegate before triggering context menu, so the mocked share delegate is used.
         ThreadUtils.runOnUiThreadBlocking(
@@ -1265,7 +1264,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testSharePageLongPress() throws Exception {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     // Set share delegate before triggering context menu, so the mocked share
@@ -1312,7 +1311,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testSharePageRightClick() throws Exception {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     // Set share delegate before triggering context menu, so the mocked share
@@ -1359,7 +1358,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testPrintPageLongPress() throws Exception {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 // Set printing controller to use the mock instance.
                 () -> {
@@ -1386,7 +1385,7 @@
     @DisableFeatures({UiAndroidFeatures.ANDROID_WINDOW_OCCLUSION})
     public void testPrintPageRightClick() throws Exception {
         DeviceInput.setSupportsPrecisionPointerForTesting(true);
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 // Set printing controller to use the mock instance.
                 () -> {
@@ -1474,7 +1473,7 @@
             String mediaDOMElement, int saveMenuID, String expectedFilename)
             throws TimeoutException, SecurityException, IOException {
         // Select "save [image/video]" in that menu.
-        Tab tab = sDownloadTestRule.getActivity().getActivityTab();
+        Tab tab = sDownloadTestRule.getActivityTab();
         int callCount = sDownloadTestRule.getChromeDownloadCallCount();
         ContextMenuUtils.selectContextMenuItem(
                 InstrumentationRegistry.getInstrumentation(),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
index bf4b735..46f4901e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
@@ -523,8 +523,7 @@
      * @param nodeId A string containing the node ID.
      */
     public void longPressNodeWithoutWaiting(String nodeId) throws TimeoutException {
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
-        DOMUtils.longPressNode(tab.getWebContents(), nodeId);
+        DOMUtils.longPressNode(mActivityTestRule.getWebContents(), nodeId);
     }
 
     /**
@@ -593,8 +592,7 @@
      */
     public long longPressNodeWithoutUp(String nodeId) throws TimeoutException {
         long downTime = SystemClock.uptimeMillis();
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
-        DOMUtils.longPressNodeWithoutUp(tab.getWebContents(), nodeId, downTime);
+        DOMUtils.longPressNodeWithoutUp(mActivityTestRule.getWebContents(), nodeId, downTime);
         waitForSelectActionBarVisible();
         waitForPanelToPeek();
         return downTime;
@@ -616,9 +614,9 @@
 
         // Drag to the specified position by a DOM node id.
         int stepCount = 100;
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
-        DOMUtils.dragNodeTo(tab.getWebContents(), startNodeId, endNodeId, stepCount, downTime);
-        DOMUtils.dragNodeEnd(tab.getWebContents(), endNodeId, downTime);
+        WebContents webContents = mActivityTestRule.getWebContents();
+        DOMUtils.dragNodeTo(webContents, startNodeId, endNodeId, stepCount, downTime);
+        DOMUtils.dragNodeEnd(webContents, endNodeId, downTime);
 
         // Make sure the selection controller knows we did a drag.
         // TODO(donnd): figure out how to reliably simulate a drag on all platforms.
@@ -636,8 +634,7 @@
      * @param nodeId A string containing the node ID.
      */
     public void clickNode(String nodeId) throws TimeoutException {
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
-        DOMUtils.clickNode(tab.getWebContents(), nodeId);
+        DOMUtils.clickNode(mActivityTestRule.getWebContents(), nodeId);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarButtonsViewBinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarButtonsViewBinderTest.java
index 852d185..6cf3ace2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarButtonsViewBinderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarButtonsViewBinderTest.java
@@ -32,7 +32,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseActivityTestRule;
@@ -61,6 +62,8 @@
 @Batch(Batch.UNIT_TESTS)
 @Features.EnableFeatures(ChromeFeatureList.CCT_TOOLBAR_REFACTOR)
 public class CustomTabToolbarButtonsViewBinderTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public BaseActivityTestRule<BlankUiTestActivity> mActivityTestRule =
             new BaseActivityTestRule<>(BlankUiTestActivity.class);
@@ -75,7 +78,6 @@
 
     @Before
     public void setUp() throws ExecutionException {
-        MockitoAnnotations.initMocks(this);
         mActivityTestRule.launchActivity(null);
         mActivity = mActivityTestRule.getActivity();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java
index b6f734a86..4bbdc081 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java
@@ -25,6 +25,7 @@
 import org.chromium.base.test.util.AdvancedMockContext;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -135,9 +136,7 @@
                     mNotification =
                             NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                             ChromeChannelDefinitions.ChannelId.DOWNLOADS)
-                                    .setSmallIcon(
-                                            org.chromium.chrome.R.drawable
-                                                    .ic_file_download_white_24dp)
+                                    .setSmallIcon(R.drawable.ic_file_download_white_24dp)
                                     .setContentTitle(FAKE_NOTIFICATION_CHANNEL)
                                     .setContentText(FAKE_NOTIFICATION_CHANNEL)
                                     .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
index 9100335..39f74c6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
@@ -22,6 +22,7 @@
 
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -100,7 +101,7 @@
         mNotification =
                 NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                 ChromeChannelDefinitions.ChannelId.DOWNLOADS)
-                        .setSmallIcon(org.chromium.chrome.R.drawable.ic_file_download_white_24dp)
+                        .setSmallIcon(R.drawable.ic_file_download_white_24dp)
                         .setContentTitle("fakeContentTitle")
                         .setContentText("fakeContentText")
                         .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadUserInitiatedTaskManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadUserInitiatedTaskManagerTest.java
index 2c11d01..028e090 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadUserInitiatedTaskManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadUserInitiatedTaskManagerTest.java
@@ -25,6 +25,7 @@
 import org.chromium.base.test.util.AdvancedMockContext;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -75,9 +76,7 @@
                     mNotification =
                             NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                             ChromeChannelDefinitions.ChannelId.DOWNLOADS)
-                                    .setSmallIcon(
-                                            org.chromium.chrome.R.drawable
-                                                    .ic_file_download_white_24dp)
+                                    .setSmallIcon(R.drawable.ic_file_download_white_24dp)
                                     .setContentTitle(FAKE_NOTIFICATION_CHANNEL)
                                     .setContentText(FAKE_NOTIFICATION_CHANNEL)
                                     .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
index 9eca2a8a..6f92687 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -510,7 +510,7 @@
         final CallbackHelper newTabCallback = new CallbackHelper();
         final CallbackHelper loadCallback = new CallbackHelper();
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
         final Holder<@Nullable Tab> latestTabHolder = new Holder<>(null);
 
         AtomicReference<OverrideUrlLoadingResult> lastResultValue = new AtomicReference<>();
@@ -899,7 +899,7 @@
     public void testNavigationFromXHRCallbackAndLostActivationLongTimeout() throws Exception {
         mTabbedActivityTestRule.startOnBlankPage();
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> RedirectHandlerTabHelper.swapHandlerForTesting(tab, mSpyRedirectHandler));
         // This is a little fragile to code changes, but better than waiting 15 real seconds.
@@ -960,7 +960,7 @@
         String originalUrl =
                 getSubframeNavigationUrl(subframeUrl, NavigationType.SELF, SandboxType.NONE);
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper subframeRedirect = new CallbackHelper();
         EmptyTabObserver observer =
@@ -1216,7 +1216,7 @@
         String redirectUrl = mTestServer.getURL(HELLO_PAGE);
         mTabbedActivityTestRule.startOnBlankPage();
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper subframeExternalProtocol = new CallbackHelper();
         final CallbackHelper subframeRedirect = new CallbackHelper();
@@ -1342,18 +1342,14 @@
         CriteriaHelper.pollUiThread(
                 () -> {
                     Criteria.checkThat(
-                            mTabbedActivityTestRule
-                                    .getActivity()
-                                    .getActivityTab()
-                                    .getUrl()
-                                    .getSpec(),
+                            mTabbedActivityTestRule.getActivityTab().getUrl().getSpec(),
                             Matchers.is(mTestServer.getURL(HELLO_PAGE)));
                 });
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     Assert.assertTrue(
                             RedirectHandlerTabHelper.getOrCreateHandlerFor(
-                                            mTabbedActivityTestRule.getActivity().getActivityTab())
+                                            mTabbedActivityTestRule.getActivityTab())
                                     .shouldNotOverrideUrlLoading());
                 });
     }
@@ -1445,7 +1441,7 @@
         // This test uses the back/forward cache, so return early if it's not enabled.
         if (!ChromeFeatureList.isEnabled(ChromeFeatureList.BACK_FORWARD_CACHE)) return;
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final RedirectHandler spyHandler =
                 Mockito.spy(
@@ -1502,7 +1498,7 @@
     public void testClearRedirectHandlerOnPageActivation() throws Exception {
         mTabbedActivityTestRule.startOnBlankPage();
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper prerenderFinishCallback = new CallbackHelper();
         WebContentsObserver observer =
@@ -1578,7 +1574,7 @@
     public void testNavigationFromFencedFrame() throws Exception {
         mTabbedActivityTestRule.startOnBlankPage();
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper frameFinishCallback = new CallbackHelper();
         WebContentsObserver observer =
@@ -1766,7 +1762,6 @@
                     Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(1));
                     Criteria.checkThat(
                             mTabbedActivityTestRule
-                                    .getActivity()
                                     .getActivityTab()
                                     .getUrl()
                                     .getSpec(),
@@ -1868,7 +1863,7 @@
 
         mCustomTabActivityRule.startCustomTabActivityWithIntent(intent);
 
-        final Tab tab = mCustomTabActivityRule.getActivity().getActivityTab();
+        final Tab tab = mCustomTabActivityRule.getActivityTab();
         ThreadUtils.runOnUiThreadBlocking(
                 () -> RedirectHandlerTabHelper.swapHandlerForTesting(tab, mSpyRedirectHandler));
 
@@ -1928,7 +1923,7 @@
         String originalUrl =
                 getSubframeNavigationUrl(subframeTarget, NavigationType.SELF, SandboxType.NONE);
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper subframeRedirect = new CallbackHelper();
         EmptyTabObserver observer =
@@ -1979,7 +1974,7 @@
         String originalUrl =
                 getSubframeNavigationUrl(subframeUrl, NavigationType.SELF, SandboxType.NONE);
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final CallbackHelper subframeRedirect = new CallbackHelper();
         EmptyTabObserver observer =
@@ -2019,7 +2014,6 @@
                         Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(1));
                         Criteria.checkThat(
                                 mTabbedActivityTestRule
-                                        .getActivity()
                                         .getActivityTab()
                                         .getUrl()
                                         .getSpec(),
@@ -2182,7 +2176,7 @@
         String originalUrl =
                 getSubframeNavigationUrl(subframeTarget, NavigationType.BLANK, SandboxType.NONE);
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final AtomicInteger navCount = new AtomicInteger(0);
         EmptyTabObserver observer =
@@ -2235,7 +2229,7 @@
         String originalUrl =
                 getSubframeNavigationUrl(subframeTarget, NavigationType.BLANK, sandboxType);
 
-        final Tab tab = mTabbedActivityTestRule.getActivity().getActivityTab();
+        final Tab tab = mTabbedActivityTestRule.getActivityTab();
 
         final AtomicInteger navCount = new AtomicInteger(0);
         EmptyTabObserver observer =
@@ -2271,7 +2265,7 @@
         // final URL is the subframe's target.
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    Tab newTab = mTabbedActivityTestRule.getActivity().getActivityTab();
+                    Tab newTab = mTabbedActivityTestRule.getActivityTab();
                     Assert.assertEquals(subframeTarget, newTab.getUrl().getSpec());
                     Assert.assertFalse(newTab.getWebContents().isLoading());
                 });
@@ -2315,7 +2309,6 @@
                     Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(0));
                     Criteria.checkThat(
                             mTabbedActivityTestRule
-                                    .getActivity()
                                     .getActivityTab()
                                     .getUrl()
                                     .getSpec(),
@@ -2409,15 +2402,16 @@
     private ChromeActivity launchTwaAndClick(String url) throws TimeoutException {
         launchTwa("com.foo.bar", url);
         ChromeActivity activity = mCustomTabActivityRule.getActivity();
+        Tab tab = activity.getActivityTab();
 
-        Assert.assertTrue(activity.getActivityTab().isTabInPWA());
-        Assert.assertFalse(activity.getActivityTab().getWebContents().hasOpener());
+        Assert.assertTrue(tab.isTabInPWA());
+        Assert.assertFalse(tab.getWebContents().hasOpener());
 
         ChromeTabbedActivity newActivity =
                 ApplicationTestUtils.waitForActivityWithClass(
                         ChromeTabbedActivity.class,
                         Stage.STARTED,
-                        () -> TouchCommon.singleClickView(activity.getActivityTab().getView()));
+                        () -> TouchCommon.singleClickView(tab.getView()));
 
         ApplicationTestUtils.waitForActivityState(newActivity, Stage.RESUMED);
 
@@ -2442,8 +2436,9 @@
                                 NAVIGATION_FROM_TARGET_BLANK_REL_OPENER_LINK,
                                 "https://example.com"));
 
-        Assert.assertFalse(newActivity.getActivityTab().isTabInPWA());
-        Assert.assertTrue(newActivity.getActivityTab().getWebContents().hasOpener());
+        Tab tab = ThreadUtils.runOnUiThreadBlocking(newActivity::getActivityTab);
+        Assert.assertFalse(tab.isTabInPWA());
+        Assert.assertTrue(tab.getWebContents().hasOpener());
     }
 
     @Test
@@ -2456,8 +2451,9 @@
                 launchTwaAndClick(
                         getUrlWithParam(NAVIGATION_FROM_TARGET_BLANK_LINK, "https://example.com"));
 
-        Assert.assertFalse(newActivity.getActivityTab().isTabInPWA());
-        Assert.assertFalse(newActivity.getActivityTab().getWebContents().hasOpener());
+        Tab tab = ThreadUtils.runOnUiThreadBlocking(newActivity::getActivityTab);
+        Assert.assertFalse(tab.isTabInPWA());
+        Assert.assertFalse(tab.getWebContents().hasOpener());
     }
 
     @Test
@@ -2472,10 +2468,10 @@
                         mTestServer.getURL(HELLO_PAGE));
 
         launchTwa("com.foo.bar", url);
-        ChromeActivity activity = mCustomTabActivityRule.getActivity();
 
-        Assert.assertTrue(activity.getActivityTab().isTabInPWA());
-        Assert.assertFalse(activity.getActivityTab().getWebContents().hasOpener());
+        Tab tab = mCustomTabActivityRule.getActivityTab();
+        Assert.assertTrue(tab.isTabInPWA());
+        Assert.assertFalse(tab.getWebContents().hasOpener());
     }
 
     private void doTestInitialIntentToApp(boolean allowInitialIntentToLeave) throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
index fcbe451..c97b5de 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
@@ -108,7 +108,7 @@
     @Before
     public void setUp() {
         mActivityTestRule.startOnBlankPage();
-        mTab = mActivityTestRule.getActivity().getActivityTab();
+        mTab = mActivityTestRule.getActivityTab();
         PictureInPictureActivityJni.setInstanceForTesting(mNativeMock);
         mOriginalHelper = PictureInPictureActivity.setLaunchIntoPipHelper(mLaunchIntoPipHelper);
         when(mNativeMock.onActivityStart(eq(mNativeWindowToken), any(), any()))
@@ -387,7 +387,7 @@
     }
 
     private WebContents getWebContents() {
-        return mActivityTestRule.getActivity().getCurrentWebContents();
+        return mActivityTestRule.getWebContents();
     }
 
     private void testExitOn(Activity activity, Runnable runnable) throws Throwable {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java
index 8f6e36c..f61c8f70 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java
@@ -62,6 +62,9 @@
 import org.chromium.blink.mojom.AuthenticatorAttachment;
 import org.chromium.blink.mojom.AuthenticatorStatus;
 import org.chromium.blink.mojom.AuthenticatorTransport;
+import org.chromium.blink.mojom.CredentialInfo;
+import org.chromium.blink.mojom.CredentialType;
+import org.chromium.blink.mojom.CredentialTypeFlags;
 import org.chromium.blink.mojom.GetAssertionAuthenticatorResponse;
 import org.chromium.blink.mojom.MakeCredentialAuthenticatorResponse;
 import org.chromium.blink.mojom.Mediation;
@@ -84,6 +87,7 @@
 import org.chromium.chrome.test.transit.page.WebPageStation;
 import org.chromium.components.ukm.UkmRecorder;
 import org.chromium.components.ukm.UkmRecorderJni;
+import org.chromium.components.webauthn.AssertionMediationType;
 import org.chromium.components.webauthn.AuthenticationContextProvider;
 import org.chromium.components.webauthn.AuthenticatorImpl;
 import org.chromium.components.webauthn.CreateConfirmationUiDelegate;
@@ -101,6 +105,7 @@
 import org.chromium.components.webauthn.WebauthnCredentialDetails;
 import org.chromium.components.webauthn.WebauthnMode;
 import org.chromium.components.webauthn.WebauthnModeProvider;
+import org.chromium.components.webauthn.cred_man.CredManSupportProvider;
 import org.chromium.content.browser.ClientDataJsonImpl;
 import org.chromium.content.browser.ClientDataJsonImplJni;
 import org.chromium.content_public.browser.ClientDataRequestType;
@@ -109,6 +114,7 @@
 import org.chromium.content_public.browser.test.mock.MockRenderFrameHost;
 import org.chromium.content_public.browser.test.mock.MockWebContents;
 import org.chromium.content_public.common.ContentSwitches;
+import org.chromium.mojo_base.mojom.String16;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.ui.test.util.GmsCoreVersionRestriction;
 import org.chromium.url.GURL;
@@ -161,6 +167,10 @@
     private static final String FILLER_ERROR_MSG = "Error Error";
     private Fido2ApiTestHelper.AuthenticatorCallback mCallback;
     private long mStartTimeMs;
+    private static final String PASSWORD_CRED_USERNAME = "Monkey";
+    private static String16 sPasswordCredUsername16;
+    private static final String PASSWORD_CRED_PASSWORD = "DLuffy2";
+    private static String16 sPasswordCredPassword16;
 
     /**
      * This class constructs the parameters array that is used for testMakeCredential_with_param and
@@ -336,6 +346,13 @@
         }
     }
 
+    private static class MockIncognitoWebContents extends MockWebContents {
+        @Override
+        public boolean isIncognito() {
+            return true;
+        }
+    }
+
     private static class TestAuthenticatorImplJni implements InternalAuthenticator.Natives {
         private final Fido2ApiTestHelper.AuthenticatorCallback mCallback;
 
@@ -374,26 +391,32 @@
 
     private static class MockBrowserBridge extends WebauthnBrowserBridge {
         public enum CallbackInvocationType {
-            IMMEDIATE_GET_ASSERTION,
+            IMMEDIATE_PASSKEY,
+            IMMEDIATE_PASSWORD,
             IMMEDIATE_HYBRID,
+            IMMEDIATE_REJECT_IMMEDIATE,
             DELAYED
         }
 
         private byte[] mSelectedCredentialId;
         private List<WebauthnCredentialDetails> mExpectedCredentialList;
         private CallbackInvocationType mInvokeCallbackImmediately =
-                CallbackInvocationType.IMMEDIATE_GET_ASSERTION;
-        private Callback<byte[]> mGetAssertionCallback;
+                CallbackInvocationType.IMMEDIATE_PASSKEY;
+        private Callback<byte[]> mPasskeyCallback;
+        private Callback<CredentialInfo> mPasswordCallback;
         private Runnable mHybridCallback;
+        private Callback<Integer> mRejectImmediateCallback;
         private int mCleanupCalled;
 
         @Override
         public void onCredentialsDetailsListReceived(
                 RenderFrameHost frameHost,
                 List<WebauthnCredentialDetails> credentialList,
-                boolean isConditionalRequest,
-                Callback<byte[]> getAssertionCallback,
-                Runnable hybridCallback) {
+                @AssertionMediationType int mediationType,
+                Callback<byte[]> passkeyCallback,
+                @Nullable Callback<CredentialInfo> passwordCallback,
+                @Nullable Runnable hybridCallback,
+                @Nullable Callback<Integer> rejectImmediateCallback) {
             Assert.assertEquals(mExpectedCredentialList.size(), credentialList.size());
             for (int i = 0; i < credentialList.size(); i++) {
                 Assert.assertEquals(
@@ -408,16 +431,26 @@
                         mExpectedCredentialList.get(0).mUserId, credentialList.get(0).mUserId);
             }
 
-            mGetAssertionCallback = getAssertionCallback;
+            mPasskeyCallback = passkeyCallback;
+            mPasswordCallback = passwordCallback;
             mHybridCallback = hybridCallback;
+            mRejectImmediateCallback = rejectImmediateCallback;
 
-            if (mInvokeCallbackImmediately == CallbackInvocationType.IMMEDIATE_GET_ASSERTION) {
-                invokeGetAssertionCallback();
+            if (mInvokeCallbackImmediately == CallbackInvocationType.IMMEDIATE_PASSKEY) {
+                invokePasskeyCallback();
+            }
+
+            if (mInvokeCallbackImmediately == CallbackInvocationType.IMMEDIATE_PASSWORD) {
+                invokePasswordCallback();
             }
 
             if (mInvokeCallbackImmediately == CallbackInvocationType.IMMEDIATE_HYBRID) {
                 invokeHybridCallback();
             }
+
+            if (mInvokeCallbackImmediately == CallbackInvocationType.IMMEDIATE_REJECT_IMMEDIATE) {
+                invokeRejectImmediateCallback();
+            }
         }
 
         @Override
@@ -438,9 +471,9 @@
             mInvokeCallbackImmediately = type;
         }
 
-        public void invokeGetAssertionCallback() {
+        public void invokePasskeyCallback() {
             if (mSelectedCredentialId != null) {
-                mGetAssertionCallback.onResult(mSelectedCredentialId);
+                mPasskeyCallback.onResult(mSelectedCredentialId);
                 return;
             }
 
@@ -450,18 +483,31 @@
              * which normally would imply an error response.
              */
             if (mExpectedCredentialList.isEmpty()) {
-                mGetAssertionCallback.onResult(new byte[0]);
+                mPasskeyCallback.onResult(new byte[0]);
                 return;
             }
 
             /* Return the first ID in the list if one has not been explicitly set. */
-            mGetAssertionCallback.onResult(mExpectedCredentialList.get(0).mCredentialId);
+            mPasskeyCallback.onResult(mExpectedCredentialList.get(0).mCredentialId);
+        }
+
+        public void invokePasswordCallback() {
+            CredentialInfo passwordCredential = new CredentialInfo();
+            passwordCredential.type = CredentialType.PASSWORD;
+            passwordCredential.name = sPasswordCredUsername16;
+            passwordCredential.id = sPasswordCredUsername16;
+            passwordCredential.password = sPasswordCredPassword16;
+            mPasswordCallback.onResult(passwordCredential);
         }
 
         public void invokeHybridCallback() {
             mHybridCallback.run();
         }
 
+        public void invokeRejectImmediateCallback() {
+            mRejectImmediateCallback.onResult(0);
+        }
+
         public int getCleanupCalledCount() {
             return mCleanupCalled;
         }
@@ -585,6 +631,15 @@
         mRequest.overrideBrowserBridgeForTesting(mMockBrowserBridge);
 
         mStartTimeMs = SystemClock.elapsedRealtime();
+
+        sPasswordCredUsername16 =
+                WebauthnBrowserBridge.stringToMojoString16(PASSWORD_CRED_USERNAME);
+        sPasswordCredPassword16 =
+                WebauthnBrowserBridge.stringToMojoString16(PASSWORD_CRED_PASSWORD);
+
+        CredManSupportProvider.setupForTesting(
+                /* overrideAndroidVersion= */ Build.VERSION_CODES.TIRAMISU,
+                /* overrideForcesGpm= */ false);
     }
 
     @Test
@@ -2293,7 +2348,7 @@
 
         // Select credential again, and provide a success response this time.
         mIntentSender.setNextResultIntent(Fido2ApiTestHelper.createSuccessfulGetAssertionIntent());
-        mMockBrowserBridge.invokeGetAssertionCallback();
+        mMockBrowserBridge.invokePasskeyCallback();
         mCallback.blockUntilCalled();
         Assert.assertEquals(Integer.valueOf(AuthenticatorStatus.SUCCESS), mCallback.getStatus());
         Fido2ApiTestHelper.validateGetAssertionResponse(mCallback.getGetAssertionResponse());
@@ -2361,6 +2416,155 @@
 
     @Test
     @SmallTest
+    public void testGetAssertion_ImmediateWithPasskeysOnly_success() {
+        Fido2ApiTestHelper.mockClientDataJson();
+        mIntentSender.setNextResultIntent(Fido2ApiTestHelper.createSuccessfulGetAssertionIntent());
+        mMockBrowserBridge.setExpectedCredentialDetailsList(
+                Arrays.asList(
+                        new WebauthnCredentialDetails[] {
+                            Fido2ApiTestHelper.getCredentialDetails()
+                        }));
+
+        mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0];
+        mRequestOptions.mediation = Mediation.IMMEDIATE;
+        mRequestOptions.requestedCredentialTypeFlags |= CredentialTypeFlags.PASSWORD;
+
+        mRequest.handleGetCredentialRequest(
+                mRequestOptions,
+                mOrigin,
+                mOrigin,
+                /* payment= */ null,
+                mCallback::onSignResponse,
+                mCallback::onError,
+                mCallback::onRequestOutcome);
+        mCallback.blockUntilCalled();
+        Assert.assertEquals(Integer.valueOf(AuthenticatorStatus.SUCCESS), mCallback.getStatus());
+        Fido2ApiTestHelper.validateGetAssertionResponse(mCallback.getGetAssertionResponse());
+        Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs);
+    }
+
+    @Test
+    @SmallTest
+    public void testGetAssertion_ImmediateWithNonEmptyAllowList_notAllowedError() {
+        mRequestOptions.mediation = Mediation.IMMEDIATE;
+        mRequestOptions.requestedCredentialTypeFlags |= CredentialTypeFlags.PASSWORD;
+
+        mRequest.handleGetCredentialRequest(
+                mRequestOptions,
+                mOrigin,
+                mOrigin,
+                /* payment= */ null,
+                mCallback::onSignResponse,
+                mCallback::onError,
+                mCallback::onRequestOutcome);
+        mCallback.blockUntilCalled();
+        Assert.assertEquals(
+                Integer.valueOf(AuthenticatorStatus.NOT_ALLOWED_ERROR), mCallback.getStatus());
+        Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs);
+    }
+
+    @Test
+    @SmallTest
+    public void testGetAssertion_ImmediateWithNoPasskeysFound_notAllowedError() {
+        mFido2ApiCallHelper.setReturnedCredentialDetails(new ArrayList<>());
+        mMockBrowserBridge.setExpectedCredentialDetailsList(new ArrayList<>());
+
+        mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0];
+        mRequestOptions.mediation = Mediation.IMMEDIATE;
+
+        mRequest.handleGetCredentialRequest(
+                mRequestOptions,
+                mOrigin,
+                mOrigin,
+                /* payment= */ null,
+                mCallback::onSignResponse,
+                mCallback::onError,
+                mCallback::onRequestOutcome);
+        mCallback.blockUntilCalled();
+        Assert.assertEquals(
+                Integer.valueOf(AuthenticatorStatus.NOT_ALLOWED_ERROR), mCallback.getStatus());
+        Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs);
+    }
+
+    @Test
+    @SmallTest
+    public void testGetAssertion_ImmediateWithNoPasskeysButPasswordReturned_success() {
+        mMockBrowserBridge.setInvokeCallbackImmediately(
+                MockBrowserBridge.CallbackInvocationType.IMMEDIATE_PASSWORD);
+        mMockBrowserBridge.setExpectedCredentialDetailsList(new ArrayList<>());
+
+        mFido2ApiCallHelper.setReturnedCredentialDetails(new ArrayList<>());
+
+        mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0];
+        mRequestOptions.mediation = Mediation.IMMEDIATE;
+        mRequestOptions.requestedCredentialTypeFlags |= CredentialTypeFlags.PASSWORD;
+
+        mRequest.handleGetCredentialRequest(
+                mRequestOptions,
+                mOrigin,
+                mOrigin,
+                /* payment= */ null,
+                mCallback::onSignResponse,
+                mCallback::onError,
+                mCallback::onRequestOutcome);
+        mCallback.blockUntilCalled();
+        Assert.assertEquals(Integer.valueOf(AuthenticatorStatus.SUCCESS), mCallback.getStatus());
+        Assert.assertEquals(
+                sPasswordCredUsername16, mCallback.getGetAssertionPasswordCredential().name);
+        Assert.assertEquals(
+                sPasswordCredPassword16, mCallback.getGetAssertionPasswordCredential().password);
+        Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs);
+    }
+
+    @Test
+    @SmallTest
+    public void testGetAssertion_ImmediateInIncognito_notAllowedError() {
+        mWebContents = new MockIncognitoWebContents();
+        mAuthenticationContextProvider =
+                new AuthenticationContextProvider() {
+                    @Override
+                    public Context getContext() {
+                        return mContext;
+                    }
+
+                    @Override
+                    public RenderFrameHost getRenderFrameHost() {
+                        return mFrameHost;
+                    }
+
+                    @Override
+                    public FidoIntentSender getIntentSender() {
+                        return mIntentSender;
+                    }
+
+                    @Override
+                    public WebContents getWebContents() {
+                        return mWebContents;
+                    }
+                };
+        mRequest = new Fido2CredentialRequest(mAuthenticationContextProvider);
+        AuthenticatorImpl.overrideFido2CredentialRequestForTesting(mRequest);
+
+        mRequestOptions.mediation = Mediation.IMMEDIATE;
+        mRequestOptions.requestedCredentialTypeFlags |= CredentialTypeFlags.PASSWORD;
+        mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0];
+
+        mRequest.handleGetCredentialRequest(
+                mRequestOptions,
+                mOrigin,
+                mOrigin,
+                /* payment= */ null,
+                mCallback::onSignResponse,
+                mCallback::onError,
+                mCallback::onRequestOutcome);
+        mCallback.blockUntilCalled();
+        Assert.assertEquals(
+                Integer.valueOf(AuthenticatorStatus.NOT_ALLOWED_ERROR), mCallback.getStatus());
+        Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs);
+    }
+
+    @Test
+    @SmallTest
     public void testGetMatchingCredentialIds_success() {
         String relyingPartyId = "subdomain.example.test";
         byte[][] allowCredentialIds =
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/DeferredStartupHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/DeferredStartupHandlerTest.java
index 98d2638..4c4e315 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/DeferredStartupHandlerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/DeferredStartupHandlerTest.java
@@ -9,11 +9,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
@@ -28,6 +30,7 @@
 @Config(manifest = Config.NONE)
 @LooperMode(LooperMode.Mode.LEGACY)
 public class DeferredStartupHandlerTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private final List<IdleHandler> mIdleHandlers = new ArrayList<>();
 
     @Mock private MessageQueue mMessageQueue;
@@ -36,7 +39,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mDeferredStartupHandler = new DeferredStartupHandler(mMessageQueue);
         Mockito.doAnswer(
                         invocation -> {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java
index 92b58ae7..790373a 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java
@@ -74,6 +74,7 @@
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
+import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
 import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
 import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
 import org.chromium.components.browser_ui.widget.TouchEventObserver;
@@ -183,6 +184,7 @@
     @Mock private InputHintChecker.Natives mInputHintCheckerJni;
     @Mock private MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
     @Mock private InsetObserver mInsetObserver;
+    @Mock private TopUiThemeColorProvider mTopUiThemeColorProvider;
 
     @Captor private ArgumentCaptor<TabObserver> mTabObserverCaptor;
 
@@ -261,6 +263,7 @@
 
         mCompositorViewHolder = spy(new CompositorViewHolder(mContext, null));
 
+        mCompositorViewHolder.setTopUiThemeColorProvider(mTopUiThemeColorProvider);
         mCompositorViewHolder.setLayoutManager(mLayoutManager);
         mCompositorViewHolder.setControlContainer(mControlContainer);
         mCompositorViewHolder.setCompositorViewForTesting(mCompositorView);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
index 2322a76..3cd6d32 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -222,7 +222,6 @@
     @Mock private TintedCompositorButton mCloseButton;
     @Mock TabStripIphController mController;
     @Captor private ArgumentCaptor<DataSharingService.Observer> mSharingObserverCaptor;
-    @Captor private ArgumentCaptor<Callback<Boolean>> mSharedImageTilesCaptor;
     @Captor private ArgumentCaptor<TabModelActionListener> mTabModelActionListenerCaptor;
     @Captor private ArgumentCaptor<Callback<TabClosureParams>> mTabRemoverCallbackCaptor;
 
@@ -235,7 +234,6 @@
     private final TestTabModel mModel = spy(new TestTabModel());
     private StripLayoutHelper mStripLayoutHelper;
     private boolean mIncognito;
-    private static final int NEW_ANIM_TAB_RESIZE_MS = 200;
     private static final String[] TEST_TAB_TITLES = {"Tab 1", "Tab 2", "Tab 3", "", null};
     private static final String EXPECTED_TAB = "The view should be a tab.";
     private static final String EXPECTED_TITLE = "The view should be a title.";
@@ -538,13 +536,12 @@
         initializeTest(false, false, 0);
 
         // Create collaboration group and show notification bubble on group title.
-        StripLayoutGroupTitle groupTitle =
-                createCollaborationGroup(
-                        /* multipleCollaborators= */ true,
-                        /* duringStripBuild= */ false,
-                        /* start= */ 0,
-                        /* end= */ 3,
-                        TAB_GROUP_ID_1);
+        createCollaborationGroup(
+                /* multipleCollaborators= */ true,
+                /* duringStripBuild= */ false,
+                /* start= */ 0,
+                /* end= */ 3,
+                TAB_GROUP_ID_1);
         int tabId = mModel.getTabAt(0).getId();
         Set<Integer> tabIds = new HashSet<>(Collections.singleton(tabId));
         mStripLayoutHelper.updateTabStripNotificationBubble(tabIds, /* hasUpdate= */ true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandlerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandlerUnitTest.java
index 7160e796..458bc55 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandlerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTimeoutHandlerUnitTest.java
@@ -1,3 +1,7 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 package org.chromium.chrome.browser.customtabs;
 
 import static org.mockito.Mockito.never;
@@ -12,7 +16,8 @@
 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.chromium.base.FakeTimeTestRule;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -28,6 +33,7 @@
 public class CustomTabActivityTimeoutHandlerUnitTest {
     @Mock private Runnable mFinishRunnable;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Rule public FakeTimeTestRule mFakeTimeTestRule = new FakeTimeTestRule();
 
     private CustomTabActivityTimeoutHandler mTimeoutHandler;
@@ -37,7 +43,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         ChromeFeatureList.sCctResetMinimumTimeoutMinutes.setForTesting(1);
         sIntentWithExtra.putExtra(
                 CustomTabActivityTimeoutHandler.EXTRA_TIMEOUT_MINUTES, TIMEOUT_MINUTES);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationBarControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationBarControllerTest.java
index 5d007120..b17a0da5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationBarControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationBarControllerTest.java
@@ -114,9 +114,7 @@
         when(mColorProvider.getNavigationBarColor()).thenReturn(Color.WHITE);
         CustomTabNavigationBarController.update(
                 mWindow, mCustomTabIntentDataProvider, mContext, /* isEdgeToEdge= */ false);
-        verify(mWindow)
-                .setNavigationBarDividerColor(
-                        mContext.getColor(org.chromium.chrome.R.color.black_alpha_12));
+        verify(mWindow).setNavigationBarDividerColor(mContext.getColor(R.color.black_alpha_12));
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/flags/BadFlagsSnackbarManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/flags/BadFlagsSnackbarManagerTest.java
index 5b2cd577..87d9403 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/flags/BadFlagsSnackbarManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/flags/BadFlagsSnackbarManagerTest.java
@@ -16,6 +16,7 @@
 import org.robolectric.Robolectric;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ui.BottomContainer;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -28,7 +29,7 @@
     @Before
     public void setup() {
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
-        mActivity.setTheme(org.chromium.chrome.R.style.Theme_BrowserUI_DayNight);
+        mActivity.setTheme(R.style.Theme_BrowserUI_DayNight);
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/fonts/FontPreloaderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/fonts/FontPreloaderUnitTest.java
index 90b7357..416c93a 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/fonts/FontPreloaderUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/fonts/FontPreloaderUnitTest.java
@@ -30,6 +30,7 @@
 import org.robolectric.annotation.Resetter;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.fonts.FontPreloaderUnitTest.ShadowResourcesCompat;
 
 import java.util.ArrayList;
@@ -43,9 +44,7 @@
 @LooperMode(Mode.PAUSED)
 public class FontPreloaderUnitTest {
     private static final Integer[] FONTS = {
-        org.chromium.chrome.R.font.chrome_google_sans,
-        org.chromium.chrome.R.font.chrome_google_sans_medium,
-        org.chromium.chrome.R.font.chrome_google_sans_bold
+        R.font.chrome_google_sans, R.font.chrome_google_sans_medium, R.font.chrome_google_sans_bold
     };
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/modules/on_demand/java/src/org/chromium/chrome/browser/data_import/DataImporterServiceImpl.java b/chrome/android/modules/on_demand/java/src/org/chromium/chrome/browser/data_import/DataImporterServiceImpl.java
index b7fad106..c8b7d3d 100644
--- a/chrome/android/modules/on_demand/java/src/org/chromium/chrome/browser/data_import/DataImporterServiceImpl.java
+++ b/chrome/android/modules/on_demand/java/src/org/chromium/chrome/browser/data_import/DataImporterServiceImpl.java
@@ -416,13 +416,7 @@
                     ownedFd,
                     (count) -> {
                         Log.i(TAG, "Bookmarks imported: %d", count);
-                        synchronized (mPendingImportsLock) {
-                            ImportResults importResults = mPendingImports.get(sessionId);
-                            assert (importResults != null);
-                            // TODO(crbug.com/435386347): Plumb the actual import result (success or
-                            // failure) back here, so it can be properly reported.
-                            importResults.successItemCount++;
-                        }
+                        updateImportResults(sessionId, count);
                         responseObserver.onNext(ImportItemResponse.newBuilder().build());
                         responseObserver.onCompleted();
                     });
@@ -441,13 +435,7 @@
                     ownedFd,
                     (count) -> {
                         Log.i(TAG, "ReadingList imported: %d", count);
-                        synchronized (mPendingImportsLock) {
-                            ImportResults importResults = mPendingImports.get(sessionId);
-                            assert (importResults != null);
-                            // TODO(crbug.com/435386347): Plumb the actual import result (success or
-                            // failure) back here, so it can be properly reported.
-                            importResults.successItemCount++;
-                        }
+                        updateImportResults(sessionId, count);
                         responseObserver.onNext(ImportItemResponse.newBuilder().build());
                         responseObserver.onCompleted();
                     });
@@ -466,13 +454,7 @@
                     ownedFd,
                     (count) -> {
                         Log.i(TAG, "History imported: %d", count);
-                        synchronized (mPendingImportsLock) {
-                            ImportResults importResults = mPendingImports.get(sessionId);
-                            assert (importResults != null);
-                            // TODO(crbug.com/435386347): Plumb the actual import result (success or
-                            // failure) back here, so it can be properly reported.
-                            importResults.successItemCount++;
-                        }
+                        updateImportResults(sessionId, count);
                         responseObserver.onNext(ImportItemResponse.newBuilder().build());
                         responseObserver.onCompleted();
                     });
@@ -486,5 +468,17 @@
                 mBridge = null;
             }
         }
+
+        private void updateImportResults(ByteString sessionId, int count) {
+            synchronized (mPendingImportsLock) {
+                ImportResults importResults = mPendingImports.get(sessionId);
+                assert (importResults != null);
+                if (count >= 0) {
+                    importResults.successItemCount++;
+                } else {
+                    importResults.failedItemCount++;
+                }
+            }
+        }
     }
 }
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 814a7b2..7a1967f 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -1956,6 +1956,11 @@
           Search this video with Image Search
         </message>
 
+        <message name="IDS_AI_MODE_ENTRYPOINT_LABEL"
+          desc="The label of the AI mode entrypoint in the omnibox">
+          AI Mode
+        </message>
+
         <!-- Lens Side Panel Error Page -->
         <message name="IDS_SIDE_PANEL_LENS_OVERLAY_GENERIC_ERROR_PAGE_FIRST_LINE"
             desc="Text shown on the side panel for the Lens feature when there is a network or other server error. The texts informs the user that an error has occured.">
@@ -2026,6 +2031,12 @@
           desc="Default query for Lens searchbox to request help with the current page context.">
           help me with this
         </message>
+
+        <!-- AI Mode Strings -->
+        <message name="IDS_LENS_COMPOSEBOX_HINT_TEXT"
+          desc="The hint text of the AI mode searchbox in the Lens side panel. This text is shown in the searchbox when the user has not yet typed any text, and prompts the user to ask a follow up question.">
+          Ask a follow up
+        </message>
       </if>
 
       <!-- OOBE -->
diff --git a/chrome/app/chromium_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1 b/chrome/app/chromium_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1
new file mode 100644
index 0000000..d66c17a
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1
@@ -0,0 +1 @@
+66b15bbd6777b1f1a09e04aa1297e348753911a6
\ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1 b/chrome/app/chromium_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1
new file mode 100644
index 0000000..99942a7
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1
@@ -0,0 +1 @@
+5cc4dc51c833fef26cdbb8a5d42ccf3c471d0817
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 392b577..2928cbd 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -1967,6 +1967,11 @@
           Search this video with Google Lens
         </message>
 
+        <message name="IDS_AI_MODE_ENTRYPOINT_LABEL"
+          desc="The label of the AI mode entrypoint in the omnibox">
+          AI Mode
+        </message>
+
         <!-- Lens Side Panel Error Page -->
         <message name="IDS_SIDE_PANEL_LENS_OVERLAY_GENERIC_ERROR_PAGE_FIRST_LINE"
             desc="Text shown on the side panel for the Lens feature when there is a network or other server error. The texts informs the user that an error has occured.">
@@ -2038,6 +2043,12 @@
           help me with this
         </message>
 
+        <!-- AI Mode Strings -->
+        <message name="IDS_LENS_COMPOSEBOX_HINT_TEXT"
+          desc="The hint text of the AI mode searchbox in the Lens side panel. This text is shown in the searchbox when the user has not yet typed any text, and prompts the user to ask a follow up question.">
+          Ask a follow up
+        </message>
+
         <!-- On Sign-in Avatar Button Label Desktop -->
         <!-- TODO(crbug.com/417928515): Finalize the string and make it translateable. -->
         <message translateable="false" name="IDS_AVATAR_BUTTON_MAKING_CHROME_YOURS" desc="">
diff --git a/chrome/app/google_chrome_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1
new file mode 100644
index 0000000..d66c17a
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_AI_MODE_ENTRYPOINT_LABEL.png.sha1
@@ -0,0 +1 @@
+66b15bbd6777b1f1a09e04aa1297e348753911a6
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1
new file mode 100644
index 0000000..99942a7
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_LENS_COMPOSEBOX_HINT_TEXT.png.sha1
@@ -0,0 +1 @@
+5cc4dc51c833fef26cdbb8a5d42ccf3c471d0817
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index ea9e979..2770375 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1699,6 +1699,8 @@
     "webapps/web_app_offline.h",
     "webauthn/chrome_web_authentication_delegate_base.cc",
     "webauthn/chrome_web_authentication_delegate_base.h",
+    "webauthn/password_credential_controller.cc",
+    "webauthn/password_credential_controller.h",
     "webauthn/webauthn_metrics_util.cc",
     "webauthn/webauthn_pref_names.cc",
     "webauthn/webauthn_pref_names.h",
@@ -2083,6 +2085,7 @@
     "//chrome/browser/ui/safety_hub:impl",
     "//chrome/browser/ui/search_engines",
     "//chrome/browser/ui/side_search",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/sync",
     "//chrome/browser/ui/sync:impl",
     "//chrome/browser/ui/translate",
@@ -4330,8 +4333,6 @@
       "webauthn/observable_authenticator_list.cc",
       "webauthn/observable_authenticator_list.h",
       "webauthn/passkey_model_factory.cc",
-      "webauthn/password_credential_controller.cc",
-      "webauthn/password_credential_controller.h",
       "webauthn/unexportable_key_utils.cc",
       "webauthn/unexportable_key_utils.h",
     ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 08fe88c..a0b2c5d4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -5036,6 +5036,12 @@
      flag_descriptions::kAutofillPaymentsFieldSwappingName,
      flag_descriptions::kAutofillPaymentsFieldSwappingDescription, kOsAll,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillPaymentsFieldSwapping)},
+    {"autofill-show-bubbles-based-on-priorities",
+     flag_descriptions::kAutofillShowBubblesBasedOnPrioritiesName,
+     flag_descriptions::kAutofillShowBubblesBasedOnPrioritiesDescription,
+     kOsAll,
+     FEATURE_VALUE_TYPE(
+         autofill::features::kAutofillShowBubblesBasedOnPriorities)},
     {"backdrop-filter-mirror-edge",
      flag_descriptions::kBackdropFilterMirrorEdgeName,
      flag_descriptions::kBackdropFilterMirrorEdgeDescription, kOsAll,
@@ -6939,6 +6945,11 @@
      flag_descriptions::kLensOverlayOmniboxEntryPointDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(lens::features::kLensOverlayOmniboxEntryPoint)},
 
+    {"ai-mode-omnibox-entry-point",
+     flag_descriptions::kAiModeOmniboxEntryPointName,
+     flag_descriptions::kAiModeOmniboxEntryPointDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(omnibox::kAiModeOmniboxEntryPoint)},
+
     {"omnibox-toolbelt", flag_descriptions::kOmniboxToolbeltName,
      flag_descriptions::kOmniboxToolbeltDescription, kOsDesktop,
      FEATURE_WITH_PARAMS_VALUE_TYPE(
diff --git a/chrome/browser/actor/BUILD.gn b/chrome/browser/actor/BUILD.gn
index 47242d2e..86856635 100644
--- a/chrome/browser/actor/BUILD.gn
+++ b/chrome/browser/actor/BUILD.gn
@@ -44,6 +44,7 @@
     ":types",
     "//base",
     "//chrome/browser/actor/ui:states",
+    "//chrome/browser/page_content_annotations:fetcher",
     "//chrome/browser/profiles",
     "//chrome/common",
     "//components/optimization_guide/content/browser",
diff --git a/chrome/browser/actor/actor_keyed_service.cc b/chrome/browser/actor/actor_keyed_service.cc
index 00671dc..d9b737b 100644
--- a/chrome/browser/actor/actor_keyed_service.cc
+++ b/chrome/browser/actor/actor_keyed_service.cc
@@ -23,9 +23,9 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/common/actor.mojom.h"
 #include "chrome/common/actor/action_result.h"
+#include "third_party/abseil-cpp/absl/strings/str_format.h"
 
 namespace {
-
 void RunLater(base::OnceClosure task) {
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
                                                               std::move(task));
@@ -152,38 +152,27 @@
       optimization_guide::ActionableAIPageContentOptions();
   page_content_annotations::FetchPageContext(
       *tab.GetContents(), options,
-      base::BindOnce(&ActorKeyedService::OnTabOservationResult,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
+      base::BindOnce(
+          [](base::OnceCallback<void(TabObservationResult)> callback,
+             TabObservationResult result) {
+            if (result.has_value()) {
+              // Context for actor observations should always have an APC and a
+              // screenshot, return failure if either is missing.
+              auto& fetch_result = **result;
+              bool has_apc =
+                  fetch_result.annotated_page_content_result.has_value();
+              bool has_screenshot = fetch_result.screenshot_result.has_value();
+              if (!has_apc || !has_screenshot) {
+                std::move(callback).Run(base::unexpected(absl::StrFormat(
+                    "Failed Observation: hasAPC[%g] hasScreenshot[%g]", has_apc,
+                    has_screenshot)));
+                return;
+              }
 
-void ActorKeyedService::OnTabOservationResult(
-    base::OnceCallback<void(TabObservationResult)> callback,
-    page_content_annotations::FetchPageContextResultCallbackArg fetch_result) {
-  if (!fetch_result.has_value()) {
-    std::move(callback).Run(base::unexpected(fetch_result.error()));
-    return;
-  }
-  auto& page_context = **fetch_result;
-  if (!page_context.screenshot_result.has_value() ||
-      !page_context.annotated_page_content_result.has_value()) {
-    std::move(callback).Run(
-        base::unexpected<std::string>("Failed Observation"));
-    return;
-  }
-  std::unique_ptr<optimization_guide::proto::TabObservation> result =
-      std::make_unique<optimization_guide::proto::TabObservation>();
-  if (page_context.screenshot_result) {
-    auto& data = page_context.screenshot_result->jpeg_data;
-    if (data.size() != 0) {
-      result->set_screenshot_mime_type("image/jpeg");
-      result->set_screenshot(data.data(), data.size());
-    }
-  }
-  if (page_context.annotated_page_content_result) {
-    result->mutable_annotated_page_content()->Swap(
-        &page_context.annotated_page_content_result->proto);
-  }
-  std::move(callback).Run(std::move(result));
+              std::move(callback).Run(std::move(result));
+            }
+          },
+          std::move(callback)));
 }
 
 void ActorKeyedService::ConvertToBrowserActionResult(
@@ -193,8 +182,9 @@
     int32_t tab_id,
     const GURL& url,
     actor::mojom::ActionResultPtr action_result,
-    base::expected<std::unique_ptr<optimization_guide::proto::TabObservation>,
-                   std::string> context_result) {
+    base::expected<
+        std::unique_ptr<page_content_annotations::FetchPageContextResult>,
+        std::string> context_result) {
   optimization_guide::proto::BrowserActionResult browser_action_result;
   if (!context_result.has_value()) {
     VLOG(1) << "Execute Action failed: Error fetching context.";
@@ -203,26 +193,27 @@
         base::BindOnce(std::move(callback), std::move(browser_action_result)));
     return;
   }
-  auto& tab_observation = **context_result;
-  if (tab_observation.has_annotated_page_content()) {
-    size_t size = tab_observation.annotated_page_content().ByteSizeLong();
-    std::vector<uint8_t> buffer(size);
-    tab_observation.annotated_page_content().SerializeToArray(buffer.data(),
-                                                              size);
-    journal_.LogAnnotatedPageContent(url, task_id, buffer);
+  auto& fetch_result = **context_result;
 
-    browser_action_result.mutable_annotated_page_content()->Swap(
-        tab_observation.mutable_annotated_page_content());
-  }
-  if (tab_observation.has_screenshot()) {
-    journal_.LogScreenshot(url, task_id, tab_observation.screenshot_mime_type(),
-                           base::as_byte_span(tab_observation.screenshot()));
+  CHECK(fetch_result.annotated_page_content_result.has_value());
+  CHECK(fetch_result.screenshot_result.has_value());
 
-    browser_action_result.set_screenshot(tab_observation.screenshot().data(),
-                                         tab_observation.screenshot().size());
-    browser_action_result.set_screenshot_mime_type(
-        tab_observation.screenshot_mime_type());
-  }
+  size_t size =
+      fetch_result.annotated_page_content_result->proto.ByteSizeLong();
+  std::vector<uint8_t> buffer(size);
+  fetch_result.annotated_page_content_result->proto.SerializeToArray(
+      buffer.data(), size);
+  journal_.LogAnnotatedPageContent(url, task_id, buffer);
+
+  browser_action_result.mutable_annotated_page_content()->Swap(
+      &fetch_result.annotated_page_content_result->proto);
+  auto& data = fetch_result.screenshot_result->jpeg_data;
+  journal_.LogScreenshot(url, task_id, kMimeTypeJpeg, base::as_byte_span(data));
+
+  // TODO(bokan): Can we avoid a copy here?
+  browser_action_result.set_screenshot(data.data(), data.size());
+  browser_action_result.set_screenshot_mime_type(kMimeTypeJpeg);
+
   browser_action_result.set_task_id(task_id.value());
   browser_action_result.set_tab_id(tab_id);
   browser_action_result.set_action_result(actor::IsOk(*action_result) ? 1 : 0);
diff --git a/chrome/browser/actor/actor_keyed_service.h b/chrome/browser/actor/actor_keyed_service.h
index fc4416a..1d84a25 100644
--- a/chrome/browser/actor/actor_keyed_service.h
+++ b/chrome/browser/actor/actor_keyed_service.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/actor/actor_task.h"
 #include "chrome/browser/actor/aggregated_journal.h"
 #include "chrome/browser/actor/task_id.h"
+#include "chrome/browser/page_content_annotations/multi_source_page_context_fetcher.h"
 #include "chrome/common/buildflags.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/optimization_guide/proto/features/actions_data.pb.h"
@@ -30,10 +31,6 @@
 class BrowserContext;
 }  // namespace content
 
-namespace page_content_annotations {
-struct FetchPageContextResult;
-}  // namespace page_content_annotations
-
 namespace actor {
 namespace ui {
 class ActorUiStateManagerInterface;
@@ -108,9 +105,9 @@
   bool IsAnyTaskActingOnTab(const tabs::TabInterface& tab) const;
   Profile* GetProfile();
 
-  using TabObservationResult =
-      base::expected<std::unique_ptr<optimization_guide::proto::TabObservation>,
-                     std::string>;
+  using TabObservationResult = base::expected<
+      std::unique_ptr<page_content_annotations::FetchPageContextResult>,
+      std::string>;
 
   // Request a TabOservation be generated from the given tab.
   void RequestTabObservation(
diff --git a/chrome/browser/actor/actor_task.cc b/chrome/browser/actor/actor_task.cc
index 483d419..d581e3f 100644
--- a/chrome/browser/actor/actor_task.cc
+++ b/chrome/browser/actor/actor_task.cc
@@ -18,6 +18,7 @@
 #include "chrome/common/actor.mojom-forward.h"
 #include "chrome/common/actor/action_result.h"
 #include "components/tabs/public/tab_interface.h"
+#include "content/public/browser/web_contents.h"
 
 namespace actor {
 
@@ -148,6 +149,17 @@
         FROM_HERE, base::BindOnce(std::move(callback), MakeOkResult()));
     return;
   }
+
+  CHECK(!actuation_mode_runners_.contains(tab_handle));
+  if (tab_handle.Get() && tab_handle.Get()->GetContents()) {
+    content::WebContents* web_contents = tab_handle.Get()->GetContents();
+    actuation_mode_runners_.emplace(
+        tab_handle, web_contents->IncrementCapturerCount(gfx::Size(),
+                                                         /*stay_hidden=*/false,
+                                                         /*stay_awake=*/true,
+                                                         /*is_activity=*/true));
+  }
+
   // Notify the UI of the new tab.
   tab_handles_.insert(tab_handle);
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
@@ -159,6 +171,10 @@
 }
 
 void ActorTask::RemoveTab(tabs::TabHandle tab_handle) {
+  // Erasing the ScopedClosureRunner from the map triggers its destructor, which
+  // automatically calls DecrementCapturerCount on the WebContents.
+  actuation_mode_runners_.erase(tab_handle);
+
   auto num_removed = tab_handles_.erase(tab_handle);
   if (num_removed > 0) {
     // Notify the UI of the tab removal.
diff --git a/chrome/browser/actor/actor_task.h b/chrome/browser/actor/actor_task.h
index 742387b23..3e4def9b 100644
--- a/chrome/browser/actor/actor_task.h
+++ b/chrome/browser/actor/actor_task.h
@@ -10,12 +10,14 @@
 
 #include "base/callback_list.h"
 #include "base/functional/callback.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/weak_ptr.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/actor/task_id.h"
 #include "chrome/browser/actor/tools/tool_request.h"
 #include "chrome/common/actor.mojom-forward.h"
 #include "components/tabs/public/tab_interface.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
 #include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
 
 class Profile;
@@ -82,7 +84,8 @@
   ExecutionEngine* GetExecutionEngine() const;
 
   // Add/remove the given TabHandle to the set of tabs this task is operating
-  // over and notify the UI if this is a new tab for the task.
+  // over and notify the UI if this is a new tab for the task. Added tabs will
+  // enter actuation mode and be kept as visible.
   using AddTabCallback = base::OnceCallback<void(mojom::ActionResultPtr)>;
   void AddTab(tabs::TabHandle tab, AddTabCallback callback);
   void RemoveTab(tabs::TabHandle tab);
@@ -97,10 +100,18 @@
   // TODO(crbug.com/411462297): This will be replaced by GetTabs soon.
   tabs::TabInterface* GetTabForObservation() const;
 
+  // The set of tabs that have been acted on at any point during this task.
   const absl::flat_hash_set<tabs::TabHandle>& GetTabs() const {
     return tab_handles_;
   }
 
+  // The set of tabs that were acted on by the last call to Act.
+  const absl::flat_hash_set<tabs::TabHandle>& GetLastActedTabs() const {
+    // TODO(bokan): Currently the client only acts on a single tab but this
+    // should track which tabs were acted on in the last call to Act.
+    return tab_handles_;
+  }
+
  private:
   void OnFinishedAct(ActCallback callback,
                      mojom::ActionResultPtr result,
@@ -123,6 +134,12 @@
   // The set of all tabs this task has acted upon.
   absl::flat_hash_set<tabs::TabHandle> tab_handles_;
 
+  // A map from a tab's handle to a ScopedClosureRunner that keeps the tab
+  // in "actuation mode". This is released when the tab is removed from the
+  // task.
+  absl::flat_hash_map<tabs::TabHandle, base::ScopedClosureRunner>
+      actuation_mode_runners_;
+
   base::WeakPtrFactory<ui::UiEventDispatcher> ui_weak_ptr_factory_;
   base::WeakPtrFactory<ActorTask> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/actor/browser_action_util.cc b/chrome/browser/actor/browser_action_util.cc
index 2af5cd3..d54798f 100644
--- a/chrome/browser/actor/browser_action_util.cc
+++ b/chrome/browser/actor/browser_action_util.cc
@@ -4,13 +4,19 @@
 
 #include "chrome/browser/actor/browser_action_util.h"
 
+#include <algorithm>
 #include <cstdint>
+#include <memory>
 #include <optional>
 
+#include "base/barrier_closure.h"
 #include "base/base64.h"
+#include "base/functional/callback_helpers.h"
 #include "base/notimplemented.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/types/expected.h"
+#include "chrome/browser/actor/actor_keyed_service.h"
+#include "chrome/browser/actor/actor_task.h"
 #include "chrome/browser/actor/shared_types.h"
 #include "chrome/browser/actor/tools/attempt_login_tool_request.h"
 #include "chrome/browser/actor/tools/click_tool_request.h"
@@ -25,11 +31,16 @@
 #include "chrome/browser/actor/tools/tool_request.h"
 #include "chrome/browser/actor/tools/type_tool_request.h"
 #include "chrome/browser/actor/tools/wait_tool_request.h"
+#include "chrome/browser/page_content_annotations/multi_source_page_context_fetcher.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/common/actor/action_result.h"
 #include "chrome/common/actor/actor_constants.h"
 #include "chrome/common/actor/actor_logging.h"
 #include "components/optimization_guide/content/browser/page_content_proto_provider.h"
 #include "components/optimization_guide/proto/features/actions_data.pb.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/window_open_disposition.h"
 
@@ -57,6 +68,9 @@
 using apc::TypeAction;
 using apc::WaitAction;
 using ::optimization_guide::DocumentIdentifierUserData;
+using ::page_content_annotations::FetchPageContextOptions;
+using ::page_content_annotations::FetchPageContextResult;
+using ::page_content_annotations::FetchPageContextResultCallbackArg;
 using ::tabs::TabHandle;
 using ::tabs::TabInterface;
 
@@ -541,14 +555,135 @@
   return requests;
 }
 
-optimization_guide::proto::ActionsResult BuildActionsResult(
+apc::TabObservation ConvertToTabObservation(
+    const page_content_annotations::FetchPageContextResult& fetch_result) {
+  apc::TabObservation tab_observation;
+
+  if (fetch_result.screenshot_result) {
+    auto& data = fetch_result.screenshot_result->jpeg_data;
+    if (data.size() != 0) {
+      tab_observation.set_screenshot_mime_type(kMimeTypeJpeg);
+      // TODO(bokan): Can we avoid a copy here?
+      tab_observation.set_screenshot(data.data(), data.size());
+    }
+  }
+
+  if (fetch_result.annotated_page_content_result) {
+    *tab_observation.mutable_annotated_page_content() =
+        fetch_result.annotated_page_content_result->proto;
+  }
+
+  return tab_observation;
+}
+
+namespace {
+
+void FetchCallback(base::RepeatingClosure barrier,
+                   apc::TabObservation* tab_observation,
+                   ActorKeyedService::TabObservationResult result) {
+  base::ScopedClosureRunner run_barrier_at_return(barrier);
+
+  if (!result.has_value()) {
+    // TODO(crbug.com/435210098): There should be some way to message failure to
+    // observe.
+    return;
+  }
+
+  FetchPageContextResult& fetch_result = **result;
+
+  // RequestTabObservation should return an error if these aren't filled in.
+  CHECK(fetch_result.screenshot_result.has_value());
+  CHECK(fetch_result.annotated_page_content_result.has_value());
+
+  *tab_observation = ConvertToTabObservation(fetch_result);
+}
+
+}  // namespace
+
+void BuildActionsResultWithObservations(
+    content::BrowserContext& browser_context,
+    mojom::ActionResultCode result_code,
+    std::optional<size_t> index_of_failed_action,
+    const ActorTask& task,
+    base::OnceCallback<void(std::unique_ptr<apc::ActionsResult>)> callback) {
+  auto response = std::make_unique<apc::ActionsResult>();
+
+  response->set_action_result(static_cast<int32_t>(result_code));
+  if (index_of_failed_action) {
+    response->set_index_of_failed_action(*index_of_failed_action);
+  }
+
+  auto* profile = Profile::FromBrowserContext(&browser_context);
+
+  std::vector<Browser*> browsers = chrome::FindAllTabbedBrowsersWithProfile(
+      profile, /*ignore_closing_browsers=*/true);
+
+  for (Browser* browser : browsers) {
+    apc::WindowObservation* window_observation = response->add_windows();
+    window_observation->set_id(browser->session_id().id());
+    window_observation->set_active(browser->IsActive());
+
+    if (tabs::TabInterface* tab = browser->GetActiveTabInterface()) {
+      window_observation->set_activated_tab_id(tab->GetHandle().raw_value());
+    }
+
+    for (const tabs::TabInterface* tab : *browser->GetTabStripModel()) {
+      window_observation->add_tab_ids(tab->GetHandle().raw_value());
+    }
+  }
+
+  absl::flat_hash_set<tabs::TabInterface*> tabs_to_fetch;
+
+  for (const tabs::TabHandle& handle : task.GetLastActedTabs()) {
+    // Include a TabObservation entry for acted on tabs. If the tab no longer
+    // exists or the fetch context failed, the observation will be empty.
+    // TODO(crbug.com/392167142): Check for a crashed tab here.
+    // TODO(crbug.com/434263095): We should probably avoid capturing
+    // observations if an action fails with kUrlBlocked. That might be better
+    // implemented by not putting the tab into the LastActedTabs set.
+    TabInterface* tab = handle.Get();
+    if (!tab) {
+      // TODO(crbug.com/435210098): There should be some way to message failure
+      // to capture an observation to the model (here and in FetchCallback). For
+      // now we leave the observation empty.
+      apc::TabObservation* tab_observation = response->add_tabs();
+      tab_observation->set_id(handle.raw_value());
+    } else {
+      tabs_to_fetch.insert(tab);
+    }
+  }
+
+  apc::ActionsResult* raw_response = response.get();
+  base::RepeatingClosure barrier = base::BarrierClosure(
+      tabs_to_fetch.size(),
+      base::BindOnce(std::move(callback), std::move(response)));
+
+  auto* actor_service = actor::ActorKeyedService::Get(profile);
+  CHECK(actor_service);
+
+  for (const tabs::TabInterface* tab : tabs_to_fetch) {
+    apc::TabObservation* tab_observation = raw_response->add_tabs();
+    tab_observation->set_id(tab->GetHandle().raw_value());
+
+    // tab_observation can be Unretained because the underlying APC is owned by
+    // the barrier which is ref-counted.
+    actor_service->RequestTabObservation(
+        *tab, base::BindOnce(FetchCallback, barrier,
+                             base::Unretained(tab_observation)));
+  }
+}
+
+apc::ActionsResult BuildErrorActionsResult(
     mojom::ActionResultCode result_code,
     std::optional<size_t> index_of_failed_action) {
-  optimization_guide::proto::ActionsResult response;
+  apc::ActionsResult response;
+  CHECK(!IsOk(result_code));
+
   response.set_action_result(static_cast<int32_t>(result_code));
   if (index_of_failed_action) {
     response.set_index_of_failed_action(*index_of_failed_action);
   }
+
   return response;
 }
 
diff --git a/chrome/browser/actor/browser_action_util.h b/chrome/browser/actor/browser_action_util.h
index 5f233139..431e7e5e 100644
--- a/chrome/browser/actor/browser_action_util.h
+++ b/chrome/browser/actor/browser_action_util.h
@@ -11,6 +11,9 @@
 #include "base/types/expected.h"
 #include "chrome/common/actor.mojom-forward.h"
 #include "components/optimization_guide/proto/features/actions_data.pb.h"
+#include "components/tabs/public/tab_interface.h"
+#include "content/public/browser/browser_context.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
 
 // Conversion function for turning optimization_guide::proto::* types into
 // ToolRequests usable by the actor framework.
@@ -22,13 +25,17 @@
 class BrowserAction;
 }  // namespace optimization_guide::proto
 
-namespace tabs {
-class TabInterface;
-}
+namespace page_content_annotations {
+struct FetchPageContextResult;
+}  // namespace page_content_annotations
 
 namespace actor {
+class ActorTask;
 class ToolRequest;
 
+// The mime type used for screenshots.
+inline constexpr std::string kMimeTypeJpeg = "image/jpeg";
+
 // Build a ToolRequest from the provided optimization_guide Action proto. If the
 // action proto doesn't provide a tab_id, and the fallback_tab parameter is
 // provided (non-null), the fallback_tab will be used as the acting tab.
@@ -59,8 +66,17 @@
     const optimization_guide::proto::Actions& actions);
 
 // Builds the ActionsResult proto from the output of a call to the
-// ActorKeyedService::PerformActions API.
-optimization_guide::proto::ActionsResult BuildActionsResult(
+// ActorKeyedService::PerformActions API and fetches new observations for
+// tabs relevant to the actions.
+void BuildActionsResultWithObservations(
+    content::BrowserContext& browser_context,
+    mojom::ActionResultCode result_code,
+    std::optional<size_t> index_of_failed_action,
+    const ActorTask& task,
+    base::OnceCallback<void(
+        std::unique_ptr<optimization_guide::proto::ActionsResult>)> callback);
+
+optimization_guide::proto::ActionsResult BuildErrorActionsResult(
     mojom::ActionResultCode result_code,
     std::optional<size_t> index_of_failed_action);
 
@@ -72,6 +88,13 @@
     const optimization_guide::proto::BrowserAction& actions,
     tabs::TabInterface* deprecated_fallback_tab);
 
+// Converts a FetchPageContext result to a TabObservation proto. Note that this
+// does not fill in the (tab) `id` field on the proto, the caller is responsible
+// for that.
+optimization_guide::proto::TabObservation ConvertToTabObservation(
+    const page_content_annotations::FetchPageContextResult&
+        page_context_result);
+
 // Builds the BrowserActionResult proto from the output of a call to the
 // ActorKeyedService::ActInFocusedTab API.
 // TODO(https://crbug.com/411462297): Remove this once the BrowserAction path is
diff --git a/chrome/browser/actor/ui/actor_overlay_browsertest.cc b/chrome/browser/actor/ui/actor_overlay_browsertest.cc
index c88e685..cea1ace0 100644
--- a/chrome/browser/actor/ui/actor_overlay_browsertest.cc
+++ b/chrome/browser/actor/ui/actor_overlay_browsertest.cc
@@ -27,6 +27,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 
+namespace actor::ui {
 namespace {
 using actor::mojom::ActionResultPtr;
 using base::test::TestFuture;
@@ -39,6 +40,31 @@
     InProcessBrowserTest::SetUp();
   }
 
+  bool IsActorOverlayVisible(Browser* browser) const {
+    return browser->GetBrowserView()
+        .GetActiveContentsContainerView()
+        ->GetActorOverlayView()
+        ->GetVisible();
+  }
+
+  unsigned int NumActorOverlayChildren(Browser* browser) const {
+    return browser->GetBrowserView()
+        .GetActiveContentsContainerView()
+        ->GetActorOverlayView()
+        ->children()
+        .size();
+  }
+
+  bool IsActorOverlayChildVisible(Browser* browser) const {
+    EXPECT_EQ(NumActorOverlayChildren(browser), 1u)
+        << "Child 0 is not present or extra children are present";
+    return browser->GetBrowserView()
+        .GetActiveContentsContainerView()
+        ->GetActorOverlayView()
+        ->children()[0]
+        ->GetVisible();
+  }
+
  private:
   base::test::ScopedFeatureList feature_list_;
 };
@@ -110,24 +136,14 @@
 
 // Testing the Actor Overlay Window Controller
 IN_PROC_BROWSER_TEST_F(ActorOverlayTest, ViewLifecycleAndVisibility) {
-  actor::ui::ActorOverlayWindowController* window_controller =
+  ActorOverlayWindowController* window_controller =
       browser()->browser_window_features()->actor_overlay_window_controller();
   ASSERT_NE(window_controller, nullptr);
 
   // The main actor_overlay_view container should initially be hidden. It should
   // also have no children.
-  EXPECT_FALSE(browser()
-                   ->GetBrowserView()
-                   .GetActiveContentsContainerView()
-                   ->GetActorOverlayView()
-                   ->GetVisible());
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            0u);
+  EXPECT_FALSE(IsActorOverlayVisible(browser()));
+  EXPECT_EQ(NumActorOverlayChildren(browser()), 0u);
   content::BrowserContext* browser_context =
       browser()->tab_strip_model()->GetActiveWebContents()->GetBrowserContext();
 
@@ -140,29 +156,15 @@
 
   // Verify container size and that it remains hidden because the child is
   // hidden.
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_FALSE(browser()
-                   ->GetBrowserView()
-                   .GetActiveContentsContainerView()
-                   ->GetActorOverlayView()
-                   ->GetVisible());
+  EXPECT_EQ(NumActorOverlayChildren(browser()), 1u);
+  EXPECT_FALSE(IsActorOverlayVisible(browser()));
 
   // Make the added WebView visible, and update the container's visibility.
   overlay_web_view->SetVisible(true);
   window_controller->MaybeUpdateContainerVisibility();
 
   // Container view should now be visible.
-  EXPECT_TRUE(browser()
-                  ->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->GetVisible());
+  EXPECT_TRUE(IsActorOverlayVisible(browser()));
   std::unique_ptr<views::WebView> managed_overlay_web_view =
       window_controller->RemoveChildWebView(overlay_web_view);
   // The raw_ptr to the removed view is now invalid, so set it to nullptr.
@@ -171,177 +173,79 @@
   // Confirm managed WebView is not null and the container should become hidden
   // again
   ASSERT_NE(managed_overlay_web_view, nullptr);
-  EXPECT_FALSE(browser()
-                   ->GetBrowserView()
-                   .GetActiveContentsContainerView()
-                   ->GetActorOverlayView()
-                   ->GetVisible());
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            0u);
+  EXPECT_FALSE(IsActorOverlayVisible(browser()));
+  EXPECT_EQ(NumActorOverlayChildren(browser()), 0u);
 }
 
 IN_PROC_BROWSER_TEST_F(ActorOverlayTest, SendStartEventAndStopEvent) {
   Profile* const profile = browser()->profile();
-  actor::ui::ActorUiStateManagerInterface* state_manager =
-      actor::ActorKeyedService::Get(profile)->GetActorUiStateManager();
+  ActorUiStateManagerInterface* state_manager =
+      ActorKeyedService::Get(profile)->GetActorUiStateManager();
   ASSERT_NE(state_manager, nullptr);
-  // actor::PageTarget page_target(gfx::Point(100, 200));
   tabs::TabHandle tab_handle =
       browser()->tab_strip_model()->GetActiveTab()->GetHandle();
   TestFuture<void> future;
-  actor::ui::ActorUiTabController* controller = browser()
-                                                    ->tab_strip_model()
-                                                    ->GetActiveTab()
-                                                    ->GetTabFeatures()
-                                                    ->actor_ui_tab_controller();
+  ActorUiTabControllerInterface* controller = browser()
+                                                  ->tab_strip_model()
+                                                  ->GetActiveTab()
+                                                  ->GetTabFeatures()
+                                                  ->actor_ui_tab_controller();
   controller->SetCallbackForTesting(future.GetCallback());
   TestFuture<ActionResultPtr> result;
-  state_manager->OnUiEvent(
-      actor::ui::StartingToActOnTab(tab_handle, actor::TaskId(1)),
-      result.GetCallback());
-  actor::ExpectOkResult(result);
+  state_manager->OnUiEvent(StartingToActOnTab(tab_handle, TaskId(1)),
+                           result.GetCallback());
+  ExpectOkResult(result);
   // Ensure callback is done.
   ASSERT_TRUE(future.Wait());
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return browser()
-        ->GetBrowserView()
-        .GetActiveContentsContainerView()
-        ->GetActorOverlayView()
-        ->GetVisible();
-  }));
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_TRUE(browser()
-                  ->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()[0]
-                  ->GetVisible());
-  state_manager->OnUiEvent(actor::ui::StoppedActingOnTab(tab_handle));
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return !browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->GetVisible();
-  }));
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_FALSE(browser()
-                   ->GetBrowserView()
-                   .GetActiveContentsContainerView()
-                   ->GetActorOverlayView()
-                   ->children()[0]
-                   ->GetVisible());
+  ASSERT_TRUE(
+      base::test::RunUntil([&]() { return IsActorOverlayVisible(browser()); }));
+  EXPECT_TRUE(IsActorOverlayChildVisible(browser()));
+  state_manager->OnUiEvent(StoppedActingOnTab(tab_handle));
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return !IsActorOverlayVisible(browser()); }));
+  EXPECT_FALSE(IsActorOverlayChildVisible(browser()));
 }
 
 IN_PROC_BROWSER_TEST_F(ActorOverlayTest, OverlayHidesOnTabBackgrounding) {
   Profile* const profile = browser()->profile();
-  actor::ui::ActorUiStateManagerInterface* state_manager =
-      actor::ActorKeyedService::Get(profile)->GetActorUiStateManager();
+  ActorUiStateManagerInterface* state_manager =
+      ActorKeyedService::Get(profile)->GetActorUiStateManager();
   ASSERT_NE(state_manager, nullptr);
   tabs::TabHandle tab_handle =
       browser()->tab_strip_model()->GetActiveTab()->GetHandle();
   // Set up callback logic.
   TestFuture<void> future;
-  actor::ui::ActorUiTabController* controller = browser()
-                                                    ->tab_strip_model()
-                                                    ->GetActiveTab()
-                                                    ->GetTabFeatures()
-                                                    ->actor_ui_tab_controller();
+  ActorUiTabControllerInterface* controller = browser()
+                                                  ->tab_strip_model()
+                                                  ->GetActiveTab()
+                                                  ->GetTabFeatures()
+                                                  ->actor_ui_tab_controller();
   controller->SetCallbackForTesting(future.GetCallback());
   TestFuture<ActionResultPtr> result;
-  state_manager->OnUiEvent(
-      actor::ui::StartingToActOnTab(tab_handle, actor::TaskId(1)),
-      result.GetCallback());
-  actor::ExpectOkResult(result);
+  state_manager->OnUiEvent(StartingToActOnTab(tab_handle, TaskId(1)),
+                           result.GetCallback());
+  ExpectOkResult(result);
   // Ensure callback is done.
   ASSERT_TRUE(future.Wait());
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return browser()
-        ->GetBrowserView()
-        .GetActiveContentsContainerView()
-        ->GetActorOverlayView()
-        ->GetVisible();
-  }));
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_TRUE(browser()
-                  ->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()[0]
-                  ->GetVisible());
+  ASSERT_TRUE(
+      base::test::RunUntil([&]() { return IsActorOverlayVisible(browser()); }));
+  EXPECT_TRUE(IsActorOverlayChildVisible(browser()));
   browser()->tab_strip_model()->AppendWebContents(
       content::WebContents::Create(content::WebContents::CreateParams(profile)),
       /*foreground=*/true);
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return !browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->GetVisible();
-  }));
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_FALSE(browser()
-                   ->GetBrowserView()
-                   .GetActiveContentsContainerView()
-                   ->GetActorOverlayView()
-                   ->children()[0]
-                   ->GetVisible());
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return !IsActorOverlayVisible(browser()); }));
+  EXPECT_FALSE(IsActorOverlayChildVisible(browser()));
   browser()->tab_strip_model()->ActivateTabAt(0);
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return browser()
-        ->GetBrowserView()
-        .GetActiveContentsContainerView()
-        ->GetActorOverlayView()
-        ->GetVisible();
-  }));
-  EXPECT_EQ(browser()
-                ->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
-  EXPECT_TRUE(browser()
-                  ->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()[0]
-                  ->GetVisible());
+  ASSERT_TRUE(
+      base::test::RunUntil([&]() { return IsActorOverlayVisible(browser()); }));
+  EXPECT_TRUE(IsActorOverlayChildVisible(browser()));
 }
 
 IN_PROC_BROWSER_TEST_F(ActorOverlayTest, RepeatedlyMoveTabBetweenWindows) {
   Profile* const profile = browser()->profile();
-  actor::ui::ActorUiStateManagerInterface* state_manager =
-      actor::ActorKeyedService::Get(profile)->GetActorUiStateManager();
+  ActorUiStateManagerInterface* state_manager =
+      ActorKeyedService::Get(profile)->GetActorUiStateManager();
   ASSERT_NE(state_manager, nullptr);
   // Initial tab setup: Create 3 tabs in the starting browser window.
   ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
@@ -353,7 +257,7 @@
 
   // Set up callback logic after tab_2 is created.
   TestFuture<void> future;
-  actor::ui::ActorUiTabController* controller =
+  ActorUiTabControllerInterface* controller =
       tab_2->GetTabFeatures()->actor_ui_tab_controller();
   controller->SetCallbackForTesting(future.GetCallback());
 
@@ -378,18 +282,13 @@
   // Start actor actuation on tab_2, which is in browser_1.
   // This should make the Actor Overlay visible in browser_1.
   TestFuture<ActionResultPtr> result;
-  state_manager->OnUiEvent(
-      actor::ui::StartingToActOnTab(tab_2->GetHandle(), actor::TaskId(1)),
-      result.GetCallback());
-  actor::ExpectOkResult(result);
+  state_manager->OnUiEvent(StartingToActOnTab(tab_2->GetHandle(), TaskId(1)),
+                           result.GetCallback());
+  ExpectOkResult(result);
   // Ensure callback is done.
   ASSERT_TRUE(future.Wait());
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return browser_1->GetBrowserView()
-        .GetActiveContentsContainerView()
-        ->GetActorOverlayView()
-        ->GetVisible();
-  }));
+  ASSERT_TRUE(
+      base::test::RunUntil([&]() { return IsActorOverlayVisible(browser_1); }));
   // Loop to repeatedly move the actuated tab between the two windows.
   // This verifies the overlay's persistence and correct re-parenting across
   // window changes. The number of iterations (10) is arbitrary and can be
@@ -405,44 +304,22 @@
     // the new browser.
     chrome::MoveTabsToExistingWindow(source_browser, target_browser, {1});
     // Verify the overlay is visible in the *new* browser holding tab_2.
-    ASSERT_TRUE(base::test::RunUntil([&]() {
-      return target_browser->GetBrowserView()
-          .GetActiveContentsContainerView()
-          ->GetActorOverlayView()
-          ->GetVisible();
-    }));
+    ASSERT_TRUE(base::test::RunUntil(
+        [&]() { return IsActorOverlayVisible(target_browser); }));
     // Verify the overlay's child WebView was correctly detached from the source
     // browser window.
-    EXPECT_EQ(source_browser->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()
-                  .size(),
-              0u);
+    EXPECT_EQ(NumActorOverlayChildren(source_browser), 0u);
     // Verify the WebView was correctly re-attached to the target browser window
     // and is visible.
-    ASSERT_EQ(target_browser->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()
-                  .size(),
-              1u);
-    EXPECT_TRUE(base::test::RunUntil([&]() {
-      return target_browser->GetBrowserView()
-          .GetActiveContentsContainerView()
-          ->GetActorOverlayView()
-          ->children()[0]
-          ->GetVisible();
-    }));
+    ASSERT_EQ(NumActorOverlayChildren(target_browser), 1u);
+    EXPECT_TRUE(base::test::RunUntil(
+        [&]() { return IsActorOverlayChildVisible(target_browser); }));
   }
   // Stop acting on the tab at the end of the test
-  state_manager->OnUiEvent(actor::ui::StoppedActingOnTab(tab_2->GetHandle()));
+  state_manager->OnUiEvent(StoppedActingOnTab(tab_2->GetHandle()));
   ASSERT_TRUE(base::test::RunUntil([&]() {
     // Overlay should become invisible in the browser that currently holds tab_1
-    return !target_browser->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->GetVisible();
+    return !IsActorOverlayVisible(target_browser);
   }));
   // Verify that stopping actuation only hides the child WebView, but does not
   // destroy it or remove it from the view hierarchy.
@@ -463,8 +340,8 @@
 
 IN_PROC_BROWSER_TEST_F(ActorOverlayTest, RepeatedlyMoveActuatedTabToNewWindow) {
   Profile* const profile = browser()->profile();
-  actor::ui::ActorUiStateManagerInterface* state_manager =
-      actor::ActorKeyedService::Get(profile)->GetActorUiStateManager();
+  ActorUiStateManagerInterface* state_manager =
+      ActorKeyedService::Get(profile)->GetActorUiStateManager();
   ASSERT_NE(state_manager, nullptr);
   // Initial tab setup: Start with one tab.
   ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
@@ -472,14 +349,13 @@
   ASSERT_NE(tab_1, nullptr);
   // Set up callback logic after tab_1 is created.
   TestFuture<void> future;
-  actor::ui::ActorUiTabController* controller =
+  ActorUiTabControllerInterface* controller =
       tab_1->GetTabFeatures()->actor_ui_tab_controller();
   controller->SetCallbackForTesting(future.GetCallback());
   TestFuture<ActionResultPtr> result;
-  state_manager->OnUiEvent(
-      actor::ui::StartingToActOnTab(tab_1->GetHandle(), actor::TaskId(1)),
-      result.GetCallback());
-  actor::ExpectOkResult(result);
+  state_manager->OnUiEvent(StartingToActOnTab(tab_1->GetHandle(), TaskId(1)),
+                           result.GetCallback());
+  ExpectOkResult(result);
   // Ensure callback is done.
   ASSERT_TRUE(future.Wait());
   Browser* browser_with_actuated_tab;
@@ -494,25 +370,12 @@
             ->browser();
     ASSERT_NE(browser_with_actuated_tab, nullptr);
     // Verify the overlay is visible in the current browser.
-    ASSERT_TRUE(base::test::RunUntil([&]() {
-      return browser_with_actuated_tab->GetBrowserView()
-          .GetActiveContentsContainerView()
-          ->GetActorOverlayView()
-          ->GetVisible();
-    }));
+    ASSERT_TRUE(base::test::RunUntil(
+        [&]() { return IsActorOverlayVisible(browser_with_actuated_tab); }));
     // Also verify that the overlay's child WebView exists and is visible.
-    ASSERT_EQ(browser_with_actuated_tab->GetBrowserView()
-                  .GetActiveContentsContainerView()
-                  ->GetActorOverlayView()
-                  ->children()
-                  .size(),
-              1u);
+    ASSERT_EQ(NumActorOverlayChildren(browser_with_actuated_tab), 1u);
     EXPECT_TRUE(base::test::RunUntil([&]() {
-      return browser_with_actuated_tab->GetBrowserView()
-          .GetActiveContentsContainerView()
-          ->GetActorOverlayView()
-          ->children()[0]
-          ->GetVisible();
+      return IsActorOverlayChildVisible(browser_with_actuated_tab);
     }));
     // Add a new tab to ensure the source window always has at least two tabs
     // before moving one to a new window (simulates user behavior).
@@ -529,29 +392,16 @@
           ->AsBrowserView()
           ->browser();
   // Stop acting on the tab at the end of the test.
-  state_manager->OnUiEvent(actor::ui::StoppedActingOnTab(tab_1->GetHandle()));
+  state_manager->OnUiEvent(StoppedActingOnTab(tab_1->GetHandle()));
   // Overlay should become invisible in the browser that currently holds the
   // actuated tab.
-  ASSERT_TRUE(base::test::RunUntil([&]() {
-    return !browser_with_actuated_tab->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->GetVisible();
-  }));
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return !IsActorOverlayVisible(browser_with_actuated_tab); }));
   // Verify that stopping actuation only hides the child WebView, but does not
   // destroy it or remove it from the view hierarchy.
-  ASSERT_EQ(browser_with_actuated_tab->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()
-                .size(),
-            1u);
+  ASSERT_EQ(NumActorOverlayChildren(browser_with_actuated_tab), 1u);
   EXPECT_TRUE(base::test::RunUntil([&]() {
-    return !browser_with_actuated_tab->GetBrowserView()
-                .GetActiveContentsContainerView()
-                ->GetActorOverlayView()
-                ->children()[0]
-                ->GetVisible();
+    return !IsActorOverlayChildVisible(browser_with_actuated_tab);
   }));
 }
 
@@ -637,3 +487,4 @@
 }
 
 }  // namespace
+}  // namespace actor::ui
diff --git a/chrome/browser/actor/ui/actor_overlay_ui.cc b/chrome/browser/actor/ui/actor_overlay_ui.cc
index a061c98..c966870 100644
--- a/chrome/browser/actor/ui/actor_overlay_ui.cc
+++ b/chrome/browser/actor/ui/actor_overlay_ui.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/actor/ui/actor_overlay_ui.h"
 
-#include "chrome/browser/actor/ui/actor_ui_tab_controller.h"
+#include "chrome/browser/actor/ui/actor_ui_tab_controller_interface.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/webui/webui_embedding_context.h"
@@ -37,7 +37,7 @@
     mojo::PendingReceiver<mojom::ActorOverlayPageHandler> receiver) {
   content::WebContents* web_contents = web_ui()->GetWebContents();
   tabs::TabInterface* tab_interface = webui::GetTabInterface(web_contents);
-  ActorUiTabController* actor_ui_tab_controller =
+  ActorUiTabControllerInterface* actor_ui_tab_controller =
       tab_interface->GetTabFeatures()->actor_ui_tab_controller();
   CHECK(actor_ui_tab_controller);
   actor_ui_tab_controller->BindActorOverlay(std::move(receiver));
diff --git a/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc b/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc
index bce6d0c..a34bc86 100644
--- a/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc
+++ b/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc
@@ -86,10 +86,13 @@
 
   std::unique_ptr<KeyedService> BuildActorKeyedService(
       content::BrowserContext* context) {
-    auto actor_keyed_service =
-        std::make_unique<ActorKeyedServiceFake>(static_cast<Profile*>(context));
-    std::unique_ptr<ActorUiStateManagerInterface> actor_ui_state_manager_fake =
+    Profile* profile = Profile::FromBrowserContext(context);
+    auto actor_keyed_service = std::make_unique<ActorKeyedServiceFake>(profile);
+    actor_keyed_service_fake_ = actor_keyed_service.get();
+
+    auto actor_ui_state_manager_fake =
         std::make_unique<ActorUiStateManagerFake>(*actor_keyed_service);
+    actor_ui_state_manager_fake_ = actor_ui_state_manager_fake.get();
     actor_keyed_service->SetActorUiStateManagerForTesting(
         std::move(actor_ui_state_manager_fake));
     return std::move(actor_keyed_service);
@@ -106,13 +109,11 @@
   }
 
   ActorUiStateManagerFake* actor_ui_state_manager() {
-    return static_cast<ActorUiStateManagerFake*>(
-        ActorKeyedService::Get(profile())->GetActorUiStateManager());
+    return actor_ui_state_manager_fake_;
   }
 
   ActorKeyedServiceFake* actor_keyed_service() {
-    return static_cast<ActorKeyedServiceFake*>(
-        ActorKeyedService::Get(profile()));
+    return actor_keyed_service_fake_;
   }
 
   content::BrowserTaskEnvironment& task_environment() {
@@ -151,6 +152,8 @@
  private:
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<TestingProfile> profile_;
+  raw_ptr<ActorKeyedServiceFake> actor_keyed_service_fake_;
+  raw_ptr<ActorUiStateManagerFake> actor_ui_state_manager_fake_;
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<MockBrowserWindowInterface> browser_window_interface_;
 };
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller.h b/chrome/browser/actor/ui/actor_ui_tab_controller.h
index b90cf57..373fd7c 100644
--- a/chrome/browser/actor/ui/actor_ui_tab_controller.h
+++ b/chrome/browser/actor/ui/actor_ui_tab_controller.h
@@ -49,7 +49,7 @@
   void SetActorTaskResume() override;
   void SetOverlayHoverStatus(bool is_hovering) override;
   void SetHandoffButtonHoverStatus(bool is_hovering) override;
-  void SetCallbackForTesting(base::OnceClosure callback);
+  void SetCallbackForTesting(base::OnceClosure callback) override;
 
   // Binds the Mojo receiver to the tab's ActorOverlayViewController.
   // Called by ActorOverlayUI when the chrome://actor-overlay page loads.
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller_interface.h b/chrome/browser/actor/ui/actor_ui_tab_controller_interface.h
index df36a21..7724fdd 100644
--- a/chrome/browser/actor/ui/actor_ui_tab_controller_interface.h
+++ b/chrome/browser/actor/ui/actor_ui_tab_controller_interface.h
@@ -77,6 +77,9 @@
   virtual base::WeakPtr<ActorUiTabControllerInterface> GetWeakPtr() = 0;
   virtual void BindActorOverlay(
       mojo::PendingReceiver<mojom::ActorOverlayPageHandler> receiver) = 0;
+
+  // Sets a callback to run when the controller is idle, for tests.
+  virtual void SetCallbackForTesting(base::OnceClosure callback) = 0;
 };
 
 }  // namespace actor::ui
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller_unittest.cc b/chrome/browser/actor/ui/actor_ui_tab_controller_unittest.cc
index 9d5f60ae..d844f58 100644
--- a/chrome/browser/actor/ui/actor_ui_tab_controller_unittest.cc
+++ b/chrome/browser/actor/ui/actor_ui_tab_controller_unittest.cc
@@ -109,7 +109,7 @@
     return actor_keyed_service_.get();
   }
 
-  ActorUiTabController* tab_controller() {
+  ActorUiTabControllerInterface* tab_controller() {
     return actor_ui_tab_controller_.get();
   }
 
diff --git a/chrome/browser/actor/ui/mock_actor_ui_tab_controller.h b/chrome/browser/actor/ui/mock_actor_ui_tab_controller.h
index f510826..5abfab0 100644
--- a/chrome/browser/actor/ui/mock_actor_ui_tab_controller.h
+++ b/chrome/browser/actor/ui/mock_actor_ui_tab_controller.h
@@ -50,6 +50,11 @@
               (mojo::PendingReceiver<mojom::ActorOverlayPageHandler> receiver),
               (override));
 
+  MOCK_METHOD(void,
+              SetCallbackForTesting,
+              (base::OnceClosure callback),
+              (override));
+
  private:
   base::WeakPtrFactory<MockActorUiTabController> weak_factory_{this};
 };
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
index 94b1521..6f688d81 100644
--- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -299,8 +299,7 @@
         base::StringPrintf("onAppMessage('%s');", message.c_str())));
   }
 
-  void SetupTest(const std::string& app_name,
-                 const std::string& guest_url_spec) {
+  void SetupTest(const std::string& app_name) {
     ASSERT_TRUE(StartEmbeddedTestServer());
 
     LoadAndLaunchPlatformApp(app_name.c_str(), "connected");
@@ -572,8 +571,7 @@
 #define MAYBE_PointerLock DISABLED_PointerLock
 #endif
 IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest, MAYBE_PointerLock) {
-  SetupTest("web_view/pointer_lock",
-            "/extensions/platform_apps/web_view/pointer_lock/guest.html");
+  SetupTest("web_view/pointer_lock");
 
   // Move the mouse over the Lock Pointer button.
   ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
@@ -643,8 +641,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest,
                        MAYBE_PointerLockFocus) {
-  SetupTest("web_view/pointer_lock_focus",
-            "/extensions/platform_apps/web_view/pointer_lock_focus/guest.html");
+  SetupTest("web_view/pointer_lock_focus");
 
   // Move the mouse over the Lock Pointer button.
   ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
@@ -879,9 +876,7 @@
 // Tests that guests receive edit commands and respond appropriately.
 IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, EditCommandsNoMenu) {
   ExtensionTestMessageListener focus_listener("Focused");
-  SetupTest("web_view/edit_commands_no_menu",
-            "/extensions/platform_apps/web_view/edit_commands_no_menu/"
-            "guest.html");
+  SetupTest("web_view/edit_commands_no_menu");
   ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
   // Ensure that an input gets focused before sending a key event.
   ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
diff --git a/chrome/browser/ash/app_restore/BUILD.gn b/chrome/browser/ash/app_restore/BUILD.gn
index a5d17bd..e1c3af3 100644
--- a/chrome/browser/ash/app_restore/BUILD.gn
+++ b/chrome/browser/ash/app_restore/BUILD.gn
@@ -96,6 +96,7 @@
     "//chrome/browser/lifetime:termination_notification",
     "//chrome/browser/prefs:util",
     "//chrome/browser/ui:browser_navigator_params_headers",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/startup:startup_tab",
     "//chrome/browser/web_applications",
     "//chrome/common:chrome_features",
diff --git a/chrome/browser/ash/dbus/BUILD.gn b/chrome/browser/ash/dbus/BUILD.gn
index 9efd0d2..eef94f2 100644
--- a/chrome/browser/ash/dbus/BUILD.gn
+++ b/chrome/browser/ash/dbus/BUILD.gn
@@ -114,7 +114,6 @@
     "//chromeos/ash/components/dbus/device_management",
     "//chromeos/ash/components/dbus/dlcservice",
     "//chromeos/ash/components/dbus/easy_unlock",
-    "//chromeos/ash/components/dbus/featured",
     "//chromeos/ash/components/dbus/gnubby",
     "//chromeos/ash/components/dbus/hermes",
     "//chromeos/ash/components/dbus/human_presence",
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc
index 2edc97b0..0f52f66 100644
--- a/chrome/browser/ash/dbus/ash_dbus_helper.cc
+++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -41,7 +41,6 @@
 #include "chromeos/ash/components/dbus/device_management/install_attributes_client.h"
 #include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/ash/components/dbus/easy_unlock/easy_unlock_client.h"
-#include "chromeos/ash/components/dbus/featured/featured_client.h"
 #include "chromeos/ash/components/dbus/gnubby/gnubby_client.h"
 #include "chromeos/ash/components/dbus/hermes/hermes_clients.h"
 #include "chromeos/ash/components/dbus/human_presence/human_presence_dbus_client.h"
@@ -263,10 +262,6 @@
       features::IsQuickDimEnabled()) {
     InitializeDBusClient<HumanPresenceDBusClient>(bus);
   }
-
-  // FeaturedClient is not a feature and instead uses the FieldTrialList (which
-  // is initialized with the FeatureList) to record early-boot trials in UMA.
-  InitializeDBusClient<featured::FeaturedClient>(bus);
 }
 
 void ShutdownDBus() {
@@ -337,7 +332,6 @@
   ImageBurnerClient::Shutdown();
   hermes_clients::Shutdown();
   GnubbyClient::Shutdown();
-  featured::FeaturedClient::Shutdown();
   EasyUnlockClient::Shutdown();
   DlcserviceClient::Shutdown();
   chromeos::DlpClient::Shutdown();
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
index 9884d01..f5d60fd 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
@@ -10,23 +10,28 @@
 
 #include "base/check.h"
 #include "base/check_deref.h"
+#include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/strings/strcat.h"
-#include "chrome/browser/ash/app_mode/fake_cws.h"
-#include "chrome/browser/ash/app_mode/test/kiosk_mixin.h"
-#include "chrome/browser/ash/app_mode/test/kiosk_test_utils.h"
-#include "chrome/browser/ash/login/test/device_state_mixin.h"
-#include "chrome/browser/ash/login/test/scoped_policy_update.h"
+#include "base/path_service.h"
+#include "chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.h"
+#include "chrome/browser/ash/policy/test_support/embedded_policy_test_server_mixin.h"
 #include "chrome/browser/policy/extension_force_install_mixin.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "extensions/test/extension_test_message_listener.h"
+#include "device_management_backend.pb.h"
+#include "extensions/common/extension_id.h"
+#include "net/http/http_status_code.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ime/ash/input_method_manager.h"
@@ -42,35 +47,49 @@
 constexpr std::string_view kBrPorMethodId = "xkb:br::por";
 constexpr std::string_view kFrFraMethodId = "xkb:fr::fra";
 
-// Corresponds to the Chrome extension under:
-// //chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src
-//
-// This extension exercises the `chrome.enterprise.kioskInput` API.
-constexpr std::string_view kExtensionId = "elhlgakmbkdkoajdlnfkhjbpgmbpjdig";
+constexpr std::string_view kCompanionExtensionId =
+    "pogfhljmaechjalhkendaaoldheklnmk";
 
-// Serves the input extension in `fake_cws` and configures `user_policy`` to
-// force install it.
-void ConfigureInputExtension(FakeCWS& fake_cws,
-                             ScopedUserPolicyUpdate& user_policy) {
-  constexpr std::string_view kVersion = "1.0.0";
-  auto crx_file = base::StrCat({kExtensionId, "-", kVersion, ".crx"});
+std::unique_ptr<net::test_server::HttpResponse> ServeSimpleHtmlPage(
+    const net::test_server::HttpRequest& request) {
+  auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+  response->set_code(net::HTTP_OK);
+  response->set_content_type("text/html");
+  response->set_content(
+      "<!DOCTYPE html>"
+      "<html lang=\"en\">"
+      "<head><title>Test Page</title></head>"
+      "<body>A simple kiosk web page.</body>"
+      "</html>");
+  return response;
+}
 
-  fake_cws.SetUpdateCrx(kExtensionId, crx_file, kVersion);
-  user_policy.policy_payload()
-      ->mutable_extensioninstallforcelist()
-      ->mutable_value()
-      ->add_entries(kExtensionId);
+void SetUpDeviceLocalAccountPolicy(
+    const std::string& account_id,
+    policy::UserPolicyBuilder& user_policy_builder) {
+  enterprise_management::PolicyData& policy_data =
+      user_policy_builder.policy_data();
+  policy_data.set_public_key_version(1);
+  policy_data.set_policy_type(
+      policy::dm_protocol::kChromePublicAccountPolicyType);
+  policy_data.set_username(account_id);
+  policy_data.set_settings_entity_id(account_id);
+  user_policy_builder.SetDefaultSigningKey();
+
+  auto& session_manager = CHECK_DEREF(FakeSessionManagerClient::Get());
+  session_manager.set_device_local_account_policy(
+      std::string(account_id), user_policy_builder.GetBlob());
 }
 
 std::string CurrentInputMethod() {
-  auto& manager = CHECK_DEREF(InputMethodManager::Get());
+  InputMethodManager& manager = CHECK_DEREF(InputMethodManager::Get());
   InputMethodManager::State& state =
       CHECK_DEREF(manager.GetActiveIMEState().get());
   return state.GetCurrentInputMethod().id();
 }
 
 std::string ToExtensionBasedInputMethod(std::string_view method) {
-  auto& manager = CHECK_DEREF(InputMethodManager::Get());
+  InputMethodManager& manager = CHECK_DEREF(InputMethodManager::Get());
   std::vector<std::string> extension_based_input_methods{std::string(method)};
   CHECK(manager.GetMigratedInputMethodIDs(&extension_based_input_methods));
   return extension_based_input_methods[0];
@@ -81,7 +100,7 @@
 }
 
 bool EnableInputMethods(const std::vector<std::string_view>& methods) {
-  auto& manager = CHECK_DEREF(InputMethodManager::Get());
+  InputMethodManager& manager = CHECK_DEREF(InputMethodManager::Get());
   InputMethodManager::State& state =
       CHECK_DEREF(manager.GetActiveIMEState().get());
   std::vector<std::string> extension_based_input_methods(methods.begin(),
@@ -97,7 +116,8 @@
     chrome.runtime.sendMessage($1, { message: $2, data: $3 })
   )";
   return content::EvalJs(
-      &web_contents, content::JsReplace(kScript, kExtensionId, message, data));
+      &web_contents,
+      content::JsReplace(kScript, kCompanionExtensionId, message, data));
 }
 
 content::EvalJsResult IsExtensionApiAvailable(
@@ -120,15 +140,9 @@
          std::string(input_method) + ".";
 }
 
-// The app used to configure `KioskMixin`.
-KioskMixin::DefaultServerWebAppOption AppInConfig() {
-  return KioskMixin::SimpleWebAppOption();
-}
-
 }  // namespace
 
-class KioskEnterpriseInputApiBrowserTest
-    : public MixinBasedInProcessBrowserTest {
+class KioskEnterpriseInputApiBrowserTest : public WebKioskBaseTest {
  public:
   KioskEnterpriseInputApiBrowserTest() = default;
   KioskEnterpriseInputApiBrowserTest(
@@ -138,26 +152,21 @@
 
   ~KioskEnterpriseInputApiBrowserTest() override = default;
 
+ protected:
   void SetUpInProcessBrowserTestFixture() override {
-    MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
-    ConfigureInputExtension(
-        kiosk_.fake_cws(),
-        *kiosk_.device_state_mixin().RequestDeviceLocalAccountPolicyUpdate(
-            AppInConfig().account_id));
+    WebKioskBaseTest::SetUpInProcessBrowserTestFixture();
+    SetUpDeviceLocalAccountPolicy(app_account_id(),
+                                  device_local_acount_policy_builder_);
   }
 
   void SetUpOnMainThread() override {
-    MixinBasedInProcessBrowserTest::SetUpOnMainThread();
-    ExtensionTestMessageListener extension_ready("ready");
-    extension_ready.set_extension_id(std::string(kExtensionId));
-    ASSERT_TRUE(kiosk::test::WaitKioskLaunched());
-    // `chrome.runtime` only gets defined once the page finishes loading.
-    content::TestNavigationObserver(&GetAppWebContents())
-        .WaitForNavigationFinished();
-    ASSERT_TRUE(extension_ready.WaitUntilSatisfied());
+    InitializeWebAppServer();
+    WebKioskBaseTest::SetUpOnMainThread();
+    InitializeRegularOnlineKiosk();
+    ForceInstallAndWaitExtensionReady();
   }
 
-  content::WebContents& GetAppWebContents() {
+  content::WebContents& app_web_contents() {
     SelectFirstBrowser();
     BrowserView* browser_view =
         BrowserView::GetBrowserViewForBrowser(browser());
@@ -165,16 +174,55 @@
   }
 
  private:
-  KioskMixin kiosk_{&mixin_host_,
-                    /*cached_configuration=*/
-                    {/*name=*/{},
-                     KioskMixin::AutoLaunchAccount{AppInConfig().account_id},
-                     {AppInConfig()}}};
+  void InitializeWebAppServer() {
+    web_app_server_.RegisterRequestHandler(
+        base::BindRepeating(&ServeSimpleHtmlPage));
+    ASSERT_TRUE(web_app_server_handle_ =
+                    web_app_server_.StartAndReturnHandle());
+    SetAppInstallUrl(web_app_server_.base_url());
+  }
+
+  void ForceInstallAndWaitExtensionReady() {
+    constexpr std::string_view kCompanionExtensionPath =
+        "extensions/api_test/enterprise_kiosk_input/";
+    constexpr std::string_view kCompanionExtensionPemPath =
+        "extensions/api_test/enterprise_kiosk_input.pem";
+    base::FilePath test_data_dir =
+        base::PathService::CheckedGet(chrome::DIR_TEST_DATA);
+
+    extension_force_install_mixin_.InitWithEmbeddedPolicyMixin(
+        &app_profile(), &policy_test_server_mixin_,
+        &device_local_acount_policy_builder_,
+        /*account_id=*/app_account_id(),
+        /*policy_type=*/policy::dm_protocol::kChromePublicAccountPolicyType);
+
+    extensions::ExtensionId extension_id;
+    bool did_install = extension_force_install_mixin_.ForceInstallFromSourceDir(
+        test_data_dir.AppendASCII(kCompanionExtensionPath),
+        test_data_dir.AppendASCII(kCompanionExtensionPemPath),
+        ExtensionForceInstallMixin::WaitMode::kReadyMessageReceived,
+        &extension_id);
+    ASSERT_TRUE(did_install);
+    ASSERT_EQ(kCompanionExtensionId, extension_id);
+  }
+
+  std::string app_account_id() { return web_app_server_.base_url().spec(); }
+
+  Profile& app_profile() {
+    return CHECK_DEREF(ProfileManager::GetPrimaryUserProfile());
+  }
+
+  net::test_server::EmbeddedTestServer web_app_server_;
+  net::test_server::EmbeddedTestServerHandle web_app_server_handle_;
+
+  policy::UserPolicyBuilder device_local_acount_policy_builder_;
+  EmbeddedPolicyTestServerMixin policy_test_server_mixin_{&mixin_host_};
+  ExtensionForceInstallMixin extension_force_install_mixin_{&mixin_host_};
 };
 
 IN_PROC_BROWSER_TEST_F(KioskEnterpriseInputApiBrowserTest,
                        CompanionExtensionCanAccessApi) {
-  ASSERT_EQ(true, IsExtensionApiAvailable(GetAppWebContents()));
+  ASSERT_EQ(true, IsExtensionApiAvailable(app_web_contents()));
 }
 
 IN_PROC_BROWSER_TEST_F(KioskEnterpriseInputApiBrowserTest,
@@ -194,7 +242,7 @@
   EXPECT_THAT(CurrentInputMethod(), HasMethodId(kUsEngMethodId));
 
   EXPECT_EQ(true,
-            SetInputMethodViaExtension(GetAppWebContents(), enabled_method_id));
+            SetInputMethodViaExtension(app_web_contents(), enabled_method_id));
   EXPECT_THAT(CurrentInputMethod(), HasMethodId(enabled_method_id));
 }
 
@@ -205,9 +253,8 @@
   EXPECT_THAT(CurrentInputMethod(), HasMethodId(kUsEngMethodId));
 
   std::string_view disabled_method_id = kBrPorMethodId;
-  EXPECT_EQ(
-      CouldNotChangeInputError(disabled_method_id),
-      SetInputMethodViaExtension(GetAppWebContents(), disabled_method_id));
+  EXPECT_EQ(CouldNotChangeInputError(disabled_method_id),
+            SetInputMethodViaExtension(app_web_contents(), disabled_method_id));
   EXPECT_THAT(CurrentInputMethod(), HasMethodId(kUsEngMethodId));
 }
 
diff --git a/chrome/browser/ash/login/session/BUILD.gn b/chrome/browser/ash/login/session/BUILD.gn
index fc4b7b9..e8426f09 100644
--- a/chrome/browser/ash/login/session/BUILD.gn
+++ b/chrome/browser/ash/login/session/BUILD.gn
@@ -69,6 +69,7 @@
     "//chrome/browser/prefs:util",
     "//chrome/browser/screen_ai:screen_ai_dlc_installer",
     "//chrome/browser/signin",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/webui/ash/shimless_rma_dialog",
     "//chrome/common",
     "//chrome/common:channel_info",
diff --git a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
index 2a4ad65..d296396 100644
--- a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
+++ b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
@@ -193,8 +193,11 @@
 auto IsWithinAutofillLimits() {
   auto frequencies = [](const FormStructure& form) {
     std::map<FieldType, size_t> counts;
-    for (const auto& field : form)
-      ++counts[field->Type().GetStorableType()];
+    for (const auto& field : form) {
+      for (FieldType field_type : field->Type().GetTypes()) {
+        ++counts[field_type];
+      }
+    }
     return counts;
   };
   return ResultOf(frequencies,
diff --git a/chrome/browser/bluetooth/android/junit/src/org/chromium/chrome/browser/bluetooth/BluetoothNotificationManagerTest.java b/chrome/browser/bluetooth/android/junit/src/org/chromium/chrome/browser/bluetooth/BluetoothNotificationManagerTest.java
index 4f4ff62..0d4b578 100644
--- a/chrome/browser/bluetooth/android/junit/src/org/chromium/chrome/browser/bluetooth/BluetoothNotificationManagerTest.java
+++ b/chrome/browser/bluetooth/android/junit/src/org/chromium/chrome/browser/bluetooth/BluetoothNotificationManagerTest.java
@@ -13,9 +13,11 @@
 import android.content.Intent;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Features.EnableFeatures;
@@ -38,6 +40,7 @@
     private static final String TEST_URL_FORMATTED =
             UrlFormatter.formatUrlForSecurityDisplay(TEST_URL, SchemeDisplay.OMIT_HTTP_AND_HTTPS);
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private MockNotificationManagerProxy mMockNotificationManager;
     private final BluetoothNotificationManagerDelegate mDelegate =
             new BluetoothNotificationManagerDelegate() {
@@ -96,8 +99,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mMockNotificationManager = new MockNotificationManagerProxy();
         BaseNotificationManagerProxyFactory.setInstanceForTesting(mMockNotificationManager);
         mManager = new BluetoothNotificationManager(mDelegate);
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegateTest.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegateTest.java
index babdcb9..2a795d9 100644
--- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegateTest.java
+++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegateTest.java
@@ -13,11 +13,13 @@
 import android.os.SystemClock;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 
@@ -30,6 +32,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class BrowserStateBrowserControlsVisibilityDelegateTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Callback<Integer> mCallback;
 
     private BrowserStateBrowserControlsVisibilityDelegate mDelegate;
@@ -37,8 +40,6 @@
 
     @Before
     public void beforeTest() {
-        MockitoAnnotations.initMocks(this);
-
         mPersistentModeSupplier = new ObservableSupplierImpl<>();
         mPersistentModeSupplier.set(false);
 
diff --git a/chrome/browser/compose/compose_text_usage_logger.cc b/chrome/browser/compose/compose_text_usage_logger.cc
index d0c0064..3babf42 100644
--- a/chrome/browser/compose/compose_text_usage_logger.cc
+++ b/chrome/browser/compose/compose_text_usage_logger.cc
@@ -82,7 +82,7 @@
     autofill::FormGlobalId form,
     autofill::FieldGlobalId field,
     const std::u16string& text_value) {
-  autofill::FormType form_type = autofill::FormType::kUnknownFormType;
+  autofill::DenseSet<autofill::FormType> form_types;
   int64_t form_control_type = -1;
   autofill::FieldSignature field_signature;
   autofill::FormSignature form_signature;
@@ -93,7 +93,7 @@
     const autofill::AutofillField* field_data =
         form_structure->GetFieldById(field);
     if (field_data) {
-      form_type = FieldTypeGroupToFormType(field_data->Type().group());
+      form_types = field_data->Type().GetFormTypes();
       form_control_type = static_cast<int64_t>(field_data->form_control_type());
 
       switch (field_data->form_control_type()) {
@@ -137,19 +137,21 @@
   }
   metrics.last_update_time = base::TimeTicks::Now();
 
-  switch (form_type) {
-    case autofill::FormType::kUnknownFormType:
-      break;
-    case autofill::FormType::kAddressForm:
-    case autofill::FormType::kLoyaltyCardForm:
-      metrics.is_autofill_field_type = true;
-      break;
-    case autofill::FormType::kStandaloneCvcForm:
-    case autofill::FormType::kCreditCardForm:
-    case autofill::FormType::kPasswordForm:
-      metrics.sensitive_field = true;
-      metrics.is_autofill_field_type = true;
-      break;
+  for (autofill::FormType form_type : form_types) {
+    switch (form_type) {
+      case autofill::FormType::kUnknownFormType:
+        break;
+      case autofill::FormType::kAddressForm:
+      case autofill::FormType::kLoyaltyCardForm:
+        metrics.is_autofill_field_type = true;
+        break;
+      case autofill::FormType::kStandaloneCvcForm:
+      case autofill::FormType::kCreditCardForm:
+      case autofill::FormType::kPasswordForm:
+        metrics.sensitive_field = true;
+        metrics.is_autofill_field_type = true;
+        break;
+    }
   }
 
   // Note that field_data->value doesn't have the current value, so we use
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
index c1a59610..f318d182 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
@@ -26,7 +26,8 @@
 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.chromium.base.supplier.UnownedUserDataSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -78,6 +79,8 @@
     @Mock private SignInInterstitialInitiator mSignInInterstitialInitiator;
     @Mock private FeedActionDelegate mFeedActionDelegate;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public ActivityScenarioRule<TestActivity> mActivityScenarioRule =
             new ActivityScenarioRule<>(TestActivity.class);
@@ -92,7 +95,6 @@
 
     @Before
     public void setUpTest() {
-        MockitoAnnotations.initMocks(this);
         FeedServiceBridgeJni.setInstanceForTesting(mFeedServiceBridgeJniMock);
         FeedSurfaceRendererBridgeJni.setInstanceForTesting(mFeedSurfaceRendererBridgeJniMock);
         WebFeedBridgeJni.setInstanceForTesting(mWebFeedBridgeJniMock);
@@ -326,7 +328,6 @@
         CreatorCoordinator creatorCoordinator =
                 newCreatorCoordinator(
                         null, mWebFeedIdDefault, mEntryPointDefault, mFollowingDefault);
-        PropertyModel creatorModel = creatorCoordinator.getCreatorModel();
         creatorCoordinator.queryFeedStream(mFeedActionDelegate, mShareDelegateSupplier);
         verify(mWebFeedBridgeJniMock).queryWebFeedId(anyString(), any());
     }
@@ -335,7 +336,6 @@
     public void testCreatorCoordinator_QueryFeed_nullWebFeedId() {
         CreatorCoordinator creatorCoordinator =
                 newCreatorCoordinator(DEFAULT_URL, null, mEntryPointDefault, mFollowingDefault);
-        PropertyModel creatorModel = creatorCoordinator.getCreatorModel();
         creatorCoordinator.queryFeedStream(mFeedActionDelegate, mShareDelegateSupplier);
         verify(mWebFeedBridgeJniMock).queryWebFeed(anyString(), any());
     }
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java
index 0324d629..0d65ed8e 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java
@@ -23,7 +23,8 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.UnownedUserDataSupplier;
@@ -70,6 +71,8 @@
     @Captor private ArgumentCaptor<Callback<FollowResults>> mFollowResultsCallbackCaptor;
     @Captor private ArgumentCaptor<Callback<UnfollowResults>> mUnfollowResultsCallbackCaptor;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public ActivityScenarioRule<TestActivity> mActivityScenarioRule =
             new ActivityScenarioRule<>(TestActivity.class);
@@ -83,7 +86,6 @@
 
     @Before
     public void setUpTest() {
-        MockitoAnnotations.initMocks(this);
         FeedSurfaceRendererBridgeJni.setInstanceForTesting(mFeedSurfaceRendererBridgeJniMock);
         FeedServiceBridgeJni.setInstanceForTesting(mFeedServiceBridgeJniMock);
         WebFeedBridgeJni.setInstanceForTesting(mWebFeedBridgeJniMock);
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorSnackbarControllerTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorSnackbarControllerTest.java
index 37be1c0..5b3a8ac 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorSnackbarControllerTest.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorSnackbarControllerTest.java
@@ -15,12 +15,14 @@
 import android.content.Context;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 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;
@@ -34,6 +36,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 public class CreatorSnackbarControllerTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private WebFeedBridge.Natives mWebFeedBridgeJniMock;
     @Mock private SnackbarManager mSnackbarManager;
 
@@ -45,7 +48,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         WebFeedBridgeJni.setInstanceForTesting(mWebFeedBridgeJniMock);
         mContext = Robolectric.setupActivity(Activity.class);
         mTitle = "Example Title";
diff --git a/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceConditionsTest.java b/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceConditionsTest.java
index 3ab2ab7d..2aee7cf2 100644
--- a/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceConditionsTest.java
+++ b/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceConditionsTest.java
@@ -23,10 +23,12 @@
 
 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.annotation.Config;
 
 import org.chromium.base.ContextUtils;
@@ -38,6 +40,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config
 public class DeviceConditionsTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Context mContext;
     @Mock private ConnectivityManager mConnectivityManager;
     @Mock private PowerManager mPowerManager;
@@ -49,8 +52,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         // Set up the battery to be at 50% by default.
         mBatteryStatus = new Intent();
         mBatteryStatus.putExtra(BatteryManager.EXTRA_SCALE, 100);
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn
index 15dc2692..096a494 100644
--- a/chrome/browser/devtools/BUILD.gn
+++ b/chrome/browser/devtools/BUILD.gn
@@ -331,6 +331,7 @@
       "//chrome/browser/first_party_sets",
       "//chrome/browser/ui/browser_window",
       "//chrome/browser/ui/media_router",
+      "//chrome/browser/ui/startup",
       "//components/custom_handlers",
       "//components/media_router/browser",
       "//components/media_router/common/mojom:media_router",
diff --git a/chrome/browser/devtools/protocol/autofill_handler.cc b/chrome/browser/devtools/protocol/autofill_handler.cc
index 6291214..4b37e41 100644
--- a/chrome/browser/devtools/protocol/autofill_handler.cc
+++ b/chrome/browser/devtools/protocol/autofill_handler.cc
@@ -8,6 +8,7 @@
 #include <variant>
 
 #include "base/check_deref.h"
+#include "base/containers/to_vector.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/devtools/protocol/autofill.h"
@@ -252,6 +253,7 @@
     if (!filled_form_ids.contains(field->renderer_form_id())) {
       continue;
     }
+    autofill::FieldTypeSet field_types = field->Type().GetTypes();
     // Whether the field was classified from the autocomplete attribute or
     // predictions. If no autocomplete attribute exists OR the actual ServerType
     // differs from what it would have been with only autocomplete, autofill
@@ -259,8 +261,13 @@
     bool autofill_inferred =
         field->html_type() == autofill::HtmlFieldType::kUnspecified ||
         field->html_type() == autofill::HtmlFieldType::kUnrecognized ||
-        autofill::HtmlFieldTypeToBestCorrespondingFieldType(
-            field->html_type()) != field->Type().GetStorableType();
+        !field_types.contains(
+            autofill::HtmlFieldTypeToBestCorrespondingFieldType(
+                field->html_type()));
+
+    std::vector<std::string_view> field_type_strings = base::ToVector(
+        field_types, &autofill::FieldTypeToDeveloperRepresentationString);
+    std::erase(field_type_strings, "");
 
     filled_fields_to_be_sent_to_devtools->push_back(
         protocol::Autofill::FilledField::Create()
@@ -271,9 +278,7 @@
                                                               : u""))
             .SetHtmlType(std::string(
                 autofill::FormControlTypeToString(field->form_control_type())))
-            .SetAutofillType(
-                std::string(FieldTypeToDeveloperRepresentationString(
-                    field->Type().GetStorableType())))
+            .SetAutofillType(base::JoinString(field_type_strings, ", "))
             .SetFillingStrategy(
                 autofill_inferred
                     ? protocol::Autofill::FillingStrategyEnum::AutofillInferred
diff --git a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
index e7fdbd4..74004e7 100644
--- a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
+++ b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/check_deref.h"
+#include "base/containers/to_vector.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
@@ -547,12 +548,16 @@
     const FormFieldData& ffd = filled_fields_by_autofill[i];
     const AutofillField* af = fs.GetFieldById(ffd.global_id());
 
+    std::vector<std::string_view> field_type_strings =
+        base::ToVector(af->Type().GetTypes(),
+                       &autofill::FieldTypeToDeveloperRepresentationString);
+    std::erase(field_type_strings, "");
+
     EXPECT_THAT(ff,
                 FilledFieldHasAttributeWithValue16("id", af->id_attribute()));
-    EXPECT_THAT(ff, FilledFieldHasAttributeWithValue(
-                        "autofillType",
-                        std::string(FieldTypeToDeveloperRepresentationString(
-                            af->Type().GetStorableType()))));
+    EXPECT_THAT(
+        ff, FilledFieldHasAttributeWithValue(
+                "autofillType", base::JoinString(field_type_strings, ", ")));
     EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16("value", af->value()));
     EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16(
                         "frameId",
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
index 12521d28..1172b05 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
@@ -12,10 +12,12 @@
 
 import org.junit.Assert;
 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.chromium.base.ContextUtils;
 import org.chromium.base.test.util.Batch;
@@ -49,13 +51,13 @@
     private static final String EXTERNAL_SD_CARD_DOWNLOAD_PATH =
             EXTERNAL_SD_CARD_DOWNLOAD_DIRECTORY_PATH + "/app-wise-release.apk";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private DownloadDirectoryProvider.Delegate mMockDirectoryDelegate;
 
     private SecondaryStorageInfo mSecondaryStorageInfo;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         doReturn(new File(PRIMARY_STORAGE_DOWNLOAD_DIRECTORY_PATH))
                 .when(mMockDirectoryDelegate)
                 .getPrimaryDownloadDirectory();
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialMediatorTest.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialMediatorTest.java
index 59899f8..198294c 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialMediatorTest.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialMediatorTest.java
@@ -28,10 +28,12 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
@@ -65,6 +67,7 @@
     private static final String OPEN_BUTTON_TEXT = "Open";
     private static final String DELETE_BUTTON_TEXT = "Delete";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private SnackbarManager mSnackbarManager;
 
     private final TestOfflineContentProvider mProvider = new TestOfflineContentProvider();
@@ -78,7 +81,6 @@
 
     @Before
     public void before() {
-        MockitoAnnotations.initMocks(this);
         mSnackbarShown = false;
         doAnswer((invocation) -> mSnackbarShown = true)
                 .when(mSnackbarManager)
diff --git a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewBinderUnitTest.java b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewBinderUnitTest.java
index 3bbe7542..150d285 100644
--- a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewBinderUnitTest.java
+++ b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleViewBinderUnitTest.java
@@ -25,10 +25,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.robolectric.annotation.Config;
 
@@ -41,6 +43,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public final class EducationalTipModuleViewBinderUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private Activity mActivity;
     private EducationalTipModuleView mEducationalTipModuleView;
     private PropertyModel mModel;
@@ -49,7 +52,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mEducationalTipModuleView =
                 (EducationalTipModuleView)
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_info_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_info_browsertest.cc
index 9cf7f38..38affd4 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_info_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_info_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/enterprise/connectors/core/content_area_user_provider.h"
 #include "components/enterprise/connectors/core/features.h"
 #include "components/signin/public/identity_manager/test_identity_manager_observer.h"
 #include "content/public/test/browser_test.h"
@@ -113,11 +114,12 @@
       ActiveUserTestCase{
           .url = "https://docs.google.com/",
           .emails = {"foo@gmail.com", "bar@gmail.com"},
-          .expected_active_email = "foo@gmail.com",
+          .expected_active_email = "",
       },
       ActiveUserTestCase{
           .url = "https://console.cloud.google.com/",
           .emails = {"bar@gmail.com"},
+          // With only 1 user it has to be the active one.
           .expected_active_email = "bar@gmail.com",
       },
       ActiveUserTestCase{
@@ -159,6 +161,108 @@
   }
 };
 
+struct ActiveFrameUserTestCase {
+  const char* tab_url;
+  const char* frame_url;
+  std::vector<const char*> emails;
+  const char* expected_active_email;
+};
+
+std::vector<ActiveFrameUserTestCase> FrameUserTestCases() {
+  return {
+      // Invalid Workspace tab URL with invalid frame URL test case.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://bar.baz.com/",
+          .frame_url = "https://foo.bar/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "",
+      },
+      // Valid Workspace tab URL with invalid frame URL test case.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://mail.google.com/",
+          .frame_url = "https://foo.bar/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "",
+      },
+      // Invalid Workspace tab URL with valid frame URL test case.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://foo.bar/",
+          .frame_url = "https://ogs.google.com/u/0/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "",
+      },
+      // Valid "/u/<N>/" test cases.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/u/0/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "foo@gmail.com",
+      },
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/abcd/efgh/u/1/ijkl/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "bar@gmail.com",
+      },
+      // Valid "authuser=<N>"/ test cases.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/?authuser=0",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "foo@gmail.com",
+      },
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/abcd/efgh/ijkl/?authuser=1",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "bar@gmail.com",
+      },
+      // Valid URLs with no valid index test cases.
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "",
+      },
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/abcd/efgh/ijkl/?authuser=foo",
+          .emails = {"foo@gmail.com", "bar@gmail.com"},
+          .expected_active_email = "",
+      },
+      ActiveFrameUserTestCase{
+          .tab_url = "https://docs.google.com/",
+          .frame_url = "https://ogs.google.com/",
+          .emails = {"bar@gmail.com"},
+          // With only 1 user it has to be the active one.
+          .expected_active_email = "bar@gmail.com",
+      },
+  };
+}
+
+class ActiveFrameUserEmailBrowserTest
+    : public MixinBasedInProcessBrowserTest,
+      public testing::WithParamInterface<ActiveFrameUserTestCase> {
+ public:
+  ActiveFrameUserEmailBrowserTest() {
+    active_user_test_mixin_ = std::make_unique<test::ActiveUserTestMixin>(
+        &mixin_host_, this, &embedded_https_test_server(), GetParam().emails);
+  }
+
+  GURL tab_url() const { return GURL(GetParam().tab_url); }
+  GURL frame_url() const { return GURL(GetParam().frame_url); }
+
+  std::string expected_active_email() const {
+    return GetParam().expected_active_email;
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      kEnterpriseActiveUserDetection};
+
+  std::unique_ptr<test::ActiveUserTestMixin> active_user_test_mixin_;
+};
+
 }  // namespace
 
 IN_PROC_BROWSER_TEST_P(ActiveUserEmailBrowserTest, GetActiveUser) {
@@ -186,4 +290,17 @@
                          ActiveUserEmailFeatureDisabledBrowserTest,
                          testing::ValuesIn(TestCases()));
 
+IN_PROC_BROWSER_TEST_P(ActiveFrameUserEmailBrowserTest, GetActiveUserForFrame) {
+  active_user_test_mixin_->SetFakeCookieValue();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), tab_url()));
+  ASSERT_EQ(expected_active_email(),
+            GetActiveFrameUser(
+                IdentityManagerFactory::GetForProfile(browser()->profile()),
+                tab_url(), frame_url()));
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+                         ActiveFrameUserEmailBrowserTest,
+                         testing::ValuesIn(FrameUserTestCases()));
+
 }  // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfoImplTest.java b/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfoImplTest.java
index b54b949..0f24f93 100644
--- a/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfoImplTest.java
+++ b/chrome/browser/enterprise/util/android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfoImplTest.java
@@ -12,11 +12,13 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
@@ -35,6 +37,7 @@
         shadows = {ShadowPostTask.class})
 @LooperMode(LooperMode.Mode.LEGACY)
 public class EnterpriseInfoImplTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock public EnterpriseInfo.Natives mNatives;
 
     @Before
@@ -43,7 +46,6 @@
         // Skip the AsyncTask, we don't actually want to query the device, just enqueue callbacks.
         getEnterpriseInfoImpl().setSkipAsyncCheckForTesting(true);
 
-        MockitoAnnotations.initMocks(this);
         EnterpriseInfoJni.setInstanceForTesting(mNatives);
     }
 
diff --git a/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.cc b/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.cc
index 5666a2a4..cfdc9b7f 100644
--- a/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.cc
+++ b/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.cc
@@ -406,6 +406,14 @@
 
   actor::TaskId task_id(actions.task_id());
 
+  // If the client didn't create a task or passed in the wrong task id, return
+  // failure.
+  actor::ActorTask* task = actor_service->GetTask(task_id);
+  if (!task) {
+    return RespondNow(
+        Error(absl::StrFormat("Invalid task_id[%d].", task_id.value())));
+  }
+
   actor::BuildToolRequestResult requests = actor::BuildToolRequest(actions);
 
   if (!requests.has_value()) {
@@ -413,7 +421,7 @@
         FROM_HERE,
         base::BindOnce(
             &ExperimentalActorPerformActionsFunction::OnActionsFinished, this,
-            actor::mojom::ActionResultCode::kArgumentsInvalid,
+            task_id, actor::mojom::ActionResultCode::kArgumentsInvalid,
             requests.error()));
     return RespondLater();
   }
@@ -421,24 +429,48 @@
   actor_service->PerformActions(
       task_id, std::move(requests.value()),
       base::BindOnce(
-          &ExperimentalActorPerformActionsFunction::OnActionsFinished, this));
+          &ExperimentalActorPerformActionsFunction::OnActionsFinished, this,
+          task_id));
 
   return RespondLater();
 }
 
 void ExperimentalActorPerformActionsFunction::OnActionsFinished(
+    actor::TaskId task_id,
     actor::mojom::ActionResultCode result_code,
     std::optional<size_t> index_of_failed_action) {
-  optimization_guide::proto::ActionsResult response =
-      actor::BuildActionsResult(result_code, index_of_failed_action);
+  auto* actor_service = actor::ActorKeyedService::Get(browser_context());
+  actor::ActorTask* task = actor_service->GetTask(task_id);
 
-  // TODO(crbug.com/411462297) Request observations and fill in the response
-  // with them (remembering to convert to session tab ids)
+  // Task is checked when calling PerformActions and it cannot be removed once
+  // added (a stopped task is no longer active but will still be retrieved by
+  // GetTask).
+  CHECK(task);
 
-  std::vector<uint8_t> data_buffer(response.ByteSizeLong());
-  if (!data_buffer.empty()) {
-    response.SerializeToArray(&data_buffer[0], response.ByteSizeLong());
+  actor::BuildActionsResultWithObservations(
+      *browser_context(), result_code, index_of_failed_action, *task,
+      base::BindOnce(
+          &ExperimentalActorPerformActionsFunction::OnObservationResult, this));
+}
+
+void ExperimentalActorPerformActionsFunction::OnObservationResult(
+    std::unique_ptr<optimization_guide::proto::ActionsResult> response) {
+  CHECK(response);
+
+  // Convert back from tab handle to session tab id.
+  for (optimization_guide::proto::TabObservation& observation :
+       *response->mutable_tabs()) {
+    // Note: session_tab_id will be -1 if the tab if couldn't be mapped.
+    int32_t session_tab_id =
+        ConvertTabHandleToSessionTabId(observation.id(), browser_context());
+    observation.set_id(session_tab_id);
   }
+
+  std::vector<uint8_t> data_buffer(response->ByteSizeLong());
+  if (!data_buffer.empty()) {
+    response->SerializeToArray(data_buffer.data(), response->ByteSizeLong());
+  }
+
   Respond(ArgumentList(api::experimental_actor::PerformActions::Results::Create(
       std::move(data_buffer))));
 }
@@ -488,8 +520,10 @@
     return;
   }
 
-  optimization_guide::proto::TabObservation& tab_observation =
-      **observation_result;
+  // TODO(bokan): This doesn't set the (tab) `id` field, maybe unneeded in this
+  // case but would be good for consistency.
+  optimization_guide::proto::TabObservation tab_observation =
+      actor::ConvertToTabObservation(**observation_result);
   std::vector<uint8_t> data_buffer(tab_observation.ByteSizeLong());
   if (!data_buffer.empty()) {
     tab_observation.SerializeToArray(&data_buffer[0], data_buffer.size());
diff --git a/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.h b/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.h
index bc82904..e1222ab 100644
--- a/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.h
+++ b/chrome/browser/extensions/api/experimental_actor/experimental_actor_api.h
@@ -120,8 +120,11 @@
  protected:
   ~ExperimentalActorPerformActionsFunction() override;
   ResponseAction Run() override;
-  void OnActionsFinished(actor::mojom::ActionResultCode result_code,
+  void OnActionsFinished(actor::TaskId task_id,
+                         actor::mojom::ActionResultCode result_code,
                          std::optional<size_t> index_of_failed_action);
+  void OnObservationResult(
+      std::unique_ptr<optimization_guide::proto::ActionsResult> response);
   DECLARE_EXTENSION_FUNCTION("experimentalActor.performActions",
                              EXPERIMENTALACTOR_PERFORMACTIONS)
 };
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 7f9dd340..519c0f3b 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -5983,7 +5983,7 @@
 // Tests --load-extension works for non-ESB users.
 // --load-extension was disabled in https://crbug.com/401529219
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_CHROMEOS)
-#define MAYBE_LoadsFromCommandLineForNonESBUsers DISABLE_LoadsFromCommandLineForNonESBUsers
+#define MAYBE_LoadsFromCommandLineForNonESBUsers DISABLED_LoadsFromCommandLineForNonESBUsers
 #else
 #define MAYBE_LoadsFromCommandLineForNonESBUsers LoadsFromCommandLineForNonESBUsers
 #endif
@@ -6037,7 +6037,7 @@
 // value)
 // --load-extension was disabled in https://crbug.com/401529219
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_CHROMEOS)
-#define MAYBE_LoadsFromCommandLineForUsersWithoutPolicy DISABLE_LoadsFromCommandLineForUsersWithoutPolicy
+#define MAYBE_LoadsFromCommandLineForUsersWithoutPolicy DISABLED_LoadsFromCommandLineForUsersWithoutPolicy
 #else
 #define MAYBE_LoadsFromCommandLineForUsersWithoutPolicy LoadsFromCommandLineForUsersWithoutPolicy
 #endif
diff --git a/chrome/browser/extensions/policy_handlers.cc b/chrome/browser/extensions/policy_handlers.cc
index 193f718..71775ecd 100644
--- a/chrome/browser/extensions/policy_handlers.cc
+++ b/chrome/browser/extensions/policy_handlers.cc
@@ -155,7 +155,7 @@
     size_t pos = entry_string.find(';');
     if (pos == std::string::npos) {
       extension_id = entry_string;
-      update_url = extension_urls::GetWebstoreUpdateUrl().spec();
+      update_url = extension_urls::kChromeWebstoreUpdateURL;
     } else {
       extension_id = entry_string.substr(0, pos);
       update_url = entry_string.substr(pos + 1);
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl.cc b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
index f86fa8442..5835206 100644
--- a/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <ranges>
 
 #include "base/containers/flat_set.h"
 #include "base/metrics/histogram_functions.h"
@@ -79,12 +80,14 @@
       form.GetFormTypes().contains(autofill::FormType::kAddressForm);
   bool has_name_or_address_field = std::ranges::any_of(
       form.fields(), [](const std::unique_ptr<autofill::AutofillField>& field) {
-        autofill::FieldTypeGroup type_group = field->Type().group();
-        return IsNameOrAddress(type_group) && IsVisibleTextField(*field);
+        return std::ranges::any_of(field->Type().GetGroups(),
+                                   &IsNameOrAddress) &&
+               IsVisibleTextField(*field);
       });
   bool has_focusable_email_field = std::ranges::any_of(
       form.fields(), [](const std::unique_ptr<autofill::AutofillField>& field) {
-        return field->Type().group() == autofill::FieldTypeGroup::kEmail &&
+        return field->Type().GetGroups().contains(
+                   autofill::FieldTypeGroup::kEmail) &&
                IsVisibleTextField(*field);
       });
   return is_address_form && has_focusable_email_field &&
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index cbe663d4..d4ce7f1 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -81,6 +81,15 @@
     "expiry_milestone": 133
   },
   {
+    "name": "ai-mode-omnibox-entry-point",
+    "owners": [
+      "khalidpeer@chromium.org",
+      "jdonnelly@chromium.org",
+      "orinj@chromium.org",
+      "chrome-desktop-search@google.com"],
+    "expiry_milestone": 145
+  },
+  {
     "name": "ai-settings-enterprise-disabled-ui",
     "owners": [
       "dullweber@chromium.org",
@@ -959,6 +968,11 @@
     "expiry_milestone": 130
   },
   {
+    "name": "autofill-show-bubbles-based-on-priorities",
+    "owners": ["vidhanj@google.com", "autofill-squad-muc@google.com"],
+    "expiry_milestone": 145
+  },
+  {
     "name": "autofill-show-manual-fill-for-virtual-cards",
     "owners": [ "siyua@chromium.org", "payments-autofill-team@google.com"],
     "expiry_milestone": 135
@@ -7721,6 +7735,14 @@
     "expiry_milestone": 150
   },
   {
+    "name": "page-context-anchor-tags",
+    "owners": [
+      "nicolasmacbeth@google.com",
+      "bling-alchemy-eng@google.com"
+    ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "page-image-service-optimization-guide-salient-images",
     "owners": [ "tommycli@chromium.org", "//components/page_image_service/OWNERS" ],
     "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8a513b4..09dae96 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -18,6 +18,10 @@
     "Enables the use of the GPU to perform 2d canvas rendering instead of "
     "using software rendering.";
 
+const char kAiModeOmniboxEntryPointName[] = "AI Mode Omnibox entrypoint";
+const char kAiModeOmniboxEntryPointDescription[] =
+    "Enables icon button for AI Mode entrypoint in the Omnibox.";
+
 const char kAiSettingsPageEnterpriseDisabledName[] =
     "AI settings page enterprise disabled UI";
 const char kAiSettingsPageEnterpriseDisabledDescription[] =
@@ -926,6 +930,12 @@
     "When enabled, swapping autofilled payment suggestions would result"
     "in overriding all of the payments fields with the swapped profile data";
 
+const char kAutofillShowBubblesBasedOnPrioritiesName[] =
+    "Show bubbles based on priorities";
+const char kAutofillShowBubblesBasedOnPrioritiesDescription[] =
+    "When enabled, the autofill and the password manager bubbles would be"
+    "shown based on their respective priorities compared to each other";
+
 const char kAutofillRequireCvcForPossibleCardUpdateName[] =
     "Require CVC for possible card update on upload save";
 const char kAutofillRequireCvcForPossibleCardUpdateDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a04107f..4e84df7 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -55,6 +55,9 @@
 extern const char kAcceleratedVideoEncodeName[];
 extern const char kAcceleratedVideoEncodeDescription[];
 
+extern const char kAiModeOmniboxEntryPointName[];
+extern const char kAiModeOmniboxEntryPointDescription[];
+
 extern const char kAiSettingsPageEnterpriseDisabledName[];
 extern const char kAiSettingsPageEnterpriseDisabledDescription[];
 
@@ -577,6 +580,9 @@
 extern const char kAutofillPaymentsFieldSwappingName[];
 extern const char kAutofillPaymentsFieldSwappingDescription[];
 
+extern const char kAutofillShowBubblesBasedOnPrioritiesName[];
+extern const char kAutofillShowBubblesBasedOnPrioritiesDescription[];
+
 extern const char kAutofillUnmaskCardRequestTimeoutName[];
 extern const char kAutofillUnmaskCardRequestTimeoutDescription[];
 
diff --git a/chrome/browser/glic/browser_ui/glic_tab_underline_view.cc b/chrome/browser/glic/browser_ui/glic_tab_underline_view.cc
index 6486390..8df5f6a 100644
--- a/chrome/browser/glic/browser_ui/glic_tab_underline_view.cc
+++ b/chrome/browser/glic/browser_ui/glic_tab_underline_view.cc
@@ -8,6 +8,7 @@
 
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/functional/bind.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/glic/browser_ui/theme_util.h"
 #include "chrome/browser/glic/host/context/glic_tab_data.h"
@@ -166,6 +167,12 @@
 
     // Observe changes in the floaty state.
     glic_service->window_controller().AddStateObserver(this);
+
+    // Subscribe to when new requests are made by glic.
+    user_input_submitted_subscription_ =
+        glic_service->AddUserInputSubmittedCallback(base::BindRepeating(
+            &GlicTabUnderlineView::UnderlineViewUpdater::OnUserInputSubmitted,
+            base::Unretained(this)));
   }
   UnderlineViewUpdater(const UnderlineViewUpdater&) = delete;
   UnderlineViewUpdater& operator=(const UnderlineViewUpdater&) = delete;
@@ -271,6 +278,10 @@
             : UpdateUnderlineReason::kPanelStateChanged_PanelShowing);
   }
 
+  void OnUserInputSubmitted() {
+    UpdateUnderlineView(UpdateUnderlineReason::kUserInputSubmitted);
+  }
+
  private:
   // Types of updates to the tab underline UI effect given changes in relevant
   // triggering signals, including tab focus, glic sharing controls, pinned tabs
@@ -296,6 +307,8 @@
     // Events related to the glic panel's state.
     kPanelStateChanged_PanelShowing,
     kPanelStateChanged_PanelHidden,
+
+    kUserInputSubmitted,
   };
 
   GlicKeyedService* GetGlicKeyedService() {
@@ -448,6 +461,11 @@
           HideUnderline();
         }
         break;
+      case UpdateUnderlineReason::kUserInputSubmitted:
+        if (underline_view_->IsShowing()) {
+          AnimateUnderline();
+        }
+        break;
     }
   }
 
@@ -513,6 +531,8 @@
         return "PanelShowing";
       case UpdateUnderlineReason::kPanelStateChanged_PanelHidden:
         return "PanelHidden";
+      case UpdateUnderlineReason::kUserInputSubmitted:
+        return "UserInputSubmitted";
     }
   }
 
@@ -543,6 +563,7 @@
   bool context_access_indicator_enabled_ = false;
   base::CallbackListSubscription indicator_change_subscription_;
   base::CallbackListSubscription pinned_tabs_change_subscription_;
+  base::CallbackListSubscription user_input_submitted_subscription_;
 
   static constexpr size_t kNumReasonsToKeep = 10u;
   std::list<std::string> underline_update_reasons_;
diff --git a/chrome/browser/glic/e2e_test/glic_e2e_test.cc b/chrome/browser/glic/e2e_test/glic_e2e_test.cc
index 0167136..f558df9 100644
--- a/chrome/browser/glic/e2e_test/glic_e2e_test.cc
+++ b/chrome/browser/glic/e2e_test/glic_e2e_test.cc
@@ -69,16 +69,18 @@
     "PoNnQAwghMiLUPg1YNFtvTfGreNT8r9oeLEyzgNCJWc=";
 }  // namespace
 
-GlicE2ETest::GlicE2ETest() = default;
-GlicE2ETest::~GlicE2ETest() = default;
-
-void GlicE2ETest::SetUp() {
+GlicE2ETest::GlicE2ETest() {
   scoped_feature_list_.InitWithFeatures(
       /*enabled_features=*/{features::kGlic, features::kTabstripComboButton,
                             features::kGlicKeyboardShortcutNewBadge,
                             features::kGlicRollout,
                             contextual_cueing::kContextualCueing},
       /*disabled_features=*/{});
+}
+
+GlicE2ETest::~GlicE2ETest() = default;
+
+void GlicE2ETest::SetUp() {
   const base::CommandLine* command_line_of_test =
       base::CommandLine::ForCurrentProcess();
 
diff --git a/chrome/browser/glic/host/context/glic_page_context_fetcher.cc b/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
index 6315454..f226454 100644
--- a/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
+++ b/chrome/browser/glic/host/context/glic_page_context_fetcher.cc
@@ -67,6 +67,8 @@
             page_context.inner_text_result->truncated));
   }
 
+  // TODO(crbug.com/411462297): Remove actor specific bits in this class once
+  // all actor entry points are removed.
   actor::AggregatedJournal* journal = nullptr;
   if (web_contents) {
     if (auto* actor_keyed_service =
@@ -146,8 +148,6 @@
       tab_context_options.include_viewport_screenshot;
 
   if (tab_context_options.include_annotated_page_content) {
-    // TODO(crbug.com/409564704): Move actor page content extraction to the
-    // actor coordinator.
     if (tab_context_options.annotated_page_content_mode ==
         optimization_guide::proto::
             ANNOTATED_PAGE_CONTENT_MODE_ACTIONABLE_ELEMENTS) {
diff --git a/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc b/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
index 0a67cf877..59096512 100644
--- a/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
+++ b/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
@@ -544,6 +544,17 @@
         expected)));
   }
 
+  auto CheckIsWebContentsCaptured(ui::ElementIdentifier tab, bool expected) {
+    return Steps(InAnyContext(CheckElement(
+        tab,
+        [](ui::TrackedElement* el) {
+          content::WebContents* tab_contents =
+              AsInstrumentedWebContents(el)->web_contents();
+          return tab_contents->IsBeingCaptured();
+        },
+        expected)));
+  }
+
   // Check ExecutionEngine caches the last apc observation.
   auto CheckExecutionEngineHasAnnotatedPageContentCache() {
     return Steps(Do([&]() {
@@ -1099,6 +1110,35 @@
                       "() => { return !(client.browser.actInFocusedTab); }")));
 }
 
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest,
+                       ActuationSucceedsOnBackgroundTab) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kOtherTabId);
+
+  constexpr std::string_view kClickableButtonLabel = "clickable";
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(
+      // clang-format off
+      InitializeWithOpenGlicWindow(),
+      StartActorTaskInNewTab(task_url, kNewActorTabId),
+      GetPageContextFromFocusedTab(),
+      SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
+                              kActivateSurfaceIncompatibilityNotice),
+      AddInstrumentedTab(kOtherTabId, GURL(chrome::kChromeUISettingsURL)),
+      FocusWebContents(kOtherTabId),
+      CheckIsWebContentsCaptured(kNewActorTabId, true),
+      ClickAction(kClickableButtonLabel),
+      WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+      CheckIsActingOnTab(kNewActorTabId, true),
+      CheckIsActingOnTab(kOtherTabId, false),
+      StopActorTask(),
+      CheckIsWebContentsCaptured(kNewActorTabId, false));
+  // clang-format on
+}
+
 }  //  namespace
 
 }  // namespace glic::test
diff --git a/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc b/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc
index 28fb302..69a5c70 100644
--- a/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc
+++ b/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc
@@ -138,9 +138,7 @@
 class GlicAnnotationManagerUiTest : public InteractiveGlicTest {
  public:
   GlicAnnotationManagerUiTest() {
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        features::kGlicScrollTo,
-        {{"glic-scroll-to-enforce-document-id", "true"}});
+    scoped_feature_list_.InitAndEnableFeature(features::kGlicScrollTo);
   }
   ~GlicAnnotationManagerUiTest() override = default;
 
@@ -1312,8 +1310,7 @@
         {features::kGlicScrollTo,
          {{"glic-scroll-to-pdf", base::ToString(enable_scroll_to_pdf)},
           {"glic-scroll-to-enforce-url-for-pdf",
-           base::ToString(enforce_url_for_pdf)},
-          {"glic-scroll-to-enforce-document-id", "true"}}}};
+           base::ToString(enforce_url_for_pdf)}}}};
     std::vector<base::test::FeatureRef> disabled_features = {};
     if (UseOopif()) {
       enabled_features.push_back({chrome_pdf::features::kPdfOopif, {}});
diff --git a/chrome/browser/glic/host/glic_api_browsertest.cc b/chrome/browser/glic/host/glic_api_browsertest.cc
index b7bc7221..f9c270fa 100644
--- a/chrome/browser/glic/host/glic_api_browsertest.cc
+++ b/chrome/browser/glic/host/glic_api_browsertest.cc
@@ -199,8 +199,7 @@
                  {features::kGlicPreLoadingTimeMs.name, "20"},
                  {features::kGlicMinLoadingTimeMs.name, "40"},
              }},
-            {features::kGlicScrollTo,
-             {{"glic-scroll-to-enforce-document-id", "true"}}},
+            {features::kGlicScrollTo, {}},
             {features::kGlicClosedCaptioning, {}},
             {features::kGlicApiActivationGating, {}},
             {mojom::features::kGlicMultiTab, {}},
diff --git a/chrome/browser/glic/host/glic_page_handler.cc b/chrome/browser/glic/host/glic_page_handler.cc
index 873bd2aed..d9da2c3 100644
--- a/chrome/browser/glic/host/glic_page_handler.cc
+++ b/chrome/browser/glic/host/glic_page_handler.cc
@@ -1052,6 +1052,7 @@
   }
 
   void OnUserInputSubmitted(glic::mojom::WebClientMode mode) override {
+    glic_service_->OnUserInputSubmitted(mode);
     glic_service_->metrics()->OnUserInputSubmitted(mode);
   }
 
diff --git a/chrome/browser/glic/media/glic_media_link_helper.cc b/chrome/browser/glic/media/glic_media_link_helper.cc
index d333918..fcdd35c 100644
--- a/chrome/browser/glic/media/glic_media_link_helper.cc
+++ b/chrome/browser/glic/media/glic_media_link_helper.cc
@@ -5,20 +5,35 @@
 #include "chrome/browser/glic/media/glic_media_link_helper.h"
 
 #include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
 #include "content/public/browser/media_session.h"
 #include "content/public/browser/web_contents.h"
+#include "media/base/media_switches.h"
 #include "net/base/url_util.h"
 #include "url/origin.h"
 
 namespace glic {
 
+// Allows embedded media to be controlled by a link helper.
+BASE_FEATURE(kMediaLinkEmbedHelper,
+             "MediaLinkEmbedHelper",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 GlicMediaLinkHelper::GlicMediaLinkHelper(content::WebContents* web_contents)
     : web_contents_(web_contents) {}
 
 GlicMediaLinkHelper::~GlicMediaLinkHelper() = default;
 
 bool GlicMediaLinkHelper::MaybeReplaceNavigation(const GURL& target) {
+  const std::string youtube_host("www.youtube.com");
+
+  // Handle embedded YT first, since it's experimental.  For any YT target, let
+  // the embed helper figure out if it applies to any frame.
+  if (base::FeatureList::IsEnabled(kMediaLinkEmbedHelper)) {
+    if (target.host() == youtube_host && YouTubeEmbedHelper(target)) {
+      return true;
+    }
+  }
+
   const GURL& committed_url =
       web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL();
 
@@ -27,13 +42,93 @@
     return false;
   }
 
-  if (target.host() == "www.youtube.com") {
+  if (target.host() == youtube_host) {
     return YouTubeHelper(target);
   }
 
   return false;
 }
 
+// static
+std::optional<base::TimeDelta>
+GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(const GURL& target) {
+  // Make sure that the target specifies a t=.
+  std::string t_string;
+  if (!net::GetValueForKeyInQuery(target, "t", &t_string)) {
+    return {};
+  }
+
+  if (!t_string.length()) {
+    return {};
+  }
+
+  unsigned int t = 0;
+  if (!base::StringToUint(t_string, &t)) {
+    return {};
+  }
+
+  return base::Seconds(t);
+}
+
+// static
+std::optional<std::string> GlicMediaLinkHelper::ExtractVideoNameIfExists(
+    const GURL& url) {
+  // `url` is a link to www.youtube.com.  The video name is either the value of
+  // the `v=` query param if the format is "...youtube.com/watch", or the last
+  // part of the path if it's "...youtube.com/embed/video name here".
+  // Extract it and return it, or else {} if there's no match.
+  std::string video_name;
+  if (url.path() == "/watch") {
+    if (net::GetValueForKeyInQuery(url, "v", &video_name) &&
+        !video_name.empty()) {
+      return video_name;
+    }
+  } else if (base::StartsWith(url.path(), "/embed/")) {
+    video_name = url.path().substr(strlen("/embed/"));
+    if (!video_name.empty()) {
+      return video_name;
+    }
+  }
+  return {};
+}
+
+bool GlicMediaLinkHelper::YouTubeEmbedHelper(const GURL& target) {
+  // `target` might be `www.youtube.com/watch` with `v=videoname`, while the
+  // video we're looking for might be in a subframe.  Use the media session's
+  // routed frame, since that's the one we can control.
+  auto* media_session = GetMediaSessionIfExists();
+  if (!media_session) {
+    return false;
+  }
+  auto* media_session_rfh = media_session->GetRoutedFrame();
+  if (!media_session_rfh) {
+    return false;
+  }
+
+  // Unlike normal helpers, this hasn't been checked yet.  We just figured out
+  // the frame now.
+  const auto& last_committed_url = media_session_rfh->GetLastCommittedURL();
+  if (last_committed_url.host() != target.host()) {
+    // Mediasession is not controlling YT.
+    return false;
+  }
+
+  // Make sure the video names exist and match.
+  auto committed_v = ExtractVideoNameIfExists(last_committed_url);
+  auto target_v = ExtractVideoNameIfExists(target);
+  if (!committed_v || !target_v || *committed_v != *target_v) {
+    return false;
+  }
+
+  // If there is a `t=` parameter in `target`, then use it.
+  if (auto maybe_time = ExtractTimeFromQueryIfExists(target)) {
+    media_session->SeekTo(*maybe_time);
+    return true;
+  }
+
+  return false;
+}
+
 bool GlicMediaLinkHelper::YouTubeHelper(const GURL& target) {
   // If `target` points to the same video as `web_contents` but contains a `t=`
   // parameter, assume that the goal is to seek to that point in the current
@@ -54,6 +149,9 @@
     return false;
   }
 
+  // This should be refactored to use the `IfExists` methods, but for now we
+  // don't want to break working code.
+
   // Make sure that the target specifies a t=.
   std::string t_string;
   if (!net::GetValueForKeyInQuery(target, "t", &t_string)) {
diff --git a/chrome/browser/glic/media/glic_media_link_helper.h b/chrome/browser/glic/media/glic_media_link_helper.h
index d12f63d..7896b59 100644
--- a/chrome/browser/glic/media/glic_media_link_helper.h
+++ b/chrome/browser/glic/media/glic_media_link_helper.h
@@ -5,7 +5,9 @@
 #ifndef CHROME_BROWSER_GLIC_MEDIA_GLIC_MEDIA_LINK_HELPER_H_
 #define CHROME_BROWSER_GLIC_MEDIA_GLIC_MEDIA_LINK_HELPER_H_
 
+#include "base/feature_list.h"
 #include "base/memory/raw_ptr.h"
+#include "base/time/time.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -15,6 +17,9 @@
 
 namespace glic {
 
+// Allow embedded media to be controlled by a link helper.
+BASE_DECLARE_FEATURE(kMediaLinkEmbedHelper);
+
 class GlicMediaLinkHelper {
  public:
   explicit GlicMediaLinkHelper(content::WebContents* web_contents);
@@ -31,8 +36,16 @@
   // Use this instead of MediaSession::GetIfExists() to make tests easier.
   virtual content::MediaSession* GetMediaSessionIfExists();
 
+  // Return the time from a `t=` parameter if it exists.  Public for testing.
+  static std::optional<base::TimeDelta> ExtractTimeFromQueryIfExists(
+      const GURL& target);
+
+  // Return the video ID if it's set in `url`.  Public for testing.
+  static std::optional<std::string> ExtractVideoNameIfExists(const GURL& url);
+
  private:
   bool YouTubeHelper(const GURL& target);
+  bool YouTubeEmbedHelper(const GURL& target);
 
   raw_ptr<content::WebContents> web_contents_ = nullptr;
 };
diff --git a/chrome/browser/glic/media/glic_media_link_helper_unittest.cc b/chrome/browser/glic/media/glic_media_link_helper_unittest.cc
index 1b54e3d..a50a6b55 100644
--- a/chrome/browser/glic/media/glic_media_link_helper_unittest.cc
+++ b/chrome/browser/glic/media/glic_media_link_helper_unittest.cc
@@ -8,8 +8,10 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/media_session.h"
 #include "content/public/test/mock_media_session.h"
+#include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/web_contents_tester.h"
+#include "media/base/media_switches.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -20,6 +22,7 @@
 
 using ::testing::_;
 using ::testing::Eq;
+using ::testing::Return;
 
 // Subclass for `GlicMediaLinkHelper` that lets us provide the `MediaSession`
 // object directly, since trying to get MediaSession::FromWebContents() to
@@ -64,6 +67,18 @@
     return media_link_helper_.get();
   }
 
+  void CreateAndAttachRoutedSubframe(const GURL& subframe_url) {
+    // Set up a subframe with an embed URL.
+    content::RenderFrameHost* subframe =
+        content::NavigationSimulator::NavigateAndCommitFromDocument(
+            subframe_url, content::RenderFrameHostTester::For(
+                              web_contents()->GetPrimaryMainFrame())
+                              ->AppendChild("subframe"));
+
+    ON_CALL(mock_media_session(), GetRoutedFrame)
+        .WillByDefault(Return(subframe));
+  }
+
  protected:
   content::MockMediaSession mock_media_session_;
   std::unique_ptr<GlicMediaLinkHelperForTest> media_link_helper_;
@@ -93,7 +108,96 @@
       GURL("https://www.example.com/another_page")));
 }
 
-// --- YouTubeHelper Specific Tests (via MaybeReplaceNavigation) ---
+// --- YouTubeEmbedHelper Specific Tests (via MaybeReplaceNavigation) ---
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_FeatureDisabled) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(kMediaLinkEmbedHelper);
+
+  // Navigate main frame to something else.
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  CreateAndAttachRoutedSubframe(GURL("https://www.youtube.com/embed/video123"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(_)).Times(0);
+
+  // The target is a regular YT link. Since the feature is off, this should
+  // fall through to the normal helper, which will fail because the main
+  // frame's host is example.com.
+  EXPECT_FALSE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/watch?v=video123&t=30")));
+}
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_SuccessWithWatchTarget) {
+  base::test::ScopedFeatureList feature_list(kMediaLinkEmbedHelper);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  CreateAndAttachRoutedSubframe(GURL("https://www.youtube.com/embed/video123"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(Eq(base::Seconds(30)))).Times(1);
+
+  EXPECT_TRUE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/watch?v=video123&t=30")));
+}
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_SuccessWithEmbedTarget) {
+  base::test::ScopedFeatureList feature_list(kMediaLinkEmbedHelper);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  CreateAndAttachRoutedSubframe(GURL("https://www.youtube.com/embed/video123"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(Eq(base::Seconds(45)))).Times(1);
+
+  EXPECT_TRUE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/embed/video123?t=45")));
+}
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_MismatchedVideoId) {
+  base::test::ScopedFeatureList feature_list(kMediaLinkEmbedHelper);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  CreateAndAttachRoutedSubframe(GURL("https://www.youtube.com/embed/video123"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(_)).Times(0);
+
+  EXPECT_FALSE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/watch?v=DIFFERENT&t=30")));
+}
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_NoTimeParam) {
+  base::test::ScopedFeatureList feature_list(kMediaLinkEmbedHelper);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  CreateAndAttachRoutedSubframe(GURL("https://www.youtube.com/embed/video123"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(_)).Times(0);
+
+  EXPECT_FALSE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/watch?v=video123")));
+}
+
+TEST_F(GlicMediaLinkHelperTest, YouTubeEmbedHelper_NoRoutedFrame) {
+  base::test::ScopedFeatureList feature_list(kMediaLinkEmbedHelper);
+
+  ON_CALL(mock_media_session(), GetRoutedFrame).WillByDefault(Return(nullptr));
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL("https://www.example.com/"));
+
+  EXPECT_CALL(mock_media_session(), SeekTo(_)).Times(0);
+
+  EXPECT_FALSE(media_link_helper()->MaybeReplaceNavigation(
+      GURL("https://www.youtube.com/watch?v=video123&t=30")));
+}
 
 TEST_F(GlicMediaLinkHelperTest, YouTubeHelper_DifferentSchemeSucceeds) {
   auto* web_contents_tester = content::WebContentsTester::For(web_contents());
@@ -252,5 +356,86 @@
       GURL("https://www.youtube.com/watch?v=video123&t=10.5")));
 }
 
+// Test fixture for static methods on GlicMediaLinkHelper.
+class GlicMediaLinkHelperStaticTest : public testing::Test {};
+
+TEST_F(GlicMediaLinkHelperStaticTest, ExtractVideoNameIfExists) {
+  // Test case for a standard YouTube "watch" URL.
+  GURL watch_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
+  std::optional<std::string> video_name =
+      GlicMediaLinkHelper::ExtractVideoNameIfExists(watch_url);
+  ASSERT_TRUE(video_name.has_value());
+  EXPECT_EQ(*video_name, "dQw4w9WgXcQ");
+
+  // Test case for a YouTube "embed" URL.
+  GURL embed_url("https://www.youtube.com/embed/dQw4w9WgXcQ");
+  video_name = GlicMediaLinkHelper::ExtractVideoNameIfExists(embed_url);
+  ASSERT_TRUE(video_name.has_value());
+  EXPECT_EQ(*video_name, "dQw4w9WgXcQ");
+
+  // Test case with other query parameters.
+  GURL watch_url_with_time("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42s");
+  video_name =
+      GlicMediaLinkHelper::ExtractVideoNameIfExists(watch_url_with_time);
+  ASSERT_TRUE(video_name.has_value());
+  EXPECT_EQ(*video_name, "dQw4w9WgXcQ");
+
+  // Test case with no 'v' parameter.
+  GURL no_v_param("https://www.youtube.com/watch?feature=youtu.be");
+  video_name = GlicMediaLinkHelper::ExtractVideoNameIfExists(no_v_param);
+  EXPECT_FALSE(video_name.has_value());
+
+  // Test case with an empty 'v' parameter.
+  GURL empty_v_param("https://www.youtube.com/watch?v=");
+  video_name = GlicMediaLinkHelper::ExtractVideoNameIfExists(empty_v_param);
+  EXPECT_FALSE(video_name.has_value());
+
+  // Test case with an invalid path.
+  GURL invalid_path("https://www.youtube.com/invalid/dQw4w9WgXcQ");
+  video_name = GlicMediaLinkHelper::ExtractVideoNameIfExists(invalid_path);
+  EXPECT_FALSE(video_name.has_value());
+}
+
+TEST_F(GlicMediaLinkHelperStaticTest, ExtractTimeFromQueryIfExists) {
+  // Test case with a valid time parameter.
+  GURL url_with_time("https://www.youtube.com/watch?v=123&t=42");
+  std::optional<base::TimeDelta> time =
+      GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_with_time);
+  ASSERT_TRUE(time.has_value());
+  EXPECT_EQ(*time, base::Seconds(42));
+
+  // Test case with "t" as the first parameter.
+  GURL url_with_time_first("https://www.youtube.com/watch?t=123&v=456");
+  time = GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_with_time_first);
+  ASSERT_TRUE(time.has_value());
+  EXPECT_EQ(*time, base::Seconds(123));
+
+  // Test case with no "t" parameter.
+  GURL url_no_time("https://www.youtube.com/watch?v=123");
+  time = GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_no_time);
+  EXPECT_FALSE(time.has_value());
+
+  // Test case with an empty "t" parameter.
+  GURL url_empty_time("https://www.youtube.com/watch?v=123&t=");
+  time = GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_empty_time);
+  EXPECT_FALSE(time.has_value());
+
+  // Test case with a non-numeric "t" parameter.
+  GURL url_non_numeric_time("https://www.youtube.com/watch?v=123&t=abc");
+  time =
+      GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_non_numeric_time);
+  EXPECT_FALSE(time.has_value());
+
+  // Test case with a negative "t" parameter.
+  GURL url_negative_time("https://www.youtube.com/watch?v=123&t=-30");
+  time = GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_negative_time);
+  EXPECT_FALSE(time.has_value());
+
+  // Test case with a fractional "t" parameter.
+  GURL url_fractional_time("https://www.youtube.com/watch?v=123&t=30.5");
+  time = GlicMediaLinkHelper::ExtractTimeFromQueryIfExists(url_fractional_time);
+  EXPECT_FALSE(time.has_value());
+}
+
 }  // namespace
 }  // namespace glic
diff --git a/chrome/browser/glic/public/glic_keyed_service.cc b/chrome/browser/glic/public/glic_keyed_service.cc
index a577087..e66f796 100644
--- a/chrome/browser/glic/public/glic_keyed_service.cc
+++ b/chrome/browser/glic/public/glic_keyed_service.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
 #include "base/feature_list.h"
+#include "base/functional/callback_forward.h"
 #include "base/location.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -60,6 +61,7 @@
 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
 #include "mojo/public/cpp/base/proto_wrapper.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
 #include "third_party/abseil-cpp/absl/strings/str_format.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "ui/base/page_transition_types.h"
@@ -366,18 +368,39 @@
   std::move(callback).Run(task_id.value());
 }
 
-void PerformActionsFinished(
+void GlicKeyedService::PerformActionsFinished(
     mojom::WebClientHandler::PerformActionsCallback callback,
+    actor::TaskId task_id,
     actor::mojom::ActionResultCode result_code,
     std::optional<size_t> index_of_failed_action) {
-  optimization_guide::proto::ActionsResult response =
-      actor::BuildActionsResult(result_code, index_of_failed_action);
-  std::move(callback).Run(mojo_base::ProtoWrapper(response));
+  actor::ActorTask* task =
+      actor::ActorKeyedService::Get(profile_)->GetTask(task_id);
+
+  // Task is checked when calling PerformActions and it doesn't go away.
+  CHECK(task);
+
+  // The callback doesn't need any weak semantics since all it does is wrap the
+  // result and pass it to the mojo callback. If `this` is destroyed the mojo
+  // connection is closed so this will be a no-op but the callback doesn't touch
+  // any freed memory.
+  auto result_callback = base::BindOnce(
+      [](mojom::WebClientHandler::PerformActionsCallback callback,
+         std::unique_ptr<optimization_guide::proto::ActionsResult> result) {
+        CHECK(result);
+        std::move(callback).Run(mojo_base::ProtoWrapper(*result));
+      },
+      std::move(callback));
+
+  actor::BuildActionsResultWithObservations(*profile_, result_code,
+                                            index_of_failed_action, *task,
+                                            std::move(result_callback));
 }
 
 void GlicKeyedService::PerformActions(
     const std::vector<uint8_t>& actions_proto,
     mojom::WebClientHandler::PerformActionsCallback callback) {
+  // TODO(bokan): Refactor the actor code in this class into an actor-specific
+  // wrapper for proto-to-actor conversion.
   optimization_guide::proto::Actions actions;
   if (!actions.ParseFromArray(actions_proto.data(), actions_proto.size())) {
     std::move(callback).Run(
@@ -398,6 +421,16 @@
   }
 
   actor::TaskId task_id(actions.task_id());
+  if (!actor_service->GetTask(task_id)) {
+    actor_service->GetJournal().Log(
+        GURL::EmptyGURL(), task_id, actor::mojom::JournalTrack::kActor,
+        "Act Failed", absl::StrFormat("No task with id[%d]", task_id.value()));
+    optimization_guide::proto::ActionsResult response =
+        actor::BuildErrorActionsResult(
+            actor::mojom::ActionResultCode::kTaskWentAway, std::nullopt);
+    std::move(callback).Run(mojo_base::ProtoWrapper(response));
+    return;
+  }
 
   actor::BuildToolRequestResult requests = actor::BuildToolRequest(actions);
   if (!requests.has_value()) {
@@ -407,7 +440,7 @@
         absl::StrFormat("Failed to convert proto::Actions[%d] to ToolRequest",
                         requests.error()));
     optimization_guide::proto::ActionsResult response =
-        actor::BuildActionsResult(
+        actor::BuildErrorActionsResult(
             actor::mojom::ActionResultCode::kArgumentsInvalid,
             requests.error());
     std::move(callback).Run(mojo_base::ProtoWrapper(response));
@@ -416,7 +449,8 @@
 
   actor_service->PerformActions(
       task_id, std::move(requests.value()),
-      base::BindOnce(PerformActionsFinished, std::move(callback)));
+      base::BindOnce(&GlicKeyedService::PerformActionsFinished, GetWeakPtr(),
+                     std::move(callback), task_id));
 }
 
 // TODO(crbug.com/411462297): Stop/Pause/Resume task need to be routed to go
@@ -443,6 +477,14 @@
   actor_controller_->ResumeTask(task_id, context_options, std::move(callback));
 }
 
+void GlicKeyedService::OnUserInputSubmitted(glic::mojom::WebClientMode mode) {
+  user_input_submitted_callback_list_.Notify();
+}
+
+base::CallbackListSubscription GlicKeyedService::AddUserInputSubmittedCallback(
+    base::RepeatingClosure callback) {
+  return user_input_submitted_callback_list_.Add(std::move(callback));
+}
 void GlicKeyedService::CaptureScreenshot(
     mojom::WebClientHandler::CaptureScreenshotCallback callback) {
   screenshot_capturer_->CaptureScreenshot(
diff --git a/chrome/browser/glic/public/glic_keyed_service.h b/chrome/browser/glic/public/glic_keyed_service.h
index d5b049d..a896f33 100644
--- a/chrome/browser/glic/public/glic_keyed_service.h
+++ b/chrome/browser/glic/public/glic_keyed_service.h
@@ -20,6 +20,7 @@
 #include "chrome/browser/glic/host/glic.mojom.h"
 #include "chrome/browser/glic/public/context/glic_sharing_manager.h"
 #include "chrome/browser/glic/widget/glic_window_controller.h"
+#include "chrome/common/actor.mojom-forward.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/web_contents.h"
 
@@ -167,6 +168,14 @@
       const mojom::GetTabContextOptions& context_options,
       glic::mojom::WebClientHandler::ResumeActorTaskCallback callback);
 
+  void OnUserInputSubmitted(glic::mojom::WebClientMode mode);
+
+  // Registers a callback to be called any time user input is submitted in the
+  // client. This is used to update UI effects on tabs that are being shared
+  // with glic.
+  base::CallbackListSubscription AddUserInputSubmittedCallback(
+      base::RepeatingClosure callback);
+
   void CaptureScreenshot(
       glic::mojom::WebClientHandler::CaptureScreenshotCallback callback);
 
@@ -214,6 +223,12 @@
   void FinishPreload(GlicPrewarmingChecksResult reason);
   void FinishPreloadFre(bool should_preload);
 
+  void PerformActionsFinished(
+      mojom::WebClientHandler::PerformActionsCallback callback,
+      actor::TaskId task_id,
+      actor::mojom::ActionResultCode result_code,
+      std::optional<size_t> index_of_failed_action);
+
   // List of callbacks to be notified when the client requests a change to the
   // context access indicator status.
   base::RepeatingCallbackList<void(bool)>
@@ -221,6 +236,9 @@
   // The state of the context access indicator as set by the client.
   bool is_context_access_indicator_enabled_ = false;
 
+  // List of callbacks to be notified when user input has been submitted.
+  base::RepeatingClosureList user_input_submitted_callback_list_;
+
   raw_ptr<Profile> profile_;
 
   std::unique_ptr<GlicEnabling> enabling_;
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewRenderTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewRenderTest.java
index 8f0876a..2073336 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewRenderTest.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewRenderTest.java
@@ -26,7 +26,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.supplier.ObservableSupplierImpl;
@@ -52,6 +53,8 @@
 @RunWith(BaseJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
 public class HubToolbarViewRenderTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public BaseActivityTestRule<BlankUiTestActivity> mActivityTestRule =
             new BaseActivityTestRule<>(BlankUiTestActivity.class);
@@ -75,7 +78,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mActivityTestRule.launchActivity(null);
         mActivity = mActivityTestRule.getActivity();
         mActivity.setTheme(R.style.Theme_BrowserUI_DayNight);
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java
index f28f1cd..bbca3f41 100644
--- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java
+++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java
@@ -31,7 +31,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.shared_preferences.SharedPreferencesManager;
@@ -54,6 +55,8 @@
 /** Unit tests for {@link ImageDescriptionsController} */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class ImageDescriptionsControllerTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public BaseActivityTestRule<BlankUiTestActivity> mActivityTestRule =
             new BaseActivityTestRule<>(BlankUiTestActivity.class);
@@ -79,8 +82,6 @@
     public void setUp() throws Exception {
         mActivityTestRule.launchActivity(null);
 
-        MockitoAnnotations.initMocks(this);
-
         ProfileJni.setInstanceForTesting(mProfileJniMock);
         when(mProfileJniMock.fromWebContents(mWebContents)).thenReturn(mProfile);
         when(mProfile.getOriginalProfile()).thenReturn(mProfile);
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java
index 705b078..49b7eec 100644
--- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java
+++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java
@@ -36,7 +36,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.shared_preferences.SharedPreferencesManager;
@@ -61,6 +62,8 @@
 /** Unit tests for {@link ImageDescriptionsDialog} */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class ImageDescriptionsDialogTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public BaseActivityTestRule<BlankUiTestActivity> mActivityTestRule =
             new BaseActivityTestRule<>(BlankUiTestActivity.class);
@@ -86,8 +89,6 @@
     public void setUp() throws Exception {
         mActivityTestRule.launchActivity(null);
 
-        MockitoAnnotations.initMocks(this);
-
         ProfileJni.setInstanceForTesting(mProfileJniMock);
         when(mProfileJniMock.fromWebContents(mWebContents)).thenReturn(mProfile);
         when(mProfile.getOriginalProfile()).thenReturn(mProfile);
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettingsTest.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettingsTest.java
index 4e3addb..b624f1a 100644
--- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettingsTest.java
+++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettingsTest.java
@@ -26,7 +26,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -58,6 +59,8 @@
     private static final String ONLY_ON_WIFI = "onlyOnWifi radio button ";
     private static final String USE_MOBILE_DATA = "useMobileData radio button ";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<ImageDescriptionsSettings> mSettingsActivityTestRule =
             new SettingsActivityTestRule<>(ImageDescriptionsSettings.class);
@@ -70,7 +73,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         ImageDescriptionsController.getInstance().setDelegateForTesting(mDelegate);
     }
 
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn
index 27da8cf1..5a9c8e02 100644
--- a/chrome/browser/incognito/BUILD.gn
+++ b/chrome/browser/incognito/BUILD.gn
@@ -96,6 +96,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//chrome/android:chrome_app_java_resources",
     "//chrome/android:chrome_java",
     "//chrome/android/features/tab_ui:test_support_javalib",
     "//chrome/browser/android/lifecycle:java",
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthCoordinatorTest.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthCoordinatorTest.java
index b75e66f..f583ebb 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthCoordinatorTest.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthCoordinatorTest.java
@@ -19,10 +19,12 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
@@ -40,6 +42,7 @@
 @LooperMode(LooperMode.Mode.PAUSED)
 @Batch(UNIT_TESTS)
 public class FullScreenIncognitoReauthCoordinatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Context mContextMock;
     @Mock private IncognitoReauthManager mIncognitoReauthManagerMock;
     @Mock private IncognitoReauthManager.IncognitoReauthCallback mIncognitoReauthCallbackMock;
@@ -64,7 +67,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mFullScreenIncognitoReauthCoordinator =
                 new FullScreenIncognitoReauthCoordinator(
                         mContextMock,
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthControllerImplTest.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthControllerImplTest.java
index d11ba27..11c4244 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthControllerImplTest.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthControllerImplTest.java
@@ -20,12 +20,14 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.LooperMode;
 
 import org.chromium.base.supplier.ObservableSupplierImpl;
@@ -51,6 +53,7 @@
 public class IncognitoReauthControllerImplTest {
     public static final int TASK_ID = 123;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private ActivityLifecycleDispatcher mActivityLifecycleDispatcherMock;
     @Mock private LayoutStateProvider mLayoutStateProviderMock;
     @Mock private TabModelSelector mTabModelSelectorMock;
@@ -92,8 +95,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         UserPrefsJni.setInstanceForTesting(mUserPrefsJniMock);
         when(mUserPrefsJniMock.get(mProfileMock)).thenReturn(mPrefServiceMock);
         when(mPrefServiceMock.getBoolean(Pref.INCOGNITO_REAUTHENTICATION_FOR_ANDROID))
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialogTest.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialogTest.java
index 6d83b9e..855cd04 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialogTest.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialogTest.java
@@ -20,10 +20,12 @@
 
 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.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
@@ -40,6 +42,7 @@
 @LooperMode(LooperMode.Mode.PAUSED)
 @Batch(UNIT_TESTS)
 public class IncognitoReauthDialogTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private ModalDialogManager mModalDialogManagerMock;
     @Mock private View mIncognitoReauthViewMock;
 
@@ -53,7 +56,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mIncognitoReauthDialog =
                 new IncognitoReauthDialog(
                         mModalDialogManagerMock,
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManagerTest.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManagerTest.java
index a7f124c..517e97f 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManagerTest.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManagerTest.java
@@ -13,10 +13,12 @@
 import androidx.test.filters.MediumTest;
 
 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.chromium.base.Callback;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -29,6 +31,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class IncognitoReauthManagerTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private IncognitoReauthManager mIncognitoReauthManager;
 
     @Mock private ReauthenticatorBridge mReauthenticatorBridgeMock;
@@ -37,7 +40,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mIncognitoReauthManager = new IncognitoReauthManager(mReauthenticatorBridgeMock);
     }
 
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthCoordinatorTest.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthCoordinatorTest.java
index ea77968..5ff06c3 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthCoordinatorTest.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthCoordinatorTest.java
@@ -18,10 +18,12 @@
 
 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.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
@@ -37,6 +39,7 @@
 @LooperMode(LooperMode.Mode.PAUSED)
 @Batch(UNIT_TESTS)
 public class TabSwitcherIncognitoReauthCoordinatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Context mContextMock;
     @Mock private IncognitoReauthManager mIncognitoReauthManagerMock;
     @Mock private IncognitoReauthManager.IncognitoReauthCallback mIncognitoReauthCallbackMock;
@@ -50,7 +53,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mTabSwitcherIncognitoReauthCoordinator =
                 new TabSwitcherIncognitoReauthCoordinator(
                         mContextMock,
diff --git a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthViewTest.java b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthViewTest.java
index ad6ccd16..c6ab629 100644
--- a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthViewTest.java
+++ b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/FullScreenIncognitoReauthViewTest.java
@@ -29,7 +29,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseActivityTestRule;
@@ -69,6 +70,8 @@
     @Mock private Runnable mCloseAllIncognitoTabsRunnable;
     @Mock private SettingsNavigation mSettingsNavigationMock;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public ChromeRenderTestRule mRenderTestRule =
             ChromeRenderTestRule.Builder.withPublicCorpus()
@@ -83,7 +86,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         SettingsNavigationFactory.setInstanceForTesting(mSettingsNavigationMock);
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
diff --git a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreferenceTest.java b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreferenceTest.java
index 9463f72..4fb341f 100644
--- a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreferenceTest.java
+++ b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreferenceTest.java
@@ -23,7 +23,8 @@
 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.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -35,6 +36,8 @@
     private static final String TITLE = "Preference Title";
     private static final String SUMMARY = "This is a summary.";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<PlaceholderSettingsForTest> mSettingsActivityTestRule =
             new SettingsActivityTestRule<>(PlaceholderSettingsForTest.class);
@@ -46,7 +49,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mSettingsActivityTestRule.startSettingsActivity();
         PreferenceFragmentCompat fragment =
                 (PreferenceFragmentCompat)
diff --git a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthViewTest.java b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthViewTest.java
index d73ed5a9..593c7fa 100644
--- a/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthViewTest.java
+++ b/chrome/browser/incognito/android/javatests/src/org/chromium/chrome/browser/incognito/reauth/TabSwitcherIncognitoReauthViewTest.java
@@ -154,8 +154,7 @@
                 .check(matches(not(isDisplayed())));
 
         mRenderTestRule.render(
-                cta.findViewById(org.chromium.chrome.R.id.tab_switcher_view_holder),
-                "incognito_reauth_view_hub");
+                cta.findViewById(R.id.tab_switcher_view_holder), "incognito_reauth_view_hub");
     }
 
     @Test
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialogTest.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialogTest.java
index 6edabe7d..cb5304eb 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialogTest.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialogTest.java
@@ -9,10 +9,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.annotation.Config;
 
 import org.chromium.base.LocaleUtils;
@@ -33,6 +35,7 @@
 @Config(manifest = Config.NONE)
 public class AppLanguagePromoDialogTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Profile mProfile;
 
     LanguageItem mFollowSystem;
@@ -50,7 +53,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         LanguageTestUtils.initializeResourceBundleForTesting();
         mFollowSystem = LanguageItem.makeFollowSystemLanguageItem();
         mLangAf = new LanguageItem("af", "Afrikaans", "Afrikaans", true);
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/LanguageBridgeTest.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/LanguageBridgeTest.java
index 799f641..9080e2f7 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/LanguageBridgeTest.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/LanguageBridgeTest.java
@@ -8,10 +8,12 @@
 
 import org.junit.Assert;
 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.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -26,12 +28,12 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class LanguageBridgeTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private FakeLanguageBridgeJni mFakeLanguageBridge;
     @Mock private Profile mProfile;
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         // Setup fake language bridge JNI interface
         mFakeLanguageBridge = new FakeLanguageBridgeJni();
         LanguageBridgeJni.setInstanceForTesting(mFakeLanguageBridge);
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManagerTest.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManagerTest.java
index 0f67700c..ec9a0740 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManagerTest.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManagerTest.java
@@ -11,11 +11,13 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -38,12 +40,12 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class LanguagesManagerTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private FakeTranslateBridgeJni mFakeTranslateBridge;
     @Mock private Profile mProfile;
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         Mockito.when(mProfile.getOriginalProfile()).thenReturn(mProfile);
         ProfileManager.setLastUsedProfileForTesting(mProfile);
         LanguageTestUtils.initializeResourceBundleForTesting();
diff --git a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java
index 34a6682..434b7b24 100644
--- a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java
+++ b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java
@@ -18,9 +18,11 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
 
@@ -38,6 +40,7 @@
 /** Tests that ChannelsUpdater correctly initializes channels on the notification manager. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class ChannelsUpdaterTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private BaseNotificationManagerProxy mNotificationManagerProxy;
     private SharedPreferencesManager mSharedPreferences;
     private ChannelsInitializer mChannelsInitializer;
@@ -45,8 +48,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         Context context = RuntimeEnvironment.getApplication();
         mNotificationManagerProxy = BaseNotificationManagerProxyFactory.create();
 
diff --git a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionRationaleBottomSheetTest.java b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionRationaleBottomSheetTest.java
index 29e19bad..41ab852 100644
--- a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionRationaleBottomSheetTest.java
+++ b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionRationaleBottomSheetTest.java
@@ -22,13 +22,15 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordHistogram;
@@ -43,6 +45,7 @@
 /** Tests for {@link NotificationPermissionRationaleBottomSheet}. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class NotificationPermissionRationaleBottomSheetTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private BottomSheetController mBottomSheetController;
     private Context mContext;
 
@@ -52,7 +55,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mBottomSheetController = Mockito.mock(BottomSheetController.class);
         when(mBottomSheetController.requestShowContent(any(), anyBoolean())).thenReturn(true);
 
diff --git a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java
index c132d78..2194996 100644
--- a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java
+++ b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java
@@ -18,10 +18,12 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
@@ -42,6 +44,7 @@
     private static final String TEST_URL = "https://testurl.com/";
     private static final String TEST_URL2 = "https://testurl2.com/";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock;
 
     @Mock OptimizationGuideBridge.OptimizationGuideCallback mCallbackMock;
@@ -50,7 +53,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         OptimizationGuideBridgeJni.setInstanceForTesting(mOptimizationGuideBridgeJniMock);
     }
 
diff --git a/chrome/browser/paint_preview/services/paint_preview_tab_service.cc b/chrome/browser/paint_preview/services/paint_preview_tab_service.cc
index 1ed0948..200dc17 100644
--- a/chrome/browser/paint_preview/services/paint_preview_tab_service.cc
+++ b/chrome/browser/paint_preview/services/paint_preview_tab_service.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/paint_preview/services/paint_preview_tab_service_file_mixin.h"
 #include "components/paint_preview/browser/file_manager.h"
 #include "components/paint_preview/browser/warm_compositor.h"
+#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
 #include "content/public/browser/render_process_host.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/gfx/geometry/rect.h"
@@ -316,7 +317,9 @@
   capture_params.root_dir = &file_path.value();
   capture_params.persistence = RecordingPersistence::kFileSystem;
   capture_params.clip_rect =
-      gfx::Rect(-1, -1, kMaxCaptureSizePixels, kMaxCaptureSizePixels);
+      gfx::Rect(paint_preview::mojom::kCenterOnScrollOffset,
+                paint_preview::mojom::kCenterOnScrollOffset,
+                kMaxCaptureSizePixels, kMaxCaptureSizePixels);
   capture_params.capture_links = true;
   capture_params.max_per_capture_size = kMaxPerCaptureSizeBytes;
   capture_params.max_decoded_image_size_bytes = kMaxDecodedImageSizeBytes;
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
index 8569caf..3b957e2 100644
--- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
+++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
@@ -17,7 +17,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -34,6 +35,8 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PasswordCheckIntegrationTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public final SettingsActivityTestRule<PasswordCheckFragmentView> mTestRule =
             new SettingsActivityTestRule<>(PasswordCheckFragmentView.class);
@@ -42,7 +45,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         PasswordCheckBridgeJni.setInstanceForTesting(mPasswordCheckBridge);
     }
 
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
index 05849ed..4f4775b 100644
--- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
+++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
@@ -77,7 +77,8 @@
 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.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
@@ -178,13 +179,14 @@
     @Mock private Runnable mMockLaunchCheckupInAccount;
     @Mock private Runnable mMockStartButtonCallback;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<PasswordCheckFragmentView> mTestRule =
             new SettingsActivityTestRule<>(PasswordCheckFragmentView.class);
 
     @Before
     public void setUp() throws InterruptedException {
-        MockitoAnnotations.initMocks(this);
         PasswordCheckComponentUiFactory.setCreationStrategy(
                 (fragmentView, customTabIntentHelper, trustedIntentHelper, profile) -> {
                     mPasswordCheckView = (PasswordCheckFragmentView) fragmentView;
diff --git a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
index 8d78b74..1e815bc8 100644
--- a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
+++ b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
@@ -44,12 +44,14 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.Callback;
@@ -126,6 +128,7 @@
     private static final String PASSWORD_CHECK_COMPROMISED_CREDENTIALS_AFTER_CHECK_HISTOGRAM =
             "PasswordManager.BulkCheck.CompromisedCredentialsCountAfterCheckAndroid";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private PasswordCheckComponentUi.Delegate mDelegate;
     @Mock private PasswordCheckChangePasswordHelper mChangePasswordDelegate;
     @Mock private PasswordCheck mPasswordCheck;
@@ -139,7 +142,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mModel = PasswordCheckProperties.createDefaultModel();
         mMediator =
                 new PasswordCheckMediator(
diff --git a/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditControllerTest.java b/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditControllerTest.java
index 79d3541..5262a5d 100644
--- a/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditControllerTest.java
+++ b/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditControllerTest.java
@@ -43,10 +43,12 @@
 import androidx.test.core.app.ApplicationProvider;
 
 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.annotation.Config;
 
 import org.chromium.base.Callback;
@@ -70,6 +72,7 @@
     private static final String TEST_PASSWORD = "TestPassword";
     private static final String NEW_TEST_PASSWORD = "TestNewPassword";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private PasswordAccessReauthenticationHelper mReauthenticationHelper;
 
     @Mock private ConfirmationDialogHelper mDeleteDialogHelper;
@@ -88,7 +91,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         Clipboard.resetForTesting();
         mMediator =
                 new CredentialEditMediator(
diff --git a/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditViewTest.java b/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditViewTest.java
index ebcbf18..5292ad9 100644
--- a/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditViewTest.java
+++ b/chrome/browser/password_entry_edit/android/internal/java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditViewTest.java
@@ -39,7 +39,8 @@
 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.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -63,13 +64,14 @@
     private CredentialEditFragmentView mCredentialEditView;
     private PropertyModel mModel;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<CredentialEditFragmentView> mTestRule =
             new SettingsActivityTestRule<>(CredentialEditFragmentView.class);
 
     @Before
     public void setUp() throws InterruptedException {
-        MockitoAnnotations.initMocks(this);
         CredentialEditUiFactory.setCreationStrategy(
                 (fragmentView, helpLauncher) -> {
                     mCredentialEditView = (CredentialEditFragmentView) fragmentView;
diff --git a/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc b/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
index d208aea..9d0a4fab 100644
--- a/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
+++ b/chrome/browser/password_manager/chrome_webauthn_credentials_delegate_unittest.cc
@@ -46,6 +46,7 @@
 #if BUILDFLAG(IS_ANDROID)
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/webauthn/android/webauthn_request_delegate_android.h"
+#include "components/webauthn/android/webauthn_client_android.h"
 #endif
 
 namespace {
@@ -154,11 +155,13 @@
     dialog_controller()->StartFlow(std::move(tai), /*passwords=*/{});
 #else
     delegate_->OnWebAuthnRequestPending(
-        main_rfh(), creds, /*is_conditional_request=*/true,
+        main_rfh(), creds, webauthn::AssertionMediationType::kConditional,
         base::BindRepeating(
             &ChromeWebAuthnCredentialsDelegateTest::OnAccountSelected,
             base::Unretained(this)),
-        /*hybrid_callback=*/base::RepeatingClosure());
+        /*password_callback=*/base::DoNothing(),
+        /*hybrid_callback=*/base::RepeatingClosure(),
+        /*reject_immediate_callback=*/base::DoNothing());
 #endif
   }
 
diff --git a/chrome/browser/password_manager/password_change/change_password_form_filling_submission_helper.cc b/chrome/browser/password_manager/password_change/change_password_form_filling_submission_helper.cc
index 3dac80f..5f9d6b5 100644
--- a/chrome/browser/password_manager/password_change/change_password_form_filling_submission_helper.cc
+++ b/chrome/browser/password_manager/password_change/change_password_form_filling_submission_helper.cc
@@ -27,6 +27,10 @@
 
 using Logger = password_manager::BrowserSavePasswordProgressLogger;
 
+constexpr optimization_guide::proto::PasswordChangeRequest::FlowStep
+    kSubmitFormFlowStep = optimization_guide::proto::PasswordChangeRequest::
+        FlowStep::PasswordChangeRequest_FlowStep_SUBMIT_FORM_STEP;
+
 blink::mojom::AIPageContentOptionsPtr GetAIPageContentOptions() {
   auto options = blink::mojom::AIPageContentOptions::New();
   // WebContents where password change is happening is hidden, and renderer
@@ -62,6 +66,7 @@
       client_(client),
       logs_uploader_(logs_uploader),
       callback_(std::move(callback)) {
+  CHECK(logs_uploader_);
   capture_annotated_page_content_ =
       base::BindOnce(&optimization_guide::GetAIPageContent, web_contents,
                      GetAIPageContentOptions());
@@ -242,6 +247,7 @@
   }
 
   if (success) {
+    logs_uploader_->MarkStepSkipped(kSubmitFormFlowStep);
     OnFormSubmitted();
     return;
   }
@@ -263,8 +269,7 @@
     return;
   }
   optimization_guide::proto::PasswordChangeRequest request;
-  request.set_step(optimization_guide::proto::PasswordChangeRequest::FlowStep::
-                       PasswordChangeRequest_FlowStep_SUBMIT_FORM_STEP);
+  request.set_step(kSubmitFormFlowStep);
   *request.mutable_page_context()->mutable_annotated_page_content() =
       std::move(content->proto);
   optimization_guide::ExecuteModelWithLogging(
diff --git a/chrome/browser/password_manager/password_change/change_password_form_finder.cc b/chrome/browser/password_manager/password_change/change_password_form_finder.cc
index 7c33e6c..6d18bb7 100644
--- a/chrome/browser/password_manager/password_change/change_password_form_finder.cc
+++ b/chrome/browser/password_manager/password_change/change_password_form_finder.cc
@@ -22,6 +22,10 @@
 
 using Logger = password_manager::BrowserSavePasswordProgressLogger;
 
+constexpr optimization_guide::proto::PasswordChangeRequest::FlowStep
+    kOpenFormFlowStep = optimization_guide::proto::PasswordChangeRequest::
+        FlowStep::PasswordChangeRequest_FlowStep_OPEN_FORM_STEP;
+
 blink::mojom::AIPageContentOptionsPtr GetAIPageContentOptions() {
   auto options = optimization_guide::DefaultAIPageContentOptions();
   // WebContents where password change is happening is hidden, and renderer
@@ -60,6 +64,7 @@
       change_password_url_(change_password_url),
       callback_(std::move(callback)),
       login_form_found_callback_(std::move(login_form_found_callback)) {
+  CHECK(logs_uploader_);
   capture_annotated_page_content_ =
       base::BindOnce(&optimization_guide::GetAIPageContent, web_contents,
                      GetAIPageContentOptions());
@@ -108,6 +113,7 @@
 
   // Change password form found, invoke callback immediately.
   if (result.change_password_form_manager) {
+    logs_uploader_->MarkStepSkipped(kOpenFormFlowStep);
     std::move(callback_).Run(result.change_password_form_manager);
     return;
   }
@@ -151,8 +157,7 @@
   }
 
   optimization_guide::proto::PasswordChangeRequest request;
-  request.set_step(optimization_guide::proto::PasswordChangeRequest::FlowStep::
-                       PasswordChangeRequest_FlowStep_OPEN_FORM_STEP);
+  request.set_step(kOpenFormFlowStep);
   *request.mutable_page_context()->mutable_annotated_page_content() =
       std::move(content->proto);
   *request.mutable_page_context()->mutable_title() =
diff --git a/chrome/browser/password_manager/password_change/model_quality_logs_uploader.cc b/chrome/browser/password_manager/password_change/model_quality_logs_uploader.cc
index 280d2fb..f6384bb 100644
--- a/chrome/browser/password_manager/password_change/model_quality_logs_uploader.cc
+++ b/chrome/browser/password_manager/password_change/model_quality_logs_uploader.cc
@@ -95,8 +95,8 @@
       PasswordChangeQuality_StepQuality_SubmissionStatus_ACTION_SUCCESS;
 }
 
-optimization_guide::proto::PasswordChangeQuality_StepQuality* GetNextStep(
-    optimization_guide::proto::LogAiDataRequest& log) {
+optimization_guide::proto::PasswordChangeQuality_StepQuality*
+GetNextStepQuality(optimization_guide::proto::LogAiDataRequest& log) {
   optimization_guide::proto::PasswordChangeQuality* quality =
       log.mutable_password_change_submission()->mutable_quality();
   if (quality->submit_form().status() !=
@@ -113,6 +113,26 @@
   return quality->mutable_open_form();
 }
 
+optimization_guide::proto::PasswordChangeQuality_StepQuality* GetStepQuality(
+    ModelQualityLogsUploader::FlowStep step,
+    optimization_guide::proto::LogAiDataRequest& log) {
+  optimization_guide::proto::PasswordChangeQuality* quality =
+      log.mutable_password_change_submission()->mutable_quality();
+  switch (step) {
+    case ModelQualityLogsUploader::FlowStep::
+        PasswordChangeRequest_FlowStep_OPEN_FORM_STEP:
+      return quality->mutable_open_form();
+    case ModelQualityLogsUploader::FlowStep::
+        PasswordChangeRequest_FlowStep_SUBMIT_FORM_STEP:
+      return quality->mutable_submit_form();
+    case ModelQualityLogsUploader::FlowStep::
+        PasswordChangeRequest_FlowStep_VERIFY_SUBMISSION_STEP:
+      return quality->mutable_verify_submission();
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace
 
 ModelQualityLogsUploader::ModelQualityLogsUploader(
@@ -199,19 +219,27 @@
 }
 
 void ModelQualityLogsUploader::SetFlowInterrupted() {
-  GetNextStep(final_log_data_)
+  GetNextStepQuality(final_log_data_)
       ->set_status(
           QualityStatus::
               PasswordChangeQuality_StepQuality_SubmissionStatus_FLOW_INTERRUPTED);
 }
 
 void ModelQualityLogsUploader::SetOtpDetected() {
-  GetNextStep(final_log_data_)
+  GetNextStepQuality(final_log_data_)
       ->set_status(
           QualityStatus::
               PasswordChangeQuality_StepQuality_SubmissionStatus_OTP_DETECTED);
 }
 
+void ModelQualityLogsUploader::MarkStepSkipped(
+    optimization_guide::proto::PasswordChangeRequest::FlowStep step) {
+  GetStepQuality(step, final_log_data_)
+      ->set_status(
+          QualityStatus::
+              PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED);
+}
+
 void ModelQualityLogsUploader::OpenFormTargetElementNotFound() {
   final_log_data_.mutable_password_change_submission()
       ->mutable_quality()
diff --git a/chrome/browser/password_manager/password_change/model_quality_logs_uploader.h b/chrome/browser/password_manager/password_change/model_quality_logs_uploader.h
index 4144cd9c..6046826 100644
--- a/chrome/browser/password_manager/password_change/model_quality_logs_uploader.h
+++ b/chrome/browser/password_manager/password_change/model_quality_logs_uploader.h
@@ -22,6 +22,7 @@
       optimization_guide::proto::PasswordChangeSubmissionLoggingData;
   using QualityStatus = optimization_guide::proto::
       PasswordChangeQuality_StepQuality_SubmissionStatus;
+  using FlowStep = optimization_guide::proto::PasswordChangeRequest::FlowStep;
 
   explicit ModelQualityLogsUploader(content::WebContents* web_contents);
   ~ModelQualityLogsUploader();
@@ -56,6 +57,11 @@
   // because an OTP was detected.
   void SetOtpDetected();
 
+  // Marks a flow step as skipped, indicating no
+  // model call was made for this step.
+  void MarkStepSkipped(
+      optimization_guide::proto::PasswordChangeRequest::FlowStep step);
+
   // To be called if element to click was not found
   // in Step=OPEN_FORM_STEP.
   void OpenFormTargetElementNotFound();
diff --git a/chrome/browser/password_manager/password_change/model_quality_logs_uploader_unittest.cc b/chrome/browser/password_manager/password_change/model_quality_logs_uploader_unittest.cc
index df82c944..81ea01f 100644
--- a/chrome/browser/password_manager/password_change/model_quality_logs_uploader_unittest.cc
+++ b/chrome/browser/password_manager/password_change/model_quality_logs_uploader_unittest.cc
@@ -30,6 +30,7 @@
 using PasswordChangeOutcome = ::optimization_guide::proto::
     PasswordChangeSubmissionData_PasswordChangeOutcome;
 using PageType = optimization_guide::proto::OpenFormResponseData_PageType;
+using FlowStep = optimization_guide::proto::PasswordChangeRequest::FlowStep;
 
 namespace {
 void CheckOpenFormStatus(const optimization_guide::proto::LogAiDataRequest& log,
@@ -453,6 +454,59 @@
       FinalModelStatus::FINAL_MODEL_STATUS_UNSPECIFIED);
 }
 
+TEST_F(ModelQualityLogsUploaderTest, OpenFormSkipped) {
+  const base::Time fake_start_time = base::Time::Now();
+  ModelQualityLogsUploader logs_uploader(web_contents());
+  // Set initial open form data for ACTION_SUCCESS status.
+  optimization_guide::proto::PasswordChangeResponse open_form_response;
+  open_form_response.mutable_open_form_data()->set_page_type(
+      PageType::OpenFormResponseData_PageType_SETTINGS_PAGE);
+  open_form_response.mutable_open_form_data()->set_dom_node_id_to_click(123);
+  logs_uploader.SetOpenFormQuality(open_form_response, CreateLoggingData(),
+                                   fake_start_time);
+  const optimization_guide::proto::LogAiDataRequest initial_log =
+      logs_uploader.GetFinalLog();
+  CheckOpenFormStatus(
+      initial_log,
+      QualityStatus::
+          PasswordChangeQuality_StepQuality_SubmissionStatus_ACTION_SUCCESS);
+
+  logs_uploader.MarkStepSkipped(
+      FlowStep::PasswordChangeRequest_FlowStep_OPEN_FORM_STEP);
+  const optimization_guide::proto::LogAiDataRequest final_log =
+      logs_uploader.GetFinalLog();
+  CheckOpenFormStatus(
+      final_log,
+      QualityStatus::
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED);
+}
+
+TEST_F(ModelQualityLogsUploaderTest, SubmitFormSkipped) {
+  const base::Time fake_start_time = base::Time::Now();
+  ModelQualityLogsUploader logs_uploader(web_contents());
+  // Set initial submit form data for ACTION_SUCCESS status.
+  optimization_guide::proto::PasswordChangeResponse submit_form_response;
+  submit_form_response.mutable_submit_form_data()->set_dom_node_id_to_click(
+      123);
+  logs_uploader.SetSubmitFormQuality(submit_form_response, CreateLoggingData(),
+                                     fake_start_time);
+  const optimization_guide::proto::LogAiDataRequest initial_log =
+      logs_uploader.GetFinalLog();
+  CheckSubmitFormStatus(
+      initial_log,
+      QualityStatus::
+          PasswordChangeQuality_StepQuality_SubmissionStatus_ACTION_SUCCESS);
+
+  logs_uploader.MarkStepSkipped(
+      FlowStep::PasswordChangeRequest_FlowStep_SUBMIT_FORM_STEP);
+  const optimization_guide::proto::LogAiDataRequest final_log =
+      logs_uploader.GetFinalLog();
+  CheckSubmitFormStatus(
+      final_log,
+      QualityStatus::
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED);
+}
+
 TEST_F(ModelQualityLogsUploaderTest, SubmitFormTargetElementNotFound) {
   const base::Time fake_start_time = base::Time::Now();
   ModelQualityLogsUploader logs_uploader(web_contents());
diff --git a/chrome/browser/password_manager/password_change_browsertest.cc b/chrome/browser/password_manager/password_change_browsertest.cc
index 63a1f44..abcb241 100644
--- a/chrome/browser/password_manager/password_change_browsertest.cc
+++ b/chrome/browser/password_manager/password_change_browsertest.cc
@@ -527,10 +527,10 @@
   VerifyUniqueQualityLog(
       /*open_form_status=*/
       QualityStatus::
-          PasswordChangeQuality_StepQuality_SubmissionStatus_UNKNOWN_STATUS,
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED,
       /* submit_form_status=*/
       QualityStatus::
-          PasswordChangeQuality_StepQuality_SubmissionStatus_UNKNOWN_STATUS,
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED,
       /*verify_submission_status=*/
       QualityStatus::
           PasswordChangeQuality_StepQuality_SubmissionStatus_ACTION_SUCCESS,
@@ -719,10 +719,10 @@
   VerifyUniqueQualityLog(
       /*open_form_status=*/
       QualityStatus::
-          PasswordChangeQuality_StepQuality_SubmissionStatus_UNKNOWN_STATUS,
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED,
       /* submit_form_status=*/
       QualityStatus::
-          PasswordChangeQuality_StepQuality_SubmissionStatus_UNKNOWN_STATUS,
+          PasswordChangeQuality_StepQuality_SubmissionStatus_STEP_SKIPPED,
       /*verify_submission_status=*/
       QualityStatus::
           PasswordChangeQuality_StepQuality_SubmissionStatus_FAILURE_STATUS,
diff --git a/chrome/browser/permissions/BUILD.gn b/chrome/browser/permissions/BUILD.gn
index cb7b8d4..ae6b6de 100644
--- a/chrome/browser/permissions/BUILD.gn
+++ b/chrome/browser/permissions/BUILD.gn
@@ -190,12 +190,16 @@
   sources = [
     "//chrome/browser/permissions/test/enums_to_string.cc",
     "//chrome/browser/permissions/test/enums_to_string.h",
+    "//chrome/browser/permissions/test/mock_passage_embedder.cc",
+    "//chrome/browser/permissions/test/mock_passage_embedder.h",
     "system/mock_platform_handle.cc",
     "system/mock_platform_handle.h",
   ]
 
   deps = [
     ":permissions",
+    "//components/passage_embeddings:test_support",
+    "//components/permissions:test_support",
     "//testing/gmock",
   ]
 }
@@ -279,6 +283,7 @@
 
     deps = [
       ":permissions",
+      ":test_support",
       "//chrome/browser/content_settings:content_settings_factory",
       "//chrome/browser/media/webrtc",
       "//chrome/browser/optimization_guide",
@@ -288,6 +293,7 @@
       "//chrome/test:test_support",
       "//components/back_forward_cache",
       "//components/optimization_guide/core:test_support",
+      "//components/passage_embeddings:test_support",
     ]
 
     if (is_chromeos) {
diff --git a/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.cc b/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.cc
index e36752c..d63642f 100644
--- a/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.cc
+++ b/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.cc
@@ -41,6 +41,8 @@
 #include "content/public/browser/web_contents.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 
+// TODO(crbug.com/382447738): Fix tflite defines; this might not build for
+// tflite right now.
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 #include "components/passage_embeddings/passage_embeddings_types.h"
 #include "components/permissions/prediction_service/permissions_aiv3_handler.h"
@@ -49,7 +51,8 @@
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
 namespace {
-
+using ComputePassagesEmbeddingsCallback =
+    ::passage_embeddings::Embedder::ComputePassagesEmbeddingsCallback;
 using ::permissions::PermissionRequest;
 using ::permissions::PermissionRequestRelevance;
 using ::permissions::PermissionsAiv1Handler;
@@ -111,6 +114,22 @@
 }
 }  // namespace
 
+inline PredictionBasedPermissionUiSelector::ModelExecutionData::
+    ModelExecutionData() = default;
+inline PredictionBasedPermissionUiSelector::ModelExecutionData::
+    ModelExecutionData(
+        PredictionBasedPermissionUiSelector::ModelExecutionData&&) = default;
+inline PredictionBasedPermissionUiSelector::ModelExecutionData::
+    ~ModelExecutionData() = default;
+
+PredictionBasedPermissionUiSelector::ModelExecutionData::ModelExecutionData(
+    permissions::PredictionRequestFeatures features,
+    PredictionRequestMetadata request_metadata,
+    permissions::PredictionModelType model_type)
+    : features(std::move(features)),
+      request_metadata(std::move(request_metadata)),
+      model_type(model_type) {}
+
 PredictionBasedPermissionUiSelector::PredictionBasedPermissionUiSelector(
     Profile* profile)
     : profile_(profile) {
@@ -225,7 +244,8 @@
       /*success=*/!snapshot.drawsNothing(), snapshot_inquire_start_time,
       model_data.model_type);
   if (snapshot.drawsNothing()) {
-    VLOG(1) << "[PermissionsAI] The page's snapshot is empty";
+    VLOG(1) << "[PermissionsAI] The page's snapshot is empty; skipping AivX "
+               "on-device model execution.";
     return InquireServerModel(model_data.features,
                               std::move(model_data.request_metadata));
   }
@@ -367,17 +387,29 @@
     ModelExecutionData model_data,
     ModelExecutionCallback model_execution_callback,
     std::unique_ptr<content_extraction::InnerTextResult> result) {
+  VLOG(1) << "[PermissionsAI] OnGetInnerTextForOnDeviceModel";
   if (result && result->inner_text.size() > kPageContentMinLength) {
-    model_data.inner_text = std::move(result->inner_text);
-    if (model_data.model_type == PredictionModelType::kOnDeviceAiV1Model &&
-        model_data.inner_text.size() > kPageContentMaxLength) {
-      model_data.inner_text.resize(kPageContentMaxLength);
+    std::string inner_text = std::move(result->inner_text);
+    if (model_data.model_type == PredictionModelType::kOnDeviceAiV1Model) {
+      if (inner_text.size() > kPageContentMaxLength) {
+        inner_text.resize(kPageContentMaxLength);
+      }
+      model_data.inner_text = std::move(inner_text);
+      return std::move(model_execution_callback).Run(std::move(model_data));
     }
+    // Aiv4
+    // TODO(chrbug.com/382447738) Add histogram to track execution time of this
+    return CreatePassageEmbeddingFromRenderedText(
+        std::move(inner_text),
+        base::BindOnce(
+            &PredictionBasedPermissionUiSelector::OnPassageEmbeddingsComputed,
+            weak_ptr_factory_.GetWeakPtr(), std::move(model_data),
 
-    return std::move(model_execution_callback).Run(std::move(model_data));
+            std::move(model_execution_callback)));
   }
 
-  VLOG(1) << "[PermissionsAI] The page's content is too short or empty";
+  VLOG(1) << "[PermissionsAI] The page's content is too short or empty; "
+             "skipping execution of AivX on-device model";
   InquireServerModel(model_data.features,
                      std::move(model_data.request_metadata));
 }
@@ -385,6 +417,7 @@
 void PredictionBasedPermissionUiSelector::Cancel() {
   request_.reset();
   callback_.Reset();
+  passage_embeddings_task_id_ = std::nullopt;
 }
 
 bool PredictionBasedPermissionUiSelector::IsPermissionRequestSupported(
@@ -500,10 +533,10 @@
     bool lookup_successful,
     bool response_from_cache,
     const std::optional<permissions::GeneratePredictionsResponse>& response) {
-  // This function is used as callback for request to the CPSSv1 on-device model
-  // and the CPSSv3 server-side model. As we have multiple prediction sources
-  // that use the server side model in the end, we check for the CPSSv1 here and
-  // set is_on_device depending on this.
+  // This function is used as callback for request to the CPSSv1 on-device
+  // model and the CPSSv3 server-side model. As we have multiple prediction
+  // sources that use the server side model in the end, we check for the
+  // CPSSv1 here and set is_on_device depending on this.
   bool is_on_device_cpss_v1 = request_metadata.prediction_source ==
                               PredictionSource::kOnDeviceCpssV1Model;
   PermissionUmaUtil::RecordPredictionModelInquireTime(
@@ -686,24 +719,6 @@
   inner_text_for_testing_ = inner_text_;
 }
 
-void PredictionBasedPermissionUiSelector::GetInnerText(
-    content::RenderFrameHost* render_frame_host,
-    ModelExecutionData model_data,
-    ModelExecutionCallback model_execution_callback) {
-  if (inner_text_for_testing_.has_value()) {
-    return OnGetInnerTextForOnDeviceModel(
-        std::move(model_data), std::move(model_execution_callback),
-        std::make_unique<content_extraction::InnerTextResult>(
-            std::move(inner_text_for_testing_.value())));
-  }
-  content_extraction::GetInnerText(
-      *render_frame_host, /*node_id=*/std::nullopt,
-      base::BindOnce(
-          &PredictionBasedPermissionUiSelector::OnGetInnerTextForOnDeviceModel,
-          weak_ptr_factory_.GetWeakPtr(), std::move(model_data),
-          std::move(model_execution_callback)));
-}
-
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 void PredictionBasedPermissionUiSelector::set_snapshot_for_testing(
     SkBitmap snapshot) {
@@ -732,6 +747,26 @@
                        snapshot_inquire_start_time, std::move(model_data)));
   }
 }
+#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
+void PredictionBasedPermissionUiSelector::GetInnerText(
+    content::RenderFrameHost* render_frame_host,
+    ModelExecutionData model_data,
+    ModelExecutionCallback model_execution_callback) {
+  VLOG(1) << "[PermissionsAI] GetInnerText";
+  if (inner_text_for_testing_.has_value()) {
+    return OnGetInnerTextForOnDeviceModel(
+        std::move(model_data), std::move(model_execution_callback),
+        std::make_unique<content_extraction::InnerTextResult>(
+            std::move(inner_text_for_testing_.value())));
+  }
+  content_extraction::GetInnerText(
+      *render_frame_host, /*node_id=*/std::nullopt,
+      base::BindOnce(
+          &PredictionBasedPermissionUiSelector::OnGetInnerTextForOnDeviceModel,
+          weak_ptr_factory_.GetWeakPtr(), std::move(model_data),
+          std::move(model_execution_callback)));
+}
 
 void PredictionBasedPermissionUiSelector::ExecuteOnDeviceAivXModel(
     ModelExecutionData model_data) {
@@ -751,7 +786,7 @@
                     ->GetPermissionsAiv1Handler()) {
           VLOG(1) << "[PermissionsAIv1] Inquire model";
           return aiv1_handler->InquireAiOnDeviceModel(
-              std::move(model_data.inner_text), request_type,
+              std::move(model_data.inner_text.value()), request_type,
               base::BindOnce(&PredictionBasedPermissionUiSelector::
                                  OnDeviceAiv1ModelExecutionCallback,
                              weak_ptr_factory_.GetWeakPtr(),
@@ -760,7 +795,9 @@
         }
         break;
       }
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
       case PredictionModelType::kOnDeviceAiV3Model: {
+        DCHECK(model_data.snapshot.has_value());
         VLOG(1)
             << "[PermissionsAI] ExecuteOnDeviceAivXModel kOnDeviceAiV3Model";
         if (PermissionsAiv3Handler* aiv3_handler =
@@ -768,7 +805,7 @@
                     request_type)) {
           VLOG(1) << "[PermissionsAI] Inquire AIv3 model";
           return aiv3_handler->ExecuteModel(
-              base::BindOnce(
+              /*callback=*/base::BindOnce(
                   &PredictionBasedPermissionUiSelector::
                       OnDeviceTfliteAivXModelExecutionCallback,
                   weak_ptr_factory_.GetWeakPtr(),
@@ -776,7 +813,7 @@
                   std::move(model_data.features),
                   std::move(model_data.request_metadata),
                   model_data.model_type),
-              PermissionsAiv3Handler::ModelInput(
+              /*model_input=*/PermissionsAiv3Handler::ModelInput(
                   std::move(model_data.snapshot.value())));
         } else {
           VLOG(1) << "[PermissionsAI] No AIv3 handler";
@@ -784,12 +821,14 @@
         break;
       }
       case PredictionModelType::kOnDeviceAiV4Model: {
+        DCHECK(model_data.snapshot.has_value());
+        DCHECK(model_data.inner_text_embedding.has_value());
         if (PermissionsAiv4Handler* aiv4_handler =
                 prediction_model_handler_provider->GetPermissionsAiv4Handler(
                     request_type)) {
           VLOG(1) << "[PermissionsAIv4] Inquire model";
           return aiv4_handler->ExecuteModel(
-              base::BindOnce(
+              /*callback=*/base::BindOnce(
                   &PredictionBasedPermissionUiSelector::
                       OnDeviceTfliteAivXModelExecutionCallback,
                   weak_ptr_factory_.GetWeakPtr(),
@@ -797,15 +836,13 @@
                   std::move(model_data.features),
                   std::move(model_data.request_metadata),
                   model_data.model_type),
-              PermissionsAiv4Handler::ModelInput(
+              /*model_input=*/PermissionsAiv4Handler::ModelInput(
                   std::move(model_data.snapshot.value()),
-                  // TODO(chrbug.com/382447738): dummy embedding
-                  passage_embeddings::Embedding(
-                      /*data=*/std::vector<float>(768, 42.f),
-                      /*passage_word_count=*/42)));
+                  std::move(model_data.inner_text_embedding.value())));
         }
         break;
       }
+#endif
       default:
         NOTREACHED();
     }
@@ -816,4 +853,77 @@
   InquireServerModel(model_data.features,
                      std::move(model_data.request_metadata));
 }
-#endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+void PredictionBasedPermissionUiSelector::
+    CreatePassageEmbeddingFromRenderedText(
+        std::string rendered_text,
+        ComputePassagesEmbeddingsCallback callback) {
+  VLOG(1) << "[PermissionsAI] CreatePassageEmbeddingFromRenderedText";
+  if (rendered_text.size() == 0) {
+    VLOG(1) << "[PermissionsAIv4]: rendered_text size is 0";
+    // TODO(chrbug.com/382447738) Add histogram to track this
+    return std::move(callback).Run(
+        {}, {}, -1,
+        passage_embeddings::ComputeEmbeddingsStatus::kExecutionFailure);
+  }
+
+  if (auto* prediction_model_handler_provider =
+          PredictionModelHandlerProviderFactory::GetForBrowserContext(
+              profile_)) {
+    if (auto* passage_embedder =
+            prediction_model_handler_provider->GetPassageEmbedder()) {
+      if (passage_embeddings_task_id_ != std::nullopt) {
+        VLOG(1) << "[PermissionsAIv4]: The embedding task did not return yet";
+        // TODO(chrbug.com/382447738) Add histogram to track this
+        // Try to cancel the embedding task for the previous query, if any.
+        passage_embedder->TryCancel(*passage_embeddings_task_id_);
+      }
+      passage_embeddings_task_id_ = passage_embedder->ComputePassagesEmbeddings(
+          passage_embeddings::PassagePriority::kUserInitiated,
+          {std::move(rendered_text)}, std::move(callback));
+      return;
+    }
+  }
+  std::move(callback).Run(
+      {}, {}, -1,
+      passage_embeddings::ComputeEmbeddingsStatus::kExecutionFailure);
+}
+
+// TODO(chrbug.com/382447738): Add timing info
+void PredictionBasedPermissionUiSelector::OnPassageEmbeddingsComputed(
+    ModelExecutionData model_data,
+    ModelExecutionCallback model_execution_callback,
+    std::vector<std::string> passages,
+    std::vector<passage_embeddings::Embedding> embeddings,
+    passage_embeddings::Embedder::TaskId task_id,
+    passage_embeddings::ComputeEmbeddingsStatus status) {
+  bool succeeded =
+      status == passage_embeddings::ComputeEmbeddingsStatus::kSuccess;
+  // TODO(chrbug.com/382447738) Add histogram to track the embeddings compute
+  // status
+  VLOG(1) << "[PermissionsAIv4]: TextEmbedding computed with "
+          << (succeeded ? "" : "no") << "success";
+
+  if (!succeeded) {
+    if (passage_embeddings_task_id_ == task_id) {
+      passage_embeddings_task_id_ = std::nullopt;
+    }
+    return InquireServerModel(model_data.features,
+                              std::move(model_data.request_metadata));
+  }
+  DCHECK(passages.size() == 1);
+
+  if (passage_embeddings_task_id_ != task_id) {
+    // TODO(chrbug.com/382447738) Add histogram to track this
+    // If the task id is different, a new permission request has started
+    // in the meantime and the request that started this call is stale.
+    return;
+  } else {
+    passage_embeddings_task_id_ = std::nullopt;
+  }
+
+  model_data.inner_text_embedding = std::move(embeddings[0]);
+  std::move(model_execution_callback).Run(std::move(model_data));
+}
+#endif
diff --git a/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.h b/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.h
index 79bc07f..3bb4b3f6 100644
--- a/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.h
+++ b/chrome/browser/permissions/prediction_service/prediction_based_permission_ui_selector.h
@@ -18,6 +18,7 @@
 #include "components/optimization_guide/proto/common_types.pb.h"
 #include "components/optimization_guide/proto/features/permissions_ai.pb.h"
 #include "components/optimization_guide/proto/models.pb.h"
+#include "components/passage_embeddings/passage_embeddings_types.h"
 #include "components/permissions/permission_actions_history.h"
 #include "components/permissions/permission_request_enums.h"
 #include "components/permissions/prediction_service/permission_ui_selector.h"
@@ -55,8 +56,18 @@
     permissions::PredictionRequestFeatures features;
     PredictionRequestMetadata request_metadata;
     permissions::PredictionModelType model_type;
+    std::optional<std::string> inner_text;
     std::optional<SkBitmap>(snapshot);
-    std::string inner_text;
+    std::optional<passage_embeddings::Embedding> inner_text_embedding;
+
+    ModelExecutionData(permissions::PredictionRequestFeatures features,
+                       PredictionRequestMetadata request_metadata,
+                       permissions::PredictionModelType model_type);
+    ModelExecutionData();
+    ~ModelExecutionData();
+    ModelExecutionData(const ModelExecutionData&) = delete;
+    ModelExecutionData(ModelExecutionData&&);
+    ModelExecutionData& operator=(const ModelExecutionData&) = delete;
   };
 
   using PredictionGrantLikelihood =
@@ -210,8 +221,11 @@
       const permissions::PredictionRequestFeatures& features,
       PredictionRequestMetadata request_metadata);
 
-  // Creates a snapshot asynchronously and calls ExecuteOnDeviceAivXModel. Part
-  // of the AivX model workflow.
+  // Part of the AivX model workflow. Creates a snapshot asynchronously and
+  // calls ExecuteOnDeviceAivXModel if the snapshot is not empty. If snapshot
+  // creation failed, on-device model execution is not attempted and instead it
+  // proceeds with the basic CPSSv3 workflow without the output of the
+  // on-device model.
   void TakeSnapshot(content::RenderWidgetHostView* host_view,
                     ModelExecutionData model_data);
 
@@ -222,6 +236,28 @@
                     ModelExecutionData model_data,
                     ModelExecutionCallback model_execution_callback);
 
+  // Part of Aiv4 workflow; to use the inner text as input to the tflite model,
+  // we need to preprocess it with the passage embeddings model. If
+  // rendered_text is an empty string, on-device model execution is not
+  // attempted and instead it proceeds with the basic CPSSv3 workflow without
+  // the output of the on-device model.
+  void CreatePassageEmbeddingFromRenderedText(
+      std::string rendered_text,
+      passage_embeddings::Embedder::ComputePassagesEmbeddingsCallback callback);
+
+  // Callback for the passage embeddings model. Sets the
+  // |passage_embeddings_task_id_| if the passage_embedder model is available.
+  // Still running embedder tasks will get canceled upon calling this function.
+  // Fills in the inner_text_embeddings field of the model_metadata on success
+  // and calls the model_execution_callback in any case. Failures will get
+  // propagated and should be handled by the model_execution_callback callback.
+  void OnPassageEmbeddingsComputed(
+      ModelExecutionData model_data,
+      ModelExecutionCallback model_execution_callback,
+      std::vector<std::string> passages,
+      std::vector<passage_embeddings::Embedding> embeddings,
+      passage_embeddings::Embedder::TaskId task_id,
+      passage_embeddings::ComputeEmbeddingsStatus status);
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
   raw_ptr<Profile> profile_;
@@ -236,10 +272,16 @@
 
   DecisionMadeCallback callback_;
 
+  std::optional<content_extraction::InnerTextResult> inner_text_for_testing_;
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
   std::optional<SkBitmap> snapshot_for_testing_;
+
+  // Used to cancel a still running embedding task for the previous stale query
+  // to the passage embedder model that we use to prepare the text input for
+  // AIv4.
+  std::optional<passage_embeddings::Embedder::TaskId>
+      passage_embeddings_task_id_;
 #endif
-  std::optional<content_extraction::InnerTextResult> inner_text_for_testing_;
 
   // Used to asynchronously call the callback during on device model execution.
   base::WeakPtrFactory<PredictionBasedPermissionUiSelector> weak_ptr_factory_{
diff --git a/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.cc b/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.cc
index 7ca6c34..da5647b 100644
--- a/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.cc
+++ b/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.cc
@@ -10,6 +10,7 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/passage_embeddings/chrome_passage_embeddings_service_controller.h"
 #include "chrome/browser/permissions/prediction_service/permissions_aiv1_handler.h"
 #include "components/optimization_guide/core/delivery/optimization_guide_model_provider.h"
 #include "components/permissions/features.h"
@@ -160,12 +161,29 @@
   }
 }
 
+void PredictionModelHandlerProvider::set_passage_embedder_for_testing(
+    passage_embeddings::Embedder* passage_embedder) {
+  passage_embedder_for_testing = passage_embedder;
+}
+
 bool PredictionModelHandlerProvider::IsAiv4ModelAvailable() {
   return base::FeatureList::IsEnabled(permissions::features::kPermissionsAIv4);
-  // TODO(crbug.com/422952428) Add check for language as the text embeddings
+  // TODO(crbug.com/382447738) Add check for language as the text embeddings
   // model required for preparing the text input of AIv4 only works on english
   // text for now.
 }
+passage_embeddings::Embedder*
+PredictionModelHandlerProvider::GetPassageEmbedder() {
+  if (passage_embedder_for_testing.has_value()) {
+    CHECK_IS_TEST();
+    return passage_embedder_for_testing.value();
+  }
+  if (auto* passage_embeddings_service_controller =
+          passage_embeddings::ChromePassageEmbeddingsServiceController::Get()) {
+    return passage_embeddings_service_controller->GetEmbedder();
+  }
+  return nullptr;
+}
 
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 }  // namespace permissions
diff --git a/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.h b/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.h
index fa91fbf..03e4a67 100644
--- a/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.h
+++ b/chrome/browser/permissions/prediction_service/prediction_model_handler_provider.h
@@ -10,6 +10,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/optimization_guide/core/delivery/optimization_guide_model_provider.h"
 #include "components/optimization_guide/machine_learning_tflite_buildflags.h"
+#include "components/passage_embeddings/passage_embeddings_types.h"
 #include "components/permissions/request_type.h"
 
 class OptimizationGuideKeyedService;
@@ -39,6 +40,7 @@
   PredictionModelHandler* GetPredictionModelHandler(RequestType request_type);
   PermissionsAiv3Handler* GetPermissionsAiv3Handler(RequestType request_type);
   PermissionsAiv4Handler* GetPermissionsAiv4Handler(RequestType request_type);
+  passage_embeddings::Embedder* GetPassageEmbedder();
 
   void set_permissions_aiv3_handler_for_testing(
       RequestType request_type,
@@ -46,7 +48,8 @@
   void set_permissions_aiv4_handler_for_testing(
       RequestType request_type,
       std::unique_ptr<PermissionsAiv4Handler> handler);
-
+  void set_passage_embedder_for_testing(
+      passage_embeddings::Embedder* passage_embedder_);
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
  private:
@@ -59,6 +62,10 @@
   std::unique_ptr<PermissionsAiv3Handler> geolocation_aiv3_handler_;
   std::unique_ptr<PermissionsAiv4Handler> notification_aiv4_handler_;
   std::unique_ptr<PermissionsAiv4Handler> geolocation_aiv4_handler_;
+  // This embedder is required to preprocess the inner_text to create the
+  // embeddings we use for the AIv4 tflite model as input.
+  std::optional<raw_ptr<passage_embeddings::Embedder>>
+      passage_embedder_for_testing;
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 };
 }  // namespace permissions
diff --git a/chrome/browser/permissions/prediction_service/prediction_service_browsertest.cc b/chrome/browser/permissions/prediction_service/prediction_service_browsertest.cc
index fc2ebc8..212f2c6 100644
--- a/chrome/browser/permissions/prediction_service/prediction_service_browsertest.cc
+++ b/chrome/browser/permissions/prediction_service/prediction_service_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/permissions/prediction_service/prediction_model_handler_provider.h"
 #include "chrome/browser/permissions/prediction_service/prediction_model_handler_provider_factory.h"
 #include "chrome/browser/permissions/prediction_service/prediction_service_factory.h"
+#include "chrome/browser/permissions/test/mock_passage_embedder.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/ui/browser.h"
@@ -36,6 +37,7 @@
 #include "components/optimization_guide/core/delivery/test_optimization_guide_model_provider.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/proto/models.pb.h"
+#include "components/passage_embeddings/passage_embeddings_test_util.h"
 #include "components/permissions/features.h"
 #include "components/permissions/permission_request_manager.h"
 #include "components/permissions/permission_uma_util.h"
@@ -45,6 +47,7 @@
 #include "components/permissions/prediction_service/prediction_request_features.h"
 #include "components/permissions/prediction_service/prediction_service_messages.pb.h"
 #include "components/permissions/request_type.h"
+#include "components/permissions/test/aivx_modelhandler_utils.h"
 #include "components/permissions/test/enums_to_string.h"
 #include "components/permissions/test/fake_permissions_aivx_modelhandlers.h"
 #include "components/permissions/test/mock_permission_prompt_factory.h"
@@ -65,11 +68,14 @@
 using ::base::test::FeatureRef;
 using ::base::test::FeatureRefAndParams;
 using ::optimization_guide::proto::OptimizationTarget;
+using ::passage_embeddings::ComputeEmbeddingsStatus;
 using ::permissions::GeneratePredictionsResponse;
 using ::permissions::PermissionRequestRelevance;
 using ::permissions::PermissionsAiv3Handler;
 using ::permissions::PredictionRequestFeatures;
 using ::permissions::PredictionService;
+using ::test::BuildBitmap;
+using ::test::PassageEmbedderMock;
 using ::test::PermissionsAiv3HandlerFake;
 using ::test::PermissionsAiv4HandlerFake;
 using ::testing::_;
@@ -105,6 +111,10 @@
 
 constexpr std::string kNoHoldbackChance = "0";
 
+// Just a meaningless color used to create snapshot dummies for the AIv3 and
+// Aiv4 models.
+constexpr SkColor kDefaultColor = SkColorSetRGB(0x1E, 0x1C, 0x0F);
+
 // This is the only server side reply that will trigger quiet UI at the
 // moment.
 constexpr auto kLikelihoodVeryUnlikely =
@@ -259,6 +269,17 @@
       .experiment_id = experiment_id,
       .permission_relevance = permission_relevance};
 }
+
+GeneratePredictionsResponse BuildPredictionServiceResponse(
+    PermissionUiSelector::PredictionGrantLikelihood likelihood) {
+  GeneratePredictionsResponse prediction_service_response;
+  prediction_service_response.mutable_prediction()
+      ->Add()
+      ->mutable_grant_likelihood()
+      ->set_discretized_likelihood(likelihood);
+  return prediction_service_response;
+}
+
 }  // namespace
 
 class PredictionServiceBrowserTestBase : public InProcessBrowserTest {
@@ -362,12 +383,8 @@
     manager->AddRequest(GetActiveMainFrame(), std::move(req));
     bubble_factory()->WaitForPermissionBubble();
 
-    if (aiv3_model_handler_) {
-      aiv3_model_handler_->WaitForModelExecutionForTesting();
-    }
-    if (aiv4_model_handler_) {
-      aiv4_model_handler_->WaitForModelExecutionForTesting();
-    }
+    WaitForModelExecutionIfNecessary();
+
     EXPECT_EQ(should_expect_quiet_ui,
               manager->ShouldCurrentRequestUseQuietUI());
     EXPECT_EQ(expected_relevance,
@@ -391,6 +408,15 @@
   raw_ptr<PermissionsAiv4HandlerFake> aiv4_model_handler_ = nullptr;
 
  private:
+  virtual void WaitForModelExecutionIfNecessary() {
+    if (aiv3_model_handler_) {
+      aiv3_model_handler_->WaitForModelExecutionForTesting();
+    }
+    if (aiv4_model_handler_) {
+      aiv4_model_handler_->WaitForModelExecutionForTesting();
+    }
+  }
+
   std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_;
   base::test::ScopedFeatureList scoped_feature_list_;
   base::HistogramTester histogram_tester_;
@@ -492,11 +518,9 @@
 IN_PROC_BROWSER_TEST_P(PredictionServiceHoldbackBrowserTest,
                        TestServerSideHoldbackWorkflow) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  GeneratePredictionsResponse prediction_service_response;
-  prediction_service_response.mutable_prediction()
-      ->Add()
-      ->mutable_grant_likelihood()
-      ->set_discretized_likelihood(GetParam().prediction_service_likelihood);
+
+  GeneratePredictionsResponse prediction_service_response =
+      BuildPredictionServiceResponse(GetParam().prediction_service_likelihood);
 
   std::string test_url = "test.a";
   PredictionRequestFeatures expected_features = BuildRequestFeatures(
@@ -731,18 +755,17 @@
 
   // We do not test screenshot handling here; this is so the code does not fail.
   void set_dummy_screenshot_for_testing() {
-    SkBitmap bitmap;
-    bitmap.allocN32Pixels(64, 64);
-    bitmap.eraseColor(SkColorSetRGB(0x1E, 0x1C, 0x0F));
-    prediction_based_permission_ui_selector()->set_snapshot_for_testing(bitmap);
+    prediction_based_permission_ui_selector()->set_snapshot_for_testing(
+        BuildBitmap(64, 64, kDefaultColor));
   }
 
   // We do not test inner text content extraction here; this is so the code does
   // not fail.
-  void set_dummy_inner_text_for_testing() {
+  void set_dummy_inner_text_for_testing(
+      std::string inner_text =
+          "dummy text that is more than min length characters long") {
     prediction_based_permission_ui_selector()->set_inner_text_for_testing(
-        {.inner_text =
-             "dummy text that is more than min length characters long"});
+        {.inner_text = std::move(inner_text)});
   }
 };
 
@@ -893,11 +916,8 @@
 
   set_dummy_screenshot_for_testing();
 
-  GeneratePredictionsResponse prediction_service_response;
-  prediction_service_response.mutable_prediction()
-      ->Add()
-      ->mutable_grant_likelihood()
-      ->set_discretized_likelihood(test_case.prediction_service_likelihood);
+  GeneratePredictionsResponse prediction_service_response =
+      BuildPredictionServiceResponse(test_case.prediction_service_likelihood);
 
   PredictionRequestFeatures expected_features =
       BuildRequestFeatures(request_type(), ExperimentId::kAiV3ExperimentId,
@@ -951,6 +971,163 @@
 // --------------- Prediction Service On Device Permissions AIv4 ---------------
 // -----------------------------------------------------------------------------
 
+class Aiv4ModelPredictionServiceBrowserTestBase
+    : public AivXModelPredictionServiceBrowserTest<PermissionsAiv4HandlerFake> {
+ public:
+  Aiv4ModelPredictionServiceBrowserTestBase()
+      : AivXModelPredictionServiceBrowserTest(/*enabled_features=*/
+                                              {
+                                                  CONFIGURE_NO_HOLDBACK_CHANCE,
+                                                  {permissions::features::
+                                                       kPermissionsAIv1,
+                                                   {}},
+                                                  {permissions::features::
+                                                       kPermissionsAIv3,
+                                                   {}},
+                                                  {permissions::features::
+                                                       kPermissionsAIv4,
+                                                   {}},
+                                              }, /*disabled_features=*/
+                                              {}) {}
+
+  RequestType request_type() const override {
+    return RequestType::kNotifications;
+  }
+
+  OptimizationTarget optimization_target() override {
+    return kAiv4OptTargetNotification;
+  }
+
+  void UpdateAivXHandlerInModelProvider(
+      std::unique_ptr<PermissionsAiv4HandlerFake> handler) override {
+    model_handler_provider()->set_permissions_aiv4_handler_for_testing(
+        request_type(), std::move(handler));
+  }
+
+  PermissionsAiv4HandlerFake* model_handler() override {
+    return aiv4_model_handler_;
+  }
+
+  void set_model_handler(PermissionsAiv4HandlerFake* handler) override {
+    aiv4_model_handler_ = handler;
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(Aiv4ModelPredictionServiceBrowserTestBase,
+                       Aiv4ModelHandlerDefined) {
+  // If AIv4 flag is defined, no other AIvX model should get initialized.
+  EXPECT_FALSE(aiv1_model_handler());
+  EXPECT_FALSE(aiv3_model_handler());
+  EXPECT_TRUE(aiv4_model_handler());
+}
+
+struct Aiv4ModelFailureTestCase {
+  std::string test_name;
+  std::string inner_text;
+  SkBitmap snapshot;
+  ComputeEmbeddingsStatus compute_embeddings_status;
+  std::optional<PassageEmbedderMock> passage_embedder;
+};
+
+class Aiv4ModelFailureBrowserTest
+    : public Aiv4ModelPredictionServiceBrowserTestBase,
+      public testing::WithParamInterface<Aiv4ModelFailureTestCase> {
+ public:
+  Aiv4ModelFailureBrowserTest() = default;
+
+  void WaitForModelExecutionIfNecessary() override {
+    // This test will not start any model execution.
+  }
+};
+
+// Each of the testcases targets a different point of failure and we want all
+// of them to get handled gracefully by skipping on-device model execution and
+// just calling CPSSv3 server side model without permission relevance calculated
+// by the on-device model.
+INSTANTIATE_TEST_SUITE_P(
+    Aiv4ModelFailureTest,
+    Aiv4ModelFailureBrowserTest,
+    ValuesIn<Aiv4ModelFailureTestCase>({
+        {
+            /*test_name=*/"NoScreenshotAvailable",
+            /*inner_text=*/"some valid text for aiv4 model",
+            /*snapshot=*/SkBitmap(),
+            /*compute_embeddings_status=*/ComputeEmbeddingsStatus::kSuccess,
+            /*passage_embedder=*/PassageEmbedderMock(),
+        },
+        {
+            /*test_name=*/"EmptyInnerText",
+            /*inner_text=*/"",
+            /*snapshot=*/BuildBitmap(64, 64, kDefaultColor),
+            /*compute_embeddings_status=*/ComputeEmbeddingsStatus::kSuccess,
+            /*passage_embedder=*/PassageEmbedderMock(),
+        },
+        {
+            /*test_name=*/"EmbedderModelFails",
+            /*inner_text=*/"some valid text for aiv4 model",
+            /*snapshot=*/BuildBitmap(64, 64, kDefaultColor),
+            /*compute_embeddings_status=*/
+            ComputeEmbeddingsStatus::kExecutionFailure,
+            /*passage_embedder=*/PassageEmbedderMock(),
+        },
+        {
+            /*test_name=*/"EmbedderModelDoesNotExist",
+            /*inner_text=*/"some valid text for aiv4 model",
+            /*snapshot=*/BuildBitmap(64, 64, kDefaultColor),
+            /*compute_embeddings_status=*/
+            ComputeEmbeddingsStatus::kSuccess,
+            /*passage_embedder=*/std::nullopt,
+        },
+    }), /*name_generator=*/
+    [](const testing::TestParamInfo<Aiv4ModelFailureBrowserTest::ParamType>&
+           info) { return info.param.test_name; });
+
+IN_PROC_BROWSER_TEST_P(Aiv4ModelFailureBrowserTest,
+                       ShouldCallCPSSv3ModelWithoutRelevance) {
+  ASSERT_TRUE(aiv4_model_handler());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  PushModelFileToModelExecutor(ModelFilePath(kOneReturnAiv4Model));
+
+  // We setup various failure conditions defined by the testcases.
+  prediction_based_permission_ui_selector()->set_snapshot_for_testing(
+      GetParam().snapshot);
+  set_dummy_inner_text_for_testing(GetParam().inner_text);
+  std::unique_ptr<PassageEmbedderMock> passage_embedder;
+  if (GetParam().passage_embedder.has_value()) {
+    passage_embedder = std::make_unique<PassageEmbedderMock>(
+        GetParam().passage_embedder.value());
+    passage_embedder->set_status(GetParam().compute_embeddings_status);
+    model_handler_provider()->set_passage_embedder_for_testing(
+        passage_embedder.get());
+  } else {
+    model_handler_provider()->set_passage_embedder_for_testing(nullptr);
+  }
+
+  // We expect a vanilla CPSSv3 call without input from the
+  // on-device model.
+  GeneratePredictionsResponse prediction_service_response =
+      BuildPredictionServiceResponse(kLikelihoodVeryUnlikely);
+  PredictionRequestFeatures expected_features =
+      BuildRequestFeatures(request_type(), ExperimentId::kAiV4ExperimentId,
+                           PermissionRequestRelevance::kUnspecified);
+  EXPECT_CALL(prediction_service(),
+              StartLookup(PredictionRequestFeatureEq(expected_features), _, _))
+      .WillRepeatedly(WithArg<2>(Invoke(
+          [&](PredictionService::LookupResponseCallback response_callback) {
+            std::move(response_callback)
+                .Run(/*lookup_successful=*/true,
+                     /*response_from_cache=*/true, prediction_service_response);
+          })));
+
+  TriggerPromptAndVerifyUi(
+      /*test_url=*/"test.a", PermissionAction::DISMISSED,
+      /*should_expect_quiet_ui=*/true, /*expected_relevance=*/std::nullopt,
+      /*expected_prediction_likelihood=*/kLikelihoodVeryUnlikely);
+
+  // Avoid dangling raw_ptr warning:
+  model_handler_provider()->set_passage_embedder_for_testing(nullptr);
+}
+
 std::vector<PermissionRequestMetadata> aiv4_request_data_testcase = {
     {/*optimization_target=*/kAiv4OptTargetGeolocation,
      /*request_type=*/RequestType::kGeolocation},
@@ -1009,24 +1186,10 @@
 using Aiv4ModelTestCase = std::tuple<ModelMetadata, PermissionRequestMetadata>;
 
 class Aiv4ModelPredictionServiceBrowserTest
-    : public AivXModelPredictionServiceBrowserTest<PermissionsAiv4HandlerFake>,
+    : public Aiv4ModelPredictionServiceBrowserTestBase,
       public testing::WithParamInterface<Aiv4ModelTestCase> {
  public:
-  Aiv4ModelPredictionServiceBrowserTest()
-      : AivXModelPredictionServiceBrowserTest(/*enabled_features=*/
-                                              {
-                                                  CONFIGURE_NO_HOLDBACK_CHANCE,
-                                                  {permissions::features::
-                                                       kPermissionsAIv1,
-                                                   {}},
-                                                  {permissions::features::
-                                                       kPermissionsAIv3,
-                                                   {}},
-                                                  {permissions::features::
-                                                       kPermissionsAIv4,
-                                                   {}},
-                                              }, /*disabled_features=*/
-                                              {}) {}
+  Aiv4ModelPredictionServiceBrowserTest() = default;
 
   RequestType request_type() const override {
     return get<1>(GetParam()).request_type;
@@ -1036,19 +1199,16 @@
     return get<1>(GetParam()).optimization_target;
   }
 
-  void UpdateAivXHandlerInModelProvider(
-      std::unique_ptr<PermissionsAiv4HandlerFake> handler) override {
-    model_handler_provider()->set_permissions_aiv4_handler_for_testing(
-        request_type(), std::move(handler));
+  void SetUpOnMainThread() override {
+    Aiv4ModelPredictionServiceBrowserTestBase::SetUpOnMainThread();
+
+    // Required to preprocess the inner_text string as input for AIv4
+    model_handler_provider()->set_passage_embedder_for_testing(
+        &passage_embedder_);
   }
 
-  PermissionsAiv4HandlerFake* model_handler() override {
-    return aiv4_model_handler_;
-  }
-
-  void set_model_handler(PermissionsAiv4HandlerFake* handler) override {
-    aiv4_model_handler_ = handler;
-  }
+ private:
+  PassageEmbedderMock passage_embedder_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1064,14 +1224,6 @@
     });
 
 IN_PROC_BROWSER_TEST_P(Aiv4ModelPredictionServiceBrowserTest,
-                       Aiv4ModelHandlerDefined) {
-  // If AIv4 flag is defined, no other AIvX model should get initialized.
-  EXPECT_FALSE(aiv1_model_handler());
-  EXPECT_FALSE(aiv3_model_handler());
-  EXPECT_TRUE(aiv4_model_handler());
-}
-
-IN_PROC_BROWSER_TEST_P(Aiv4ModelPredictionServiceBrowserTest,
                        TestAiv4Workflow) {
   ASSERT_TRUE(aiv4_model_handler());
 
@@ -1083,11 +1235,8 @@
   set_dummy_screenshot_for_testing();
   set_dummy_inner_text_for_testing();
 
-  GeneratePredictionsResponse prediction_service_response;
-  prediction_service_response.mutable_prediction()
-      ->Add()
-      ->mutable_grant_likelihood()
-      ->set_discretized_likelihood(test_case.prediction_service_likelihood);
+  GeneratePredictionsResponse prediction_service_response =
+      BuildPredictionServiceResponse(test_case.prediction_service_likelihood);
 
   PredictionRequestFeatures expected_features =
       BuildRequestFeatures(request_type(), ExperimentId::kAiV4ExperimentId,
diff --git a/chrome/browser/permissions/test/mock_passage_embedder.cc b/chrome/browser/permissions/test/mock_passage_embedder.cc
new file mode 100644
index 0000000..6b7ed21
--- /dev/null
+++ b/chrome/browser/permissions/test/mock_passage_embedder.cc
@@ -0,0 +1,34 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/permissions/test/mock_passage_embedder.h"
+
+#include <string>
+#include <vector>
+
+namespace test {
+
+using passage_embeddings::ComputeEmbeddingsStatus;
+using passage_embeddings::PassagePriority;
+using passage_embeddings::TestEmbedder;
+using TaskId = passage_embeddings::Embedder::TaskId;
+
+TaskId PassageEmbedderMock::ComputePassagesEmbeddings(
+    PassagePriority priority,
+    std::vector<std::string> passages,
+    ComputePassagesEmbeddingsCallback callback) {
+  if (status_ == ComputeEmbeddingsStatus::kSuccess) {
+    TestEmbedder::ComputePassagesEmbeddings(priority, passages,
+                                            std::move(callback));
+    return 0;
+  }
+
+  std::move(callback).Run(passages, {}, 0, status_);
+  return 0;
+}
+
+void PassageEmbedderMock::set_status(ComputeEmbeddingsStatus status) {
+  status_ = status;
+}
+}  // namespace test
diff --git a/chrome/browser/permissions/test/mock_passage_embedder.h b/chrome/browser/permissions/test/mock_passage_embedder.h
new file mode 100644
index 0000000..515ac6f
--- /dev/null
+++ b/chrome/browser/permissions/test/mock_passage_embedder.h
@@ -0,0 +1,34 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERMISSIONS_TEST_MOCK_PASSAGE_EMBEDDER_H_
+#define CHROME_BROWSER_PERMISSIONS_TEST_MOCK_PASSAGE_EMBEDDER_H_
+
+#include <string>
+#include <vector>
+
+#include "components/passage_embeddings/passage_embeddings_test_util.h"
+
+namespace test {
+
+class PassageEmbedderMock : public passage_embeddings::TestEmbedder {
+ public:
+  PassageEmbedderMock() = default;
+  ~PassageEmbedderMock() override = default;
+
+  // passage_embeddings::TestEmbedder:
+  passage_embeddings::Embedder::TaskId ComputePassagesEmbeddings(
+      passage_embeddings::PassagePriority priority,
+      std::vector<std::string> passages,
+      ComputePassagesEmbeddingsCallback callback) override;
+
+  void set_status(passage_embeddings::ComputeEmbeddingsStatus status);
+
+ private:
+  passage_embeddings::ComputeEmbeddingsStatus status_ =
+      passage_embeddings::ComputeEmbeddingsStatus::kSuccess;
+};
+}  // namespace test
+
+#endif  // CHROME_BROWSER_PERMISSIONS_TEST_MOCK_PASSAGE_EMBEDDER_H_
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java
index f50e8ed0f..277708b 100644
--- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java
+++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java
@@ -12,13 +12,13 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.DoNotBatch;
@@ -46,6 +46,8 @@
     private static final String ASSERT_PRELOAD_PAGES_STATE_NATIVE =
             "Incorrect Preload Pages state from native.";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<PreloadPagesSettingsFragment> mTestRule =
             new SettingsActivityTestRule<>(PreloadPagesSettingsFragment.class);
@@ -58,11 +60,6 @@
     private RadioButtonGroupPreloadPagesSettings mPreloadPagesPreference;
     private Preference mManagedDisclaimerText;
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
     private void startSettings() {
         mTestRule.startSettingsActivity();
         mPreloadPagesSettingsFragment = mTestRule.getFragment();
diff --git a/chrome/browser/prefs/BUILD.gn b/chrome/browser/prefs/BUILD.gn
index 6e6e9c8..d8daccce 100644
--- a/chrome/browser/prefs/BUILD.gn
+++ b/chrome/browser/prefs/BUILD.gn
@@ -83,6 +83,7 @@
     "//chrome/browser/ui/safety_hub",
     "//chrome/browser/ui/search_engines",
     "//chrome/browser/ui/side_search",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/startup:startup_tab",
     "//chrome/browser/ui/toolbar",
     "//chrome/browser/ui/toolbar/chrome_labs",
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
index d403a953..8af5bef 100644
--- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
+++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
@@ -40,7 +40,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -72,6 +73,8 @@
 @DoNotBatch(reason = "Need to evaluate these tests for batching; some test startup behavior.")
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public final class PrivacySandboxDialogTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public final AutoResetCtaTransitTestRule mActivityTestRule =
             ChromeTransitTestRules.fastAutoResetCtaActivityRule();
@@ -101,7 +104,6 @@
         mTestPage =
                 mActivityTestRule.getTestServer().getURL("/chrome/test/data/android/google.html");
 
-        MockitoAnnotations.initMocks(this);
         mFakePrivacySandboxBridge = new FakePrivacySandboxBridge();
         PrivacySandboxBridgeJni.setInstanceForTesting(mFakePrivacySandboxBridge);
         PrivacySandboxDialogController.disableAnimations(true);
diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn
index 81d7fd8..29e4041c 100644
--- a/chrome/browser/profiles/BUILD.gn
+++ b/chrome/browser/profiles/BUILD.gn
@@ -275,6 +275,7 @@
     "//chrome/browser/ui/hats",
     "//chrome/browser/ui/prefs",
     "//chrome/browser/ui/safety_hub",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/toolbar",
     "//chrome/browser/ui/toolbar/pinned_toolbar",
     "//chrome/browser/updates/announcement_notification",
diff --git a/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/ProfileKeyedMapTest.java b/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/ProfileKeyedMapTest.java
index 6b2bf9b..26c3e72 100644
--- a/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/ProfileKeyedMapTest.java
+++ b/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/ProfileKeyedMapTest.java
@@ -10,11 +10,13 @@
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.lifetime.Destroyable;
@@ -27,6 +29,8 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class ProfileKeyedMapTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Mock private Profile mProfile1;
     @Mock private Profile mIncognitoProfile1;
     @Mock private Profile mProfile2;
@@ -34,8 +38,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         Mockito.when(mProfile1.getOriginalProfile()).thenReturn(mProfile1);
         Mockito.when(mIncognitoProfile1.getOriginalProfile()).thenReturn(mProfile1);
     }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
index 3ab1bb6..1ac7d57 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java
@@ -23,10 +23,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.robolectric.annotation.Config;
 
@@ -45,6 +47,7 @@
 @Config(manifest = Config.NONE)
 public class RestoreTabsCoordinatorUnitTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock FaviconHelper.Natives mFaviconHelperJniMock;
     @Mock private RestoreTabsMediator mMediator;
     @Mock private Profile mProfile;
@@ -60,7 +63,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         FaviconHelperJni.setInstanceForTesting(mFaviconHelperJniMock);
         when(mFaviconHelperJniMock.init()).thenReturn(1L);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
index 01afbd2..4614dcd 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java
@@ -31,10 +31,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -68,6 +70,7 @@
 public class RestoreTabsMediatorUnitTest {
     private static final String RESTORE_TABS_USED = EventConstants.RESTORE_TABS_PROMO_USED;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private RestoreTabsControllerDelegate mDelegate;
     @Mock private ForeignSessionHelper mForeignSessionHelper;
     @Mock private TabCreatorManager mTabCreatorManager;
@@ -81,7 +84,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         TrackerFactory.setTrackerForTests(mTracker);
         mMediator.initialize(mModel, mProfile, mTabCreatorManager, mBottomSheetController);
     }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsPromoSheetContentUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsPromoSheetContentUnitTest.java
index a6881e44..540e4bf 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsPromoSheetContentUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsPromoSheetContentUnitTest.java
@@ -22,10 +22,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -37,6 +39,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class RestoreTabsPromoSheetContentUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private View mContentView;
     @Mock private BottomSheetController mBottomSheetController;
     @Mock private RecyclerView mRecyclerView;
@@ -48,7 +51,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mSheetContent =
                 new RestoreTabsPromoSheetContent(mContentView, mModel, mBottomSheetController);
     }
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java
index eebd020..45d8530 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java
@@ -36,8 +36,9 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
@@ -72,6 +73,8 @@
 public class RestoreTabsTest {
     private static final String RESTORE_TABS_FEATURE = FeatureConstants.RESTORE_TABS_ON_FRE_FEATURE;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public FreshCtaTransitTestRule mActivityTestRule =
             ChromeTransitTestRules.freshChromeTabbedActivityRule();
@@ -87,7 +90,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mPage = mActivityTestRule.startOnBlankPage();
         TrackerFactory.setTrackerForTests(mMockTracker);
 
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsUiRenderTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsUiRenderTest.java
index f3849a556..4d53669 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsUiRenderTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsUiRenderTest.java
@@ -29,7 +29,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseActivityTestRule;
@@ -75,6 +76,8 @@
     public static List<ParameterSet> sClassParams =
             new NightModeTestUtils.NightModeParams().getParameters();
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public final ChromeRenderTestRule mRenderTestRule =
             ChromeRenderTestRule.Builder.withPublicCorpus()
@@ -104,7 +107,6 @@
 
     @Before
     public void setUp() throws InterruptedException {
-        MockitoAnnotations.initMocks(this);
         ProfileManager.setLastUsedProfileForTesting(mProfile);
         ForeignSessionHelperJni.setInstanceForTesting(mForeignSessionHelperJniMock);
         FaviconHelperJni.setInstanceForTesting(mFaviconHelperJniMock);
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenViewBinderUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenViewBinderUnitTest.java
index 7c0c579..470daf1 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenViewBinderUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsDetailScreenViewBinderUnitTest.java
@@ -28,10 +28,12 @@
 
 import org.junit.Assert;
 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.robolectric.annotation.Config;
 
@@ -53,6 +55,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class RestoreTabsDetailScreenViewBinderUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private RestoreTabsDetailScreenCoordinator.Delegate mMockDelegate;
     @Mock private TabItemViewBinder.BindContext mBindContext;
 
@@ -63,7 +66,6 @@
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mRestoreTabsDetailView =
                 LayoutInflater.from(mActivity)
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsPromoScreenViewBinderUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsPromoScreenViewBinderUnitTest.java
index 9ad0cf9e..1aadb6e 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsPromoScreenViewBinderUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/RestoreTabsPromoScreenViewBinderUnitTest.java
@@ -26,10 +26,12 @@
 
 import org.junit.Assert;
 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.robolectric.annotation.Config;
 
@@ -54,6 +56,7 @@
 @Config(manifest = Config.NONE)
 public class RestoreTabsPromoScreenViewBinderUnitTest {
     private static final long JAN_1_1970 = new Date(70, Calendar.JANUARY, 1).getTime();
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private RestoreTabsPromoScreenCoordinator.Delegate mMockDelegate;
 
     private Activity mActivity;
@@ -63,7 +66,6 @@
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mRestoreTabsPromoView =
                 LayoutInflater.from(mActivity)
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/TabItemViewBinderUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/TabItemViewBinderUnitTest.java
index 1b9cef4..9e2f434 100644
--- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/TabItemViewBinderUnitTest.java
+++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/ui/TabItemViewBinderUnitTest.java
@@ -21,10 +21,12 @@
 import org.junit.After;
 import org.junit.Assert;
 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.robolectric.annotation.Config;
 
@@ -47,6 +49,7 @@
 @Config(manifest = Config.NONE)
 public class TabItemViewBinderUnitTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock FaviconHelper.Natives mFaviconHelperJniMock;
     @Mock Profile mProfile;
 
@@ -59,7 +62,6 @@
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         ProfileManager.setLastUsedProfileForTesting(mProfile);
         FaviconHelperJni.setInstanceForTesting(mFaviconHelperJniMock);
         when(mFaviconHelperJniMock.init()).thenReturn(1L);
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn
index 0ae3cf12..ec9ce3b9 100644
--- a/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -93,7 +93,6 @@
   ts_deps = [
     "//chrome/browser/resources/new_tab_shared:build_ts",
     "//third_party/lit/v3_0:build_ts",
-    "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/cr_components/color_change_listener:build_ts",
     "//ui/webui/resources/cr_components/help_bubble:build_ts",
     "//ui/webui/resources/cr_components/most_visited:build_ts",
diff --git a/chrome/browser/resources/new_tab_page/composebox/composebox.ts b/chrome/browser/resources/new_tab_page/composebox/composebox.ts
index 97fbde93..2c0a1f6b 100644
--- a/chrome/browser/resources/new_tab_page/composebox/composebox.ts
+++ b/chrome/browser/resources/new_tab_page/composebox/composebox.ts
@@ -123,7 +123,7 @@
   protected accessor submitting_: boolean = false;
   protected accessor showErrorScrim_: boolean = false;
   protected accessor errorMessage_: string = '';
-  protected accessor result_: AutocompleteResult|null;
+  protected accessor result_: AutocompleteResult|null = null;
   protected accessor inputPlaceholder_: string =
       loadTimeData.getString('searchboxComposePlaceholder');
   private maxFileCount_: number =
@@ -136,12 +136,9 @@
   private searchboxCallbackRouter_: SearchboxPageCallbackRouter;
   private pageHandler_: PageHandlerRemote;
   private searchboxHandler_: SearchboxPageHandlerRemote;
-  private setFileUploadStatusListenerId_: number|null = null;
   private eventTracker_: EventTracker = new EventTracker();
-  private listenerIds: number[];
-  private searchboxListenerIds: number[];
-
-
+  private listenerIds: number[] = [];
+  private searchboxListenerIds: number[] = [];
   private composeboxCloseByEscape_: boolean =
       loadTimeData.getBoolean('composeboxCloseByEscape');
 
diff --git a/chrome/browser/resources/new_tab_page/middle_slot_promo.ts b/chrome/browser/resources/new_tab_page/middle_slot_promo.ts
index 5d7c5d2..300b3ff 100644
--- a/chrome/browser/resources/new_tab_page/middle_slot_promo.ts
+++ b/chrome/browser/resources/new_tab_page/middle_slot_promo.ts
@@ -45,10 +45,6 @@
     Promise<{container: Element, id: string | null}|null> {
   const browserHandler = NewTabPageProxy.getInstance().handler;
   const promoBrowserCommandHandler = BrowserCommandProxy.getInstance().handler;
-  if (!promo) {
-    return null;
-  }
-
   const commandIds: Command[] = [];
 
   function createAnchor(target: Url) {
@@ -61,6 +57,7 @@
     if (!commandIdMatch) {
       el.href = target.url;
     } else {
+      assert(commandIdMatch[1]);
       commandId = +commandIdMatch[1];
       // Make sure we don't send unsupported commands to the browser.
       if (!Object.values(Command).includes(commandId)) {
@@ -170,10 +167,9 @@
     };
   }
 
-  protected accessor shownMiddleSlotPromoId_: string;
-  private accessor promo_: Promo;
-
-  private blocklistedMiddleSlotPromoId_: string;
+  protected accessor shownMiddleSlotPromoId_: string = '';
+  private accessor promo_: Promo|null = null;
+  private blocklistedMiddleSlotPromoId_: string = '';
   private eventTracker_: EventTracker = new EventTracker();
   private pageHandler_: PageHandlerRemote;
   private setPromoListenerId_: number|null = null;
@@ -212,23 +208,34 @@
     }
   }
 
+  private hidePromoContainer_() {
+    this.$.promoAndDismissContainer.hidden = true;
+    this.fire('ntp-middle-slot-promo-loaded');
+  }
+
   private onPromoChange_() {
+    if (!this.promo_) {
+      this.hidePromoContainer_();
+      return;
+    }
+
     renderPromo(this.promo_).then(promo => {
       if (!promo) {
-        this.$.promoAndDismissContainer.hidden = true;
-      } else {
-        const promoContainer = this.shadowRoot.getElementById('promoContainer');
-        if (promoContainer) {
-          promoContainer.remove();
-        }
-        if (loadTimeData.getBoolean('middleSlotPromoDismissalEnabled')) {
-          this.shownMiddleSlotPromoId_ = promo.id ?? '';
-        }
-        const renderedPromoContainer = promo.container;
-        assert(renderedPromoContainer);
-        this.$.promoAndDismissContainer.prepend(renderedPromoContainer);
-        this.$.promoAndDismissContainer.hidden = false;
+        this.hidePromoContainer_();
+        return;
       }
+
+      const promoContainer = this.shadowRoot.getElementById('promoContainer');
+      if (promoContainer) {
+        promoContainer.remove();
+      }
+      if (loadTimeData.getBoolean('middleSlotPromoDismissalEnabled')) {
+        this.shownMiddleSlotPromoId_ = promo.id ?? '';
+      }
+      const renderedPromoContainer = promo.container;
+      assert(renderedPromoContainer);
+      this.$.promoAndDismissContainer.prepend(renderedPromoContainer);
+      this.$.promoAndDismissContainer.hidden = false;
       this.fire('ntp-middle-slot-promo-loaded');
     });
   }
diff --git a/chrome/browser/resources/new_tab_page/modules/module_wrapper.ts b/chrome/browser/resources/new_tab_page/modules/module_wrapper.ts
index 2a5c051..ceb5771 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_wrapper.ts
+++ b/chrome/browser/resources/new_tab_page/modules/module_wrapper.ts
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {assert} from 'chrome://resources/js/assert.js';
+import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {CrLitElement, render} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
 import {recordLoadDuration, recordOccurrence, recordPerdecage, recordSparseValueWithPersistentHash} from '../metrics_utils.js';
@@ -45,7 +47,8 @@
     };
   }
 
-  accessor module: ModuleInstance;
+  accessor module: ModuleInstance|null = null;
+  private eventTracker_: EventTracker = new EventTracker();
 
   override render() {
     // Update the light DOM element(s) and allow Lit to handle the shadow DOM
@@ -56,7 +59,14 @@
     return getHtml.bind(this)();
   }
 
+  override disconnectedCallback() {
+    super.disconnectedCallback();
+    this.eventTracker_.removeAll();
+  }
+
   override firstUpdated() {
+    assert(this.module);
+
     if (!this.module.initialized) {
       this.module.initialized = true;
       this.initModuleInstance_();
@@ -64,30 +74,35 @@
 
     if (!this.module.impressed) {
       // Install observer to log module header impression.
-      const headerObserver =
-          new IntersectionObserver(([{intersectionRatio}]) => {
-            if (intersectionRatio >= 1.0) {
-              headerObserver.disconnect();
+      const headerObserver = new IntersectionObserver((entries) => {
+        assert(entries.length > 0);
+        const observerEntry = entries[0]!;
+        if (observerEntry.intersectionRatio >= 1.0) {
+          headerObserver.disconnect();
 
-              const time = WindowProxy.getInstance().now();
-              recordLoadDuration('NewTabPage.Modules.Impression', time);
-              recordLoadDuration(
-                  `NewTabPage.Modules.Impression.${this.module.descriptor.id}`,
-                  time);
-              this.module.impressed = true;
-              this.dispatchEvent(new Event('detect-impression'));
-              this.module.element.dispatchEvent(new Event('detect-impression'));
-            }
-          }, {threshold: 1.0});
+          assert(this.module);
+          const time = WindowProxy.getInstance().now();
+          recordLoadDuration('NewTabPage.Modules.Impression', time);
+          recordLoadDuration(
+              `NewTabPage.Modules.Impression.${this.module.descriptor.id}`,
+              time);
+          this.module.impressed = true;
+          this.dispatchEvent(new Event('detect-impression'));
+          this.module.element.dispatchEvent(new Event('detect-impression'));
+        }
+      }, {threshold: 1.0});
       headerObserver.observe(this.$.impressionProbe);
     }
   }
 
   private initModuleInstance_() {
+    assert(this.module);
+
     // Log at most one usage per module per NTP page load. This is possible,
     // if a user opens a link in a new tab.
     this.module.element.addEventListener('usage', (e: Event) => {
       e.stopPropagation();
+      assert(this.module);
       NewTabPageProxy.getInstance().handler.onModuleUsed(
           this.module.descriptor.id);
 
@@ -99,18 +114,21 @@
     // button clicks.
     this.module.element.addEventListener('menu-button-click', (e: Event) => {
       e.stopPropagation();
+      assert(this.module);
       NewTabPageProxy.getInstance().handler.onModuleUsed(
           this.module.descriptor.id);
     }, {once: true});
 
     // Log module's id when module's info button is clicked.
     this.module.element.addEventListener('info-button-click', () => {
+      assert(this.module);
       recordSparseValueWithPersistentHash(
           'NewTabPage.Modules.InfoButtonClicked', this.module.descriptor.id);
     }, {once: true});
 
     // Track whether the user hovered on the module.
     this.module.element.addEventListener('mouseover', () => {
+      assert(this.module);
       recordSparseValueWithPersistentHash(
           'NewTabPage.Modules.Hover', this.module.descriptor.id);
     }, {
@@ -121,14 +139,17 @@
     // Install observer to track max perdecage (x/10th) of the module visible
     // on the page.
     let intersectionPerdecage = 0;
-    const moduleObserver = new IntersectionObserver(([{intersectionRatio}]) => {
-      intersectionPerdecage =
-          Math.floor(Math.max(intersectionPerdecage, intersectionRatio * 10));
+    const moduleObserver = new IntersectionObserver((entries) => {
+      assert(entries.length > 0);
+      const observerEntry = entries[0]!;
+      intersectionPerdecage = Math.floor(Math.max(
+          intersectionPerdecage, observerEntry.intersectionRatio * 10));
     }, {threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]});
     // Use `pagehide` rather than `unload` because unload is being deprecated.
     // `pagehide` fires with the same timing and is safe to use since NTP never
     // enters back/forward-cache.
-    window.addEventListener('pagehide', () => {
+    this.eventTracker_.add(window, 'pagehide', () => {
+      assert(this.module);
       recordPerdecage(
           'NewTabPage.Modules.ImpressionRatio', intersectionPerdecage);
       recordPerdecage(
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts
index 0ccdda5..2528ae6 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 import './calendar_event.js';
 
+import {assert} from 'chrome://resources/js/assert.js';
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
@@ -68,9 +69,11 @@
 
   private computeDoubleBookedIndices_(): number[] {
     const results: number[] = [];
+    const expandedEvent = this.events[this.expandedEventIndex_];
+    assert(expandedEvent);
     for (let i = this.expandedEventIndex_ + 1; i < this.events.length; i++) {
-      if (this.events[i].startTime.internalValue ===
-          this.events[this.expandedEventIndex_].startTime.internalValue) {
+      if (this.events[i]!.startTime.internalValue ===
+          expandedEvent.startTime.internalValue) {
         results.push(i);
       } else {
         break;
@@ -82,7 +85,9 @@
   private compareEventPriority_(
       eventAIndex: number, eventBIndex: number, soon: number): number {
     const eventA = this.events[eventAIndex];
+    assert(eventA);
     const eventB = this.events[eventBIndex];
+    assert(eventB);
     const eventAStartTime = toJsTimestamp(eventA.startTime);
     const eventBStartTime = toJsTimestamp(eventB.startTime);
     const eventAInProgress = eventAStartTime <= soon;
@@ -129,8 +134,9 @@
     // Find the indices of all meetings that are not over.
     let expandableEventIndices: number[] = this.events.map((_, i) => i);
     expandableEventIndices = expandableEventIndices.filter((eventIndex) => {
-      const endTimeMs = toJsTimestamp(this.events[eventIndex].endTime);
-      return endTimeMs > now;
+      const expandableEvent = this.events[eventIndex];
+      assert(expandableEvent);
+      return toJsTimestamp(expandableEvent.endTime) > now;
     });
 
     if (expandableEventIndices.length === 0) {
@@ -141,6 +147,7 @@
     expandableEventIndices.sort(
         (a, b) => this.compareEventPriority_(a, b, in5Minutes));
 
+    assert(expandableEventIndices[0]);
     return expandableEventIndices[0];
   }
 
@@ -165,6 +172,7 @@
   // events.
   protected sortEvents_() {
     const expandedEvent = this.events[this.expandedEventIndex_];
+    assert(expandedEvent);
     const firstDoubleBookedEventIndex =
         this.events.findIndex((calendarEvent: CalendarEvent) => {
           return calendarEvent.startTime.internalValue ===
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar_event.ts b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar_event.ts
index 4f856be..aecf60c0 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar_event.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar_event.ts
@@ -4,6 +4,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/cr_chip/cr_chip.js';
 
+import {assert} from 'chrome://resources/js/assert.js';
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
@@ -91,14 +92,18 @@
         (this.expanded && this.showAttachments_())) {
       const attachmentList = this.renderRoot.querySelector('#attachmentList');
       if (attachmentList && attachmentList.children.length > 1) {
+        const attachments = attachmentList.children;
         this.intersectionObserver_ =
             new IntersectionObserver(() => this.updateAttachmentListClass_(), {
               root: attachmentList,
               threshold: 1.0,
             });
-        this.intersectionObserver_.observe(attachmentList.children[0]);
-        this.intersectionObserver_.observe(
-            attachmentList.children[attachmentList.children.length - 1]);
+        const firstAttachment = attachments[0]!;
+        assert(firstAttachment);
+        this.intersectionObserver_.observe(firstAttachment);
+        const lastAttachment = attachments[attachments.length - 1];
+        assert(lastAttachment);
+        this.intersectionObserver_.observe(lastAttachment);
       }
     }
   }
@@ -151,7 +156,9 @@
   }
 
   protected isAttachmentDisabled_(index: number): boolean {
-    return !this.event.attachments[index].resourceUrl?.url;
+    const attachment = this.event.attachments[index];
+    assert(attachment);
+    return !attachment.resourceUrl?.url;
   }
 
   protected openAttachment_(e: Event) {
@@ -159,6 +166,7 @@
     recordCalendarAction(CalendarAction.ATTACHMENT_CLICKED, this.moduleName);
     const currentTarget = e.currentTarget as HTMLElement;
     const index = Number(currentTarget.dataset['index']);
+    assert(this.event.attachments[index]);
     const resourceUrl = this.event.attachments[index].resourceUrl?.url;
     if (resourceUrl) {
       WindowProxy.getInstance().navigate(resourceUrl);
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/file_suggestion.ts b/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/file_suggestion.ts
index 0ba7b10..084d627 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/file_suggestion.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/file_suggestion.ts
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {assert} from 'chrome://resources/js/assert.js';
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
 import type {File} from '../../../file_suggestion.mojom-webui.js';
@@ -51,11 +52,12 @@
     const index = Number(currentTarget.dataset['index']);
     recordSmallCount(
         `NewTabPage.${this.moduleName}.FileClick`, index);
-    const recommendationType = this.files[index].recommendationType;
-    if (recommendationType != null) {
+    const file = this.files[index];
+    assert(file);
+    if (file.recommendationType !== null) {
       recordEnumeration(
           `NewTabPage.${this.moduleName}.RecommendationTypeClick`,
-          recommendationType, RecommendationType.MAX_VALUE + 1);
+          file.recommendationType, RecommendationType.MAX_VALUE + 1);
     }
   }
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/microsoft_files_module.ts b/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/microsoft_files_module.ts
index 7455976..d5548fc 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/microsoft_files_module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/file_suggestion/microsoft_files_module.ts
@@ -145,9 +145,12 @@
     numOfFiles.set(RecommendationType.kShared, 0);
     numOfFiles.set(RecommendationType.kTrending, 0);
     for (let i = 0; i < files.length; i++) {
-      numOfFiles.set(
-          files[i].recommendationType!,
-          numOfFiles.get(files[i].recommendationType!)! + 1);
+      const file = files[i]!;
+      const recommendationType = file.recommendationType;
+      if (recommendationType !== null) {
+        numOfFiles.set(
+            recommendationType, numOfFiles.get(recommendationType)! + 1);
+      }
     }
     recordSmallCount(
         'NewTabPage.MicrosoftFiles.ShownFiles.Used',
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/module_header.ts b/chrome/browser/resources/new_tab_page/modules/v2/module_header.ts
index a8572fc..2440ca3 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/module_header.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/module_header.ts
@@ -51,7 +51,7 @@
 
   accessor headerText: string|null = null;
   accessor menuItemGroups: MenuItem[][] = [];
-  accessor moreActionsText: string;
+  accessor moreActionsText: string = '';
 
   protected onButtonClick_(e: Event) {
     const action = (e.currentTarget as HTMLElement).dataset['action'];
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/modules.ts b/chrome/browser/resources/new_tab_page/modules/v2/modules.ts
index 9abe380..215d46f 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/modules.ts
+++ b/chrome/browser/resources/new_tab_page/modules/v2/modules.ts
@@ -113,7 +113,7 @@
   private maxColumnCount_: number =
       loadTimeData.getInteger('modulesMaxColumnCount');
   private availableWidth_: number = 0;
-  private containerMaxWidth_: number;
+  private containerMaxWidth_: number = 0;
   private eventTracker_: EventTracker = new EventTracker();
   private setDisabledModulesListenerId_: number|null = null;
   private setModulesLoadableListenerId_: number|null = null;
@@ -126,7 +126,6 @@
   // loading behavior.
   private modulesReloadable_: boolean =
       loadTimeData.getBoolean('modulesReloadable');
-  private modulesLoadInitiated_: boolean = false;
 
   override render() {
     return getHtml.bind(this)();
@@ -137,7 +136,7 @@
 
     const widths: Set<number> = new Set();
     for (let i = 0; i < SUPPORTED_MODULE_WIDTHS.length; i++) {
-      const namedWidth = SUPPORTED_MODULE_WIDTHS[i];
+      const namedWidth = SUPPORTED_MODULE_WIDTHS[i]!;
       for (let u = 1; u <= this.maxColumnCount_ - i; u++) {
         const width = (namedWidth.value * u) + (CONTAINER_GAP_WIDTH * (u - 1));
         if (width <= this.containerMaxWidth_) {
@@ -153,20 +152,20 @@
     const queries: QueryDetails[] = [];
     for (let i = 1; i < thresholds.length - 1; i++) {
       queries.push({
-        maxWidth: (thresholds[i + 1] - 1),
+        maxWidth: (thresholds[i + 1]! - 1),
         query: `(min-width: ${
-            thresholds[i] + 2 * MARGIN_WIDTH}px) and (max-width: ${
-            thresholds[i + 1] - 1 + (2 * MARGIN_WIDTH)}px)`,
+            thresholds[i]! + 2 * MARGIN_WIDTH}px) and (max-width: ${
+            thresholds[i + 1]! - 1 + (2 * MARGIN_WIDTH)}px)`,
       });
     }
     queries.splice(0, 0, {
-      maxWidth: thresholds[0],
-      query: `(max-width: ${thresholds[0] - 1 + (2 * MARGIN_WIDTH)}px)`,
+      maxWidth: thresholds[0]!,
+      query: `(max-width: ${thresholds[0]! - 1 + (2 * MARGIN_WIDTH)}px)`,
     });
     queries.push({
-      maxWidth: thresholds[thresholds.length - 1],
+      maxWidth: thresholds[thresholds.length - 1]!,
       query: `(min-width: ${
-          thresholds[thresholds.length - 1] + (2 * MARGIN_WIDTH)}px)`,
+          thresholds[thresholds.length - 1]! + (2 * MARGIN_WIDTH)}px)`,
     });
 
     // Produce media queries with relevant view thresholds at which module
@@ -219,6 +218,7 @@
   override firstUpdated() {
     this.style.setProperty('--container-gap', `${CONTAINER_GAP_WIDTH}px`);
 
+    assert(SUPPORTED_MODULE_WIDTHS[0]);
     this.containerMaxWidth_ =
         this.maxColumnCount_ * SUPPORTED_MODULE_WIDTHS[0].value +
         (this.maxColumnCount_ - 1) * CONTAINER_GAP_WIDTH;
@@ -257,7 +257,6 @@
    * and is called only when the container is empty.
    */
   private async loadModules_(): Promise<void> {
-    this.modulesLoadInitiated_ = true;
     const modulesIdNames = (await this.pageHandler_.getModulesIdNames()).data;
     const modules =
         await ModuleRegistry.getInstance().initializeModulesHavingIds(
@@ -398,22 +397,24 @@
         1,
         Math.floor(
             (availableWidth + CONTAINER_GAP_WIDTH) /
-            (CONTAINER_GAP_WIDTH + SUPPORTED_MODULE_WIDTHS[0].value)),
+            (CONTAINER_GAP_WIDTH + SUPPORTED_MODULE_WIDTHS[0]!.value)),
         this.maxColumnCount_);
 
     let index = 0;
     while (index < visibleModuleInstances.length) {
       const instances =
           visibleModuleInstances.slice(index, index + rowMaxInstanceCount);
-      let namedWidth = SUPPORTED_MODULE_WIDTHS[0];
+      let namedWidth = SUPPORTED_MODULE_WIDTHS[0]!;
       for (let i = 1; i < SUPPORTED_MODULE_WIDTHS.length; i++) {
+        const moduleWidth = SUPPORTED_MODULE_WIDTHS[i];
+        assert(moduleWidth);
         if (Math.floor(
                 (availableWidth -
                  (CONTAINER_GAP_WIDTH * (instances.length - 1))) /
-                SUPPORTED_MODULE_WIDTHS[i].value) < instances.length) {
+                moduleWidth.value) < instances.length) {
           break;
         }
-        namedWidth = SUPPORTED_MODULE_WIDTHS[i];
+        namedWidth = moduleWidth;
       }
 
       instances.slice(0, instances.length).forEach(instance => {
@@ -428,8 +429,12 @@
   }
 
   protected onDisableModule_(e: DisableModuleEvent) {
-    const id = ((e.target! as HTMLElement).parentNode as ModuleWrapperElement)
-                   .module.descriptor.id;
+    const moduleWrapper =
+        (e.target! as HTMLElement).parentNode as ModuleWrapperElement;
+    assert(moduleWrapper);
+    const module = moduleWrapper.module;
+    assert(module);
+    const id = module.descriptor.id;
     const restoreCallback = e.detail.restoreCallback;
     this.undoData_ = {
       message: e.detail.message,
@@ -460,6 +465,7 @@
         ((e.target! as HTMLElement).parentNode as ModuleWrapperElement);
     const index = Array.from(wrapper.parentNode!.children).indexOf(wrapper);
     const module = this.moduleInstances_[index];
+    assert(module);
     this.moduleInstances_ = this.moduleInstances_.toSpliced(index, 1);
 
     const restoreCallback = e.detail.restoreCallback;
diff --git a/chrome/browser/resources/new_tab_page/ntp_promo/ntp_single_promo.ts b/chrome/browser/resources/new_tab_page/ntp_promo/ntp_single_promo.ts
index fcadf54c..9a1eb11 100644
--- a/chrome/browser/resources/new_tab_page/ntp_promo/ntp_single_promo.ts
+++ b/chrome/browser/resources/new_tab_page/ntp_promo/ntp_single_promo.ts
@@ -83,7 +83,7 @@
   // Public for testing purposes only.
   onSetPromos(eligible: Promo[]) {
     if (eligible.length > 0) {
-      const promo: Promo = eligible[0];
+      const promo: Promo = eligible[0]!;
       this.bodyIconName_ = promo.iconName;
       this.bodyText_ = promo.bodyText;
       this.actionButtonText_ = promo.buttonText;
diff --git a/chrome/browser/resources/new_tab_page/tsconfig_base.json b/chrome/browser/resources/new_tab_page/tsconfig_base.json
index 4f55657a2..d5e92a3f 100644
--- a/chrome/browser/resources/new_tab_page/tsconfig_base.json
+++ b/chrome/browser/resources/new_tab_page/tsconfig_base.json
@@ -1,5 +1,5 @@
 {
-  "extends": "../../../../tools/typescript/tsconfig_base_mixed.json",
+  "extends": "../../../../tools/typescript/tsconfig_base_lit.json",
   "compilerOptions": {
     "typeRoots": ["../../../../third_party/node/node_modules/@types"],
     "types": ["dom-speech-recognition"]
diff --git a/chrome/browser/resources/new_tab_page/voice_search_overlay.ts b/chrome/browser/resources/new_tab_page/voice_search_overlay.ts
index 849d498c..28ddced 100644
--- a/chrome/browser/resources/new_tab_page/voice_search_overlay.ts
+++ b/chrome/browser/resources/new_tab_page/voice_search_overlay.ts
@@ -5,12 +5,11 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_page_selector/cr_page_selector.js';
 
+import {assert} from 'chrome://resources/js/assert.js';
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
 import {loadTimeData} from './i18n_setup.js';
 import {recordEnumeration} from './metrics_utils.js';
-import type {PageHandlerRemote} from './new_tab_page.mojom-webui.js';
-import {NewTabPageProxy} from './new_tab_page_proxy.js';
 import {getCss} from './voice_search_overlay.css.js';
 import {getHtml} from './voice_search_overlay.html.js';
 import {WindowProxy} from './window_proxy.js';
@@ -200,7 +199,6 @@
       interimResult_: {type: String},
       finalResult_: {type: String},
       state_: {type: Number},
-      error_: {type: Number},
       helpUrl_: {type: String},
       micVolumeLevel_: {type: Number},
       micVolumeDuration_: {type: Number},
@@ -210,7 +208,6 @@
   protected accessor interimResult_: string = '';
   protected accessor finalResult_: string = '';
   private accessor state_: State = State.UNINITIALIZED;
-  private accessor error_: Error;
   protected accessor helpUrl_: string =
       `https://support.google.com/chrome/?p=ui_voice_search&hl=${
           window.navigator.language}`;
@@ -218,13 +215,12 @@
   protected accessor micVolumeDuration_: number =
       VOLUME_ANIMATION_DURATION_MIN_MS;
 
-  private pageHandler_: PageHandlerRemote;
   private voiceRecognition_: SpeechRecognition;
+  private error_: Error|null = null;
   private timerId_: number|null = null;
 
   constructor() {
     super();
-    this.pageHandler_ = NewTabPageProxy.getInstance().handler;
     this.voiceRecognition_ = new window.webkitSpeechRecognition();
     this.voiceRecognition_.continuous = false;
     this.voiceRecognition_.interimResults = true;
@@ -367,17 +363,21 @@
     this.interimResult_ = '';
     this.finalResult_ = '';
 
-    const finalResult = results[e.resultIndex];
+    const speechResult = results[e.resultIndex];
+    assert(speechResult);
     // Process final results.
-    if (finalResult.isFinal) {
-      this.finalResult_ = finalResult[0].transcript;
+    if (!!speechResult && speechResult.isFinal) {
+      this.finalResult_ = speechResult[0]!.transcript;
       this.onFinalResult_();
       return;
     }
 
     // Process interim results.
     for (let j = 0; j < results.length; j++) {
-      const result = results[j][0];
+      const resultList = results[j]!;
+      const result = resultList[0];
+      assert(result);
+
       if (result.confidence > RECOGNITION_CONFIDENCE_THRESHOLD) {
         this.finalResult_ += result.transcript;
       } else {
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 3d9630b..d72db96 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -65,7 +65,7 @@
         }
       }
     </style>
-    <settings-section>
+    <settings-section page-title="$i18n{peoplePageTitle}">
       <div>
 
 <if expr="not is_chromeos">
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
index 56e8ad2..5ef6e8b 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/AdvancedProtectionMediatorTest.java
@@ -18,10 +18,12 @@
 import androidx.fragment.app.Fragment;
 
 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.annotation.Config;
 
 import org.chromium.base.ContextUtils;
@@ -50,6 +52,7 @@
 @DisableFeatures(PermissionsAndroidFeatureList.OS_ADDITIONAL_SECURITY_PERMISSION_KILL_SWITCH)
 @Config(manifest = Config.NONE)
 public class AdvancedProtectionMediatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private WindowAndroid mWindowAndroid;
     @Mock private Context mContext;
     private final WeakReference<Context> mWeakContext = new WeakReference<>(mContext);
@@ -94,7 +97,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         when(mWindowAndroid.getUnownedUserDataHost()).thenReturn(mWindowUserDataHost);
         when(mWindowAndroid.getContext()).thenReturn(mWeakContext);
         MessagesFactory.attachMessageDispatcher(mWindowAndroid, mMessageDispatcher);
diff --git a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
index 290af48..7c4ada9 100644
--- a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
+++ b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
@@ -17,13 +17,13 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.DoNotBatch;
@@ -57,6 +57,8 @@
     private static final String ASSERT_SAFE_BROWSING_STATE_NATIVE =
             "Incorrect Safe Browsing state from native.";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<SafeBrowsingSettingsFragment> mTestRule =
             new SettingsActivityTestRule<>(SafeBrowsingSettingsFragment.class);
@@ -69,11 +71,6 @@
     private RadioButtonGroupSafeBrowsingPreference mSafeBrowsingPreference;
     private Preference mManagedDisclaimerText;
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
     private void startSettings() {
         mTestRule.startSettingsActivity();
         mSafeBrowsingSettingsFragment = mTestRule.getFragment();
diff --git a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
index 27ca96b..c2f5731 100644
--- a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
+++ b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
@@ -108,8 +108,4 @@
   return ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 }
 
-bool ChromeSafeBrowsingUIManagerDelegate::IsSendingOfHitReportsEnabled() {
-  return true;
-}
-
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.h b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.h
index eef6b3b..111d9ee0 100644
--- a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.h
+++ b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.h
@@ -47,7 +47,6 @@
   PingManager* GetPingManager(
       content::BrowserContext* browser_context) override;
   bool IsMetricsAndCrashReportingEnabled() override;
-  bool IsSendingOfHitReportsEnabled() override;
 };
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
index 58ae222..af5958c 100644
--- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
+++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
@@ -34,7 +34,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.ParameterizedRobolectricTestRunner;
 import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
 import org.robolectric.annotation.Config;
@@ -118,6 +119,8 @@
 
     private static final String TEST_EMAIL_ADDRESS = "test@example.com";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule(order = -2)
     public BaseRobolectricTestRule mBaseRule = new BaseRobolectricTestRule();
 
@@ -257,7 +260,6 @@
 
     @Before
     public void setUp() throws PasswordCheckBackendException, CredentialManagerBackendException {
-        MockitoAnnotations.initMocks(this);
         PasswordManagerUtilBridgeJni.setInstanceForTesting(mPasswordManagerUtilBridgeNativeMock);
         PasswordManagerHelperJni.setInstanceForTesting(mPasswordManagerHelperNativeMock);
         when(mProfile.getOriginalProfile()).thenReturn(mProfile);
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java
index 0cdd8d8..cfa6e91 100644
--- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java
+++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java
@@ -23,7 +23,8 @@
 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.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
@@ -72,6 +73,8 @@
     private static final long H_TO_MS = 60 * MIN_TO_MS;
     private static final long DAY_TO_MS = 24 * H_TO_MS;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public SettingsActivityTestRule<SafetyCheckSettingsFragment> mSettingsActivityTestRule =
             new SettingsActivityTestRule<>(SafetyCheckSettingsFragment.class);
@@ -88,7 +91,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck);
         SyncServiceFactory.setInstanceForTesting(mSyncService);
         PasswordManagerUtilBridgeJni.setInstanceForTesting(mPasswordManagerUtilBridgeNativeMock);
diff --git a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediatorUnitTest.java b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediatorUnitTest.java
index 35b4dc6..20a2e6c 100644
--- a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediatorUnitTest.java
+++ b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediatorUnitTest.java
@@ -19,12 +19,14 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.FeatureOverrides;
@@ -65,6 +67,7 @@
 @Features.DisableFeatures(ChromeFeatureList.SEARCH_RESUMPTION_MODULE_ANDROID)
 public class SearchResumptionModuleMediatorUnitTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Tab mTabToTrack;
     @Mock private Tab mTab;
     @Mock private ViewStub mParent;
@@ -94,7 +97,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mUserDataHost = new UserDataHost();
         AutocompleteControllerJni.setInstanceForTesting(mControllerJniMock);
         doReturn(mAutocompleteController).when(mControllerJniMock).getForProfile(any());
diff --git a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
index 0a2618c..6f72182 100644
--- a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
+++ b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
@@ -14,11 +14,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.FeatureOverrides;
@@ -48,6 +50,7 @@
 @SuppressWarnings("DoNotMock") // Mocks GURL
 @Features.EnableFeatures(ChromeFeatureList.SEARCH_RESUMPTION_MODULE_ANDROID)
 public class SearchResumptionModuleUtilsUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private TemplateUrlService mTemplateUrlService;
     @Mock private IdentityServicesProvider mIdentityServicesProvider;
     @Mock private SyncService mSyncServiceMock;
@@ -60,8 +63,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService);
         IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
         doReturn(mIdentityManager).when(mIdentityServicesProvider).getIdentityManager(any());
diff --git a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleViewUnitTest.java b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleViewUnitTest.java
index f14ae34..b204f8e 100644
--- a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleViewUnitTest.java
+++ b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleViewUnitTest.java
@@ -15,11 +15,13 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.Robolectric;
 import org.robolectric.annotation.Config;
 
@@ -38,6 +40,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class SearchResumptionModuleViewUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private Activity mActivity;
     private SearchResumptionModuleView mModuleView;
     private View mHeaderView;
@@ -49,7 +52,6 @@
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mPropertyModel = new PropertyModel(SearchResumptionModuleProperties.ALL_KEYS);
     }
diff --git a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionTileBuilderUnitTest.java b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionTileBuilderUnitTest.java
index abd71990..5eff903 100644
--- a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionTileBuilderUnitTest.java
+++ b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionTileBuilderUnitTest.java
@@ -13,10 +13,12 @@
 import androidx.test.filters.MediumTest;
 
 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.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -36,6 +38,7 @@
 public class SearchResumptionTileBuilderUnitTest {
     // The search suggestions are meant to be shown on any website.
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Tab mTab;
     @Mock private SearchResumptionTileContainerView mSuggestionTilesContainerView;
     @Mock SearchResumptionTileView mTileView1;
@@ -52,8 +55,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         doReturn(OmniboxSuggestionType.SEARCH_SUGGEST).when(mSearchSuggest1).getType();
         doReturn("suggestion 1").when(mSearchSuggest1).getDisplayText();
 
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTest.java
index 8f06f0d..ae125d1f 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTest.java
@@ -24,6 +24,7 @@
 import org.chromium.base.test.BaseActivityTestRule;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.ui.base.WindowAndroid;
@@ -100,8 +101,8 @@
         qrCodeDialog.setTabs(tabs);
 
         View dialog = qrCodeDialog.getDialogView(mActivityTestRule.getActivity());
-        ViewPager viewPager = dialog.findViewById(org.chromium.chrome.R.id.qrcode_view_pager);
-        TabLayout tabLayout = dialog.findViewById(org.chromium.chrome.R.id.tab_layout);
+        ViewPager viewPager = dialog.findViewById(R.id.qrcode_view_pager);
+        TabLayout tabLayout = dialog.findViewById(R.id.tab_layout);
 
         assertEquals(
                 "Tab is disabled and should not be in adapter.",
@@ -123,8 +124,8 @@
         qrCodeDialog.setTabs(tabs);
 
         View dialog = qrCodeDialog.getDialogView(mActivityTestRule.getActivity());
-        ViewPager viewPager = dialog.findViewById(org.chromium.chrome.R.id.qrcode_view_pager);
-        TabLayout tabLayout = dialog.findViewById(org.chromium.chrome.R.id.tab_layout);
+        ViewPager viewPager = dialog.findViewById(R.id.qrcode_view_pager);
+        TabLayout tabLayout = dialog.findViewById(R.id.tab_layout);
 
         assertEquals("Tab views should be in the viewPager.", 1, viewPager.getAdapter().getCount());
         assertEquals("Tabs should be in the tabLayout.", 1, tabLayout.getTabCount());
diff --git a/chrome/browser/shortcuts/BUILD.gn b/chrome/browser/shortcuts/BUILD.gn
index 0b4ff13..b756216 100644
--- a/chrome/browser/shortcuts/BUILD.gn
+++ b/chrome/browser/shortcuts/BUILD.gn
@@ -144,6 +144,7 @@
       "//chrome/browser:browser_process",
       "//chrome/browser/profiles",
       "//chrome/browser/ui",
+      "//chrome/browser/ui/startup",
       "//chrome/common:non_code_constants",
       "//chrome/test:test_support",
       "//chrome/test:test_support_ui",
diff --git a/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabModuleViewBinderUnitTest.java b/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabModuleViewBinderUnitTest.java
index 792d8109..7e1c38a8 100644
--- a/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabModuleViewBinderUnitTest.java
+++ b/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabModuleViewBinderUnitTest.java
@@ -35,10 +35,12 @@
 
 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.robolectric.annotation.Config;
 
@@ -59,6 +61,7 @@
     private static final int TAB_ID = 1;
     private static final String HISTOGRAM_START_SURFACE_MODULE_CLICK = "StartSurface.Module.Click";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private Activity mActivity;
     private SingleTabView mSingleTabModuleView;
     private PropertyModelChangeProcessor<PropertyModel, SingleTabView, PropertyKey>
@@ -72,8 +75,6 @@
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mActivity.setTheme(R.style.Theme_BrowserUI_DayNight);
         mSingleTabModuleView =
@@ -105,16 +106,16 @@
     @SmallTest
     public void testVisibility() {
         mPropertyModel.set(IS_VISIBLE, true);
-        assertTrue(isViewVisible(org.chromium.chrome.R.id.single_tab_view));
+        assertTrue(isViewVisible(R.id.single_tab_view));
 
         mPropertyModel.set(IS_VISIBLE, false);
-        assertFalse(isViewVisible(org.chromium.chrome.R.id.single_tab_view));
+        assertFalse(isViewVisible(R.id.single_tab_view));
     }
 
     @Test
     @SmallTest
     public void testSetTitle() {
-        TextView title = mSingleTabModuleView.findViewById(org.chromium.chrome.R.id.tab_title_view);
+        TextView title = mSingleTabModuleView.findViewById(R.id.tab_title_view);
         assertEquals("", title.getText());
 
         mPropertyModel.set(TITLE, TEST_TITLE);
@@ -124,7 +125,7 @@
     @Test
     @SmallTest
     public void testSetUrl() {
-        TextView url = mSingleTabModuleView.findViewById(org.chromium.chrome.R.id.tab_url_view);
+        TextView url = mSingleTabModuleView.findViewById(R.id.tab_url_view);
         assertEquals("", url.getText());
 
         mPropertyModel.set(URL, TEST_URL);
@@ -134,8 +135,7 @@
     @Test
     @SmallTest
     public void testSetFavicon() {
-        ImageView favicon =
-                mSingleTabModuleView.findViewById(org.chromium.chrome.R.id.tab_favicon_view);
+        ImageView favicon = mSingleTabModuleView.findViewById(R.id.tab_favicon_view);
         assertNull(favicon.getDrawable());
 
         mPropertyModel.set(FAVICON, new BitmapDrawable());
diff --git a/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabSwitcherOnNtpMediatorUnitTest.java b/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabSwitcherOnNtpMediatorUnitTest.java
index 3deddbff..ef06b93 100644
--- a/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabSwitcherOnNtpMediatorUnitTest.java
+++ b/chrome/browser/single_tab/android/junit/src/org/chromium/chrome/browser/single_tab/SingleTabSwitcherOnNtpMediatorUnitTest.java
@@ -35,13 +35,15 @@
 import android.util.Size;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.Callback;
@@ -73,6 +75,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class SingleTabSwitcherOnNtpMediatorUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock UrlUtilities.Natives mUrlUtilitiesJniMock;
 
     private final int mTabId = 1;
@@ -100,7 +103,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         UrlUtilitiesJni.setInstanceForTesting(mUrlUtilitiesJniMock);
 
         doReturn(true).when(mTabListFaviconProvider).isInitialized();
@@ -397,8 +399,7 @@
                 ContextUtils.getApplicationContext()
                         .getResources()
                         .getDimensionPixelSize(
-                                org.chromium.chrome.R.dimen
-                                        .ntp_search_box_lateral_margin_narrow_window_tablet);
+                                R.dimen.ntp_search_box_lateral_margin_narrow_window_tablet);
         UiConfig.DisplayStyle displayStyleRegular =
                 new DisplayStyle(HorizontalDisplayStyle.REGULAR, VerticalDisplayStyle.REGULAR);
         when(mUiConfig.getCurrentDisplayStyle()).thenReturn(displayStyleRegular);
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
index 23cfd8e..8b4360f 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -38,7 +38,6 @@
 #include "components/supervised_user/core/browser/supervised_user_url_filter.h"
 #include "components/supervised_user/core/browser/supervised_user_utils.h"
 #include "components/supervised_user/core/common/features.h"
-#include "components/supervised_user/core/common/features_testutils.h"
 #include "components/supervised_user/core/common/supervised_user_constants.h"
 #include "components/supervised_user/test_support/kids_management_api_server_mock.h"
 #include "content/public/browser/navigation_controller.h"
@@ -405,9 +404,7 @@
 }
 
 class SupervisedUserIframeFilterTest
-    : public SupervisedUserNavigationThrottleTestBase,
-      public testing::WithParamInterface<
-          supervised_user::testing::LocalWebApprovalsTestCase> {
+    : public SupervisedUserNavigationThrottleTestBase {
  protected:
   SupervisedUserIframeFilterTest()
       : SupervisedUserNavigationThrottleTestBase(
@@ -442,23 +439,12 @@
   RenderFrameTracker* tracker() { return tracker_.get(); }
 
  private:
-  static supervised_user::testing::LocalWebApprovalsTestCase
-  GetLocalWebApprovalsSupportTestParam() {
-    return GetParam();
-  }
-
- private:
   bool RunCommandAndGetBooleanFromFrame(content::FrameTreeNodeId frame_id,
                                         const std::string& command);
 
   std::unique_ptr<RenderFrameTracker> tracker_;
   raw_ptr<supervised_user::PermissionRequestCreatorMock, DanglingUntriaged>
       permission_creator_;
-
-  // Each feature is enabled within its own feature list.
-  std::unique_ptr<base::test::ScopedFeatureList>
-      local_web_approvals_test_support_{
-          GetLocalWebApprovalsSupportTestParam().MakeFeatureList()};
 };
 
 void SupervisedUserIframeFilterTest::SetUpOnMainThread() {
@@ -624,17 +610,7 @@
   return supervised_user::IsLocalWebApprovalsEnabled();
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    LocalWebApprovalsEnabled,
-    SupervisedUserIframeFilterTest,
-    supervised_user::testing::LocalWebApprovalsTestCase::Values(),
-    [](const testing::TestParamInfo<
-        supervised_user::testing::LocalWebApprovalsTestCase>& info) {
-      return base::StrCat({"WithLocalWebApprovalsTestCase",
-                           static_cast<std::string>(info.param)});
-    });
-
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, BlockSubFrame) {
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest, BlockSubFrame) {
   base::HistogramTester histogram_tester;
 
   BlockHost(kIframeHost2);
@@ -681,7 +657,7 @@
       1);
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, BlockMultipleSubFrames) {
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest, BlockMultipleSubFrames) {
   BlockHost(kIframeHost1);
   BlockHost(kIframeHost2);
 
@@ -729,7 +705,7 @@
   DCHECK_EQ(GetBlockedFrames().size(), 0u);
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, TestBackButton) {
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest, TestBackButton) {
   BlockHost(kIframeHost1);
 
   GURL allowed_url_with_iframes = embedded_test_server()->GetURL(
@@ -758,7 +734,7 @@
                                   content::EXECUTE_SCRIPT_NO_USER_GESTURE));
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest,
                        TestBackButtonMainFrame) {
   BlockHost(kExampleHost);
 
@@ -793,7 +769,7 @@
 // Tests that the trivial www-subdomain stripping is applied on the url
 // of the interstitial. Blocked urls without further conflicts will be
 // unblocked by a remote approval.
-IN_PROC_BROWSER_TEST_P(
+IN_PROC_BROWSER_TEST_F(
     SupervisedUserIframeFilterTest,
     BlockedMainFrameFromClassifyUrlForUnstripedHostIsStrippedInRemoteApproval) {
   // Classify url blocks the navigation to the target url.
@@ -830,7 +806,7 @@
 
 // Tests that the url stripping is applied on the url on the interstitial, when
 // there is no unstriped host entry in the blocklist.
-IN_PROC_BROWSER_TEST_P(
+IN_PROC_BROWSER_TEST_F(
     SupervisedUserIframeFilterTest,
     BlockedMainFrameFromBlockListIsStrippedInRemoteApproval) {
   // Manual parental blocklist entry blocks the navigation to the target url.
@@ -862,7 +838,7 @@
 // Tests that the url stripping is skipped on the url on the interstitial, when
 // there is a unstriped host entry in the blocklist. Blocked urls without
 // further conflicts will be unblocked by a remote approval.
-IN_PROC_BROWSER_TEST_P(
+IN_PROC_BROWSER_TEST_F(
     SupervisedUserIframeFilterTest,
     BlockedMainFrameFromBlockListForUnstripedHostSkipsStrippingInRemoteApproval) {
   // Manual parental blocklist entry for the unstriped url blocks the
@@ -895,7 +871,7 @@
   EXPECT_FALSE(IsInterstitialBeingShownInFrame(blocked_frame_id));
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest,
                        AllowlistedMainFrameDenylistedIframe) {
   AllowlistHost(kExampleHost);
   BlockHost(kIframeHost1);
@@ -912,7 +888,7 @@
   EXPECT_EQ(kIframeHost1, GetBlockedFrameURL(blocked[0]).host());
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest,
                        RememberAlreadyRequestedHosts) {
   BlockHost(kExampleHost);
 
@@ -929,8 +905,12 @@
   // Expect that the local approvals button is shown if the flag is enabled.
   EXPECT_EQ(IsLocalWebApprovalsEnabled(),
             IsLocalApprovalsButtonBeingShown(blocked_frames[0]));
-  // Expect that the "Block reason" is shown.
-  EXPECT_TRUE(IsBlockReasonBeingShown(blocked_frames[0]));
+  if (!base::FeatureList::IsEnabled(
+          supervised_user::kSupervisedUserBlockInterstitialV3)) {
+    // Expect that the "Block reason" is shown if we are in interstitial
+    // version 2. The field does not exist in interstitial version 3.
+    EXPECT_TRUE(IsBlockReasonBeingShown(blocked_frames[0]));
+  }
 
   // Delay approval/denial by parent.
   permission_creator()->SetPermissionResult(true);
@@ -958,8 +938,12 @@
   // flag is enabled.
   EXPECT_EQ(IsLocalWebApprovalsEnabled(),
             IsLocalApprovalsInsteadButtonBeingShown(blocked_frames[0]));
-  // Expect that the "Block reason" is not shown.
-  EXPECT_FALSE(IsBlockReasonBeingShown(blocked_frames[0]));
+  if (!base::FeatureList::IsEnabled(
+          supervised_user::kSupervisedUserBlockInterstitialV3)) {
+    // Expect that the "Block reason" is not shown if we are in interstitial
+    // version 2. The field does not exist in interstitial version 3.
+    EXPECT_FALSE(IsBlockReasonBeingShown(blocked_frames[0]));
+  }
 
   content::WebContents* active_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -983,7 +967,7 @@
   EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));
 }
 
-IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserIframeFilterTest,
                        IFramesWithSameDomainAsMainFrameAllowed) {
   supervised_user_test_util::SetWebFilterType(
       browser()->profile(), supervised_user::WebFilterType::kCertainSites);
@@ -1025,17 +1009,7 @@
   SupervisedUserIframeFilterTest::SetUp();
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    LocalWebApprovalsEnabledNarrowWidth,
-    SupervisedUserNarrowWidthIframeFilterTest,
-    supervised_user::testing::LocalWebApprovalsTestCase::OnlySupported(),
-    [](const testing::TestParamInfo<
-        supervised_user::testing::LocalWebApprovalsTestCase>& info) {
-      return base::StrCat({"WithLocalWebApprovalsTestCase",
-                           static_cast<std::string>(info.param)});
-    });
-
-IN_PROC_BROWSER_TEST_P(SupervisedUserNarrowWidthIframeFilterTest,
+IN_PROC_BROWSER_TEST_F(SupervisedUserNarrowWidthIframeFilterTest,
                        NarrowWidthWindow) {
   BlockHost(kExampleHost);
 
@@ -1110,18 +1084,7 @@
 // Tests Chrome OS local web approvals flow.
 using ChromeOSLocalWebApprovalsTest = SupervisedUserIframeFilterTest;
 
-// Only test for the local web approvals feature enabled.
-INSTANTIATE_TEST_SUITE_P(
-    ,
-    ChromeOSLocalWebApprovalsTest,
-    supervised_user::testing::LocalWebApprovalsTestCase::OnlySupported(),
-    [](const testing::TestParamInfo<
-        supervised_user::testing::LocalWebApprovalsTestCase>& info) {
-      return base::StrCat({"WithLocalWebApprovalsTestCase",
-                           static_cast<std::string>(info.param)});
-    });
-
-IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
+IN_PROC_BROWSER_TEST_F(ChromeOSLocalWebApprovalsTest,
                        StartLocalWebApprovalsFromMainFrame) {
   base::HistogramTester histogram_tester;
   BlockHost(kExampleHost);
@@ -1167,7 +1130,7 @@
       1);
 }
 
-IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
+IN_PROC_BROWSER_TEST_F(ChromeOSLocalWebApprovalsTest,
                        StartLocalWebApprovalsFromIframe) {
   base::HistogramTester histogram_tester;
   BlockHost(kIframeHost1);
@@ -1218,7 +1181,7 @@
       1);
 }
 
-IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
+IN_PROC_BROWSER_TEST_F(ChromeOSLocalWebApprovalsTest,
                        UpdateUIAfterRemoteRequestSent) {
   BlockHost(kExampleHost);
 
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java
index fb11d19..883ae257 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java
@@ -8,10 +8,12 @@
 import static org.mockito.Mockito.verify;
 
 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.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplierImpl;
@@ -20,6 +22,7 @@
 /** Tests for CurrentTabObserver. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class CurrentTabObserverTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private CurrentTabObserver mCurrentTabObserver;
 
     private ObservableSupplierImpl<Tab> mTabSupplier;
@@ -34,8 +37,6 @@
 
     @Before
     public void beforeTest() {
-        MockitoAnnotations.initMocks(this);
-
         mTabSupplier = new ObservableSupplierImpl<>();
         mCurrentTabObserver = new CurrentTabObserver(mTabSupplier, mTabObserver, mSwapCallback);
     }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedAppTest.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedAppTest.java
index 603b7655..24f7d04 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedAppTest.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabAssociatedAppTest.java
@@ -11,12 +11,14 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.UserDataHost;
@@ -31,6 +33,7 @@
 public class TabAssociatedAppTest {
     private static final String APP_ID = "magicApp";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private Tab mTab;
 
     @Captor ArgumentCaptor<TabObserver> mTabObserverCaptor;
@@ -40,7 +43,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         when(mTab.getUserDataHost()).thenReturn(mUserDataHost);
         doNothing().when(mTab).addObserver(mTabObserverCaptor.capture());
     }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/WebContentsState.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/WebContentsState.java
index 13729ad..c53adb2 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/WebContentsState.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/WebContentsState.java
@@ -6,7 +6,6 @@
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 
 import java.nio.ByteBuffer;
 
@@ -34,7 +33,7 @@
     private static @Nullable WebContentsState sEmptyWebContentsState;
 
     public WebContentsState(ByteBuffer buffer) {
-        assert buffer.isDirect() || ChromeFeatureList.sTabStorageSqlitePrototype.isEnabled();
+        assert buffer.isDirect();
         mBuffer = buffer;
         sEmptyWebContentsState = null;
     }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PriceDropMetricsLoggerTest.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PriceDropMetricsLoggerTest.java
index ada0cdb..7be3527 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PriceDropMetricsLoggerTest.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PriceDropMetricsLoggerTest.java
@@ -10,10 +10,12 @@
 
 import org.junit.Assert;
 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.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.HistogramWatcher;
@@ -23,13 +25,13 @@
 /** Test relating to {@link PriceDropMetricsLogger} */
 @RunWith(BaseRobolectricTestRunner.class)
 public class PriceDropMetricsLoggerTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private ShoppingPersistedTabData mShoppingPersistedTabData;
 
     private PriceDropMetricsLogger mPriceDropMetricsLogger;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         doReturn("offer-id").when(mShoppingPersistedTabData).getMainOfferId();
         doReturn(true).when(mShoppingPersistedTabData).hasPriceMicros();
         doReturn(true).when(mShoppingPersistedTabData).hasPreviousPriceMicros();
diff --git a/chrome/browser/tab/tab_state_storage_service.cc b/chrome/browser/tab/tab_state_storage_service.cc
index aec1e4f..dc0fa8d 100644
--- a/chrome/browser/tab/tab_state_storage_service.cc
+++ b/chrome/browser/tab/tab_state_storage_service.cc
@@ -11,6 +11,7 @@
 #include "base/android/jni_string.h"
 #include "base/android/token_android.h"
 #include "base/logging.h"
+#include "base/memory/raw_ptr.h"
 #include "base/token.h"
 #include "chrome/browser/tab/jni_headers/TabStateStorageService_jni.h"
 
@@ -23,17 +24,21 @@
     const base::android::JavaRef<jobject>& j_callback,
     std::vector<tabs_pb::TabState> tab_states) {
   std::vector<base::android::ScopedJavaLocalRef<jobject>> j_tab_state_vector;
-  for (const tabs_pb::TabState& tab_state : tab_states) {
-    // TODO(skym): Creating copying it into a new string just to pass across
-    // JNI.
-    std::string web_contents_state_bytes = tab_state.web_contents_state_bytes();
-    std::string* heap_web_contents_state_bytes =
-        new std::string(web_contents_state_bytes);
-    auto j_web_contents_state_buffer =
-        base::android::ScopedJavaLocalRef<jobject>::Adopt(
-            env, env->NewDirectByteBuffer(
-                     static_cast<void*>(heap_web_contents_state_bytes->data()),
-                     heap_web_contents_state_bytes->size()));
+  for (tabs_pb::TabState& tab_state : tab_states) {
+    base::android::ScopedJavaLocalRef<jobject> j_web_contents_state_buffer;
+    if (tab_state.has_web_contents_state_bytes()) {
+      // TODO(https://crbug.com/427255040): This is probably leaking memory and
+      // should be fixed. No path back from Java when the owning object is
+      // destroyed/cleaned/gc'd, and Java currently has no way to tell the
+      // backing implementation of the owning object.
+      raw_ptr<std::string> web_contents_state_bytes_ptr =
+          tab_state.release_web_contents_state_bytes();
+      j_web_contents_state_buffer =
+          base::android::ScopedJavaLocalRef<jobject>::Adopt(
+              env, env->NewDirectByteBuffer(
+                       static_cast<void*>(web_contents_state_bytes_ptr->data()),
+                       web_contents_state_bytes_ptr->size()));
+    }
 
     base::Token tab_group_token(tab_state.tab_group_id_high(),
                                 tab_state.tab_group_id_low());
diff --git a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherCustomViewManagerUnitTest.java b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherCustomViewManagerUnitTest.java
index c43d4db..65154b1 100644
--- a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherCustomViewManagerUnitTest.java
+++ b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherCustomViewManagerUnitTest.java
@@ -14,10 +14,12 @@
 
 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.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -26,6 +28,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class TabSwitcherCustomViewManagerUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private TabSwitcherCustomViewManager.Delegate mDelegate;
     @Mock private View mView;
     @Mock private Runnable mBackPressRunnableMock;
@@ -34,7 +37,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mTabSwitcherCustomViewManager = new TabSwitcherCustomViewManager();
         mTabSwitcherCustomViewManager.setDelegate(mDelegate);
     }
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
index e94fe4f..e56249c 100644
--- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
+++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
@@ -142,11 +142,11 @@
     return {TriggerOutcome::kCannotShowAutofillUi, {}};
   }
 
-  if (field->Type().group() == FieldTypeGroup::kIban) {
+  if (field->Type().GetGroups().contains(FieldTypeGroup::kIban)) {
     return DryRunForIban();
-  } else if (field->Type().group() == FieldTypeGroup::kCreditCard) {
+  } else if (field->Type().GetGroups().contains(FieldTypeGroup::kCreditCard)) {
     return DryRunForCreditCard(*field, *form);
-  } else if (field->Type().group() == FieldTypeGroup::kLoyaltyCard ||
+  } else if (field->Type().GetGroups().contains(FieldTypeGroup::kLoyaltyCard) ||
              field->Type().GetLoyaltyCardType() ==
                  EMAIL_OR_LOYALTY_MEMBERSHIP_ID) {
     return DryRunForLoyaltyCard();
@@ -421,11 +421,11 @@
   }
   const FormStructure* form = manager_->FindCachedFormById(form_id);
   const AutofillField* field = form ? form->GetFieldById(field_id) : nullptr;
-  FieldTypeGroup group =
-      field ? field->Type().group() : FieldTypeGroup::kNoGroup;
-  if (group == FieldTypeGroup::kIban) {
+  const FieldTypeGroupSet groups =
+      field ? field->Type().GetGroups() : FieldTypeGroupSet{};
+  if (groups.contains(FieldTypeGroup::kIban)) {
     base::UmaHistogramEnumeration(kUmaTouchToFillIbanTriggerOutcome, outcome);
-  } else if (group == FieldTypeGroup::kLoyaltyCard) {
+  } else if (groups.contains(FieldTypeGroup::kLoyaltyCard)) {
     base::UmaHistogramEnumeration(kUmaTouchToFillLoyaltyCardTriggerOutcome,
                                   outcome);
   } else {
diff --git a/chrome/browser/touch_to_fill/common/android/java/src/org/chromium/chrome/browser/touch_to_fill/common/BottomSheetFocusHelperRoboelectricTest.java b/chrome/browser/touch_to_fill/common/android/java/src/org/chromium/chrome/browser/touch_to_fill/common/BottomSheetFocusHelperRoboelectricTest.java
index 88b8a093..09d21da 100644
--- a/chrome/browser/touch_to_fill/common/android/java/src/org/chromium/chrome/browser/touch_to_fill/common/BottomSheetFocusHelperRoboelectricTest.java
+++ b/chrome/browser/touch_to_fill/common/android/java/src/org/chromium/chrome/browser/touch_to_fill/common/BottomSheetFocusHelperRoboelectricTest.java
@@ -9,10 +9,12 @@
 import static org.mockito.Mockito.when;
 
 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.chromium.base.UserData;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -30,6 +32,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Batch(Batch.PER_CLASS)
 public class BottomSheetFocusHelperRoboelectricTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private BottomSheetFocusHelper mBottomSheetFocusHelper;
 
     @Mock private BottomSheetController mBottomSheetController;
@@ -42,7 +45,6 @@
 
     @Before
     public void setUp() throws InterruptedException {
-        MockitoAnnotations.initMocks(this);
         mBottomSheetFocusHelper =
                 new BottomSheetFocusHelper(mBottomSheetController, mWindowAndroid);
         mBottomSheetFocusHelper.setWebContentsAccessibility(mWebContentsAccessibility);
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.cc
index ad068feb..02742bb 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.cc
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.cc
@@ -20,9 +20,11 @@
 
 TouchToFillControllerWebAuthnDelegate::TouchToFillControllerWebAuthnDelegate(
     CredentialReceiver* receiver,
-    bool should_show_hybrid_option)
+    bool should_show_hybrid_option,
+    bool is_immediate)
     : credential_receiver_(receiver),
-      should_show_hybrid_option_(should_show_hybrid_option) {}
+      should_show_hybrid_option_(should_show_hybrid_option),
+      is_immediate_(is_immediate) {}
 
 TouchToFillControllerWebAuthnDelegate::
     ~TouchToFillControllerWebAuthnDelegate() = default;
@@ -34,7 +36,10 @@
 void TouchToFillControllerWebAuthnDelegate::OnCredentialSelected(
     const password_manager::UiCredential& credential,
     base::OnceClosure action_complete) {
-  NOTIMPLEMENTED();
+  CHECK(is_immediate_);
+  credential_receiver_->OnPasswordCredentialSelected(
+      {credential.username(), credential.password()});
+  std::move(action_complete).Run();
 }
 
 void TouchToFillControllerWebAuthnDelegate::OnPasskeyCredentialSelected(
@@ -62,7 +67,11 @@
 
 void TouchToFillControllerWebAuthnDelegate::OnDismiss(
     base::OnceClosure action_complete) {
-  credential_receiver_->OnWebAuthnAccountSelected(std::vector<uint8_t>());
+  if (is_immediate_) {
+    credential_receiver_->OnCredentialSelectionDeclined();
+  } else {
+    credential_receiver_->OnWebAuthnAccountSelected(std::vector<uint8_t>());
+  }
   std::move(action_complete).Run();
 }
 
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h
index f0d1fc9..368c3d4c 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h
@@ -11,6 +11,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_delegate.h"
+#include "chrome/browser/webauthn/shared_types.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace content {
@@ -37,6 +38,14 @@
     // for the selected credential.
     virtual void OnWebAuthnAccountSelected(const std::vector<uint8_t>& id) = 0;
 
+    // Provides a password credential that the user has selected.
+    virtual void OnPasswordCredentialSelected(
+        const PasswordCredentialPair& password_credential) = 0;
+
+    // Called when the user dismisses the sheet in immediate mode without
+    // having selected a credential.
+    virtual void OnCredentialSelectionDeclined() = 0;
+
     // Tells the WebAuthn Java implementation the the user has selected the
     // option for hybrid sign-in, which should be handled by the platform.
     virtual void OnHybridSignInSelected() = 0;
@@ -46,7 +55,8 @@
   };
 
   TouchToFillControllerWebAuthnDelegate(CredentialReceiver* receiver,
-                                        bool should_show_hybrid_option);
+                                        bool should_show_hybrid_option,
+                                        bool is_immediate);
 
   TouchToFillControllerWebAuthnDelegate(
       const TouchToFillControllerWebAuthnDelegate&) = delete;
@@ -82,6 +92,7 @@
   raw_ptr<CredentialReceiver> credential_receiver_ = nullptr;
 
   bool should_show_hybrid_option_;
+  bool is_immediate_;
 };
 
 #endif  // CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_MANAGER_TOUCH_TO_FILL_CONTROLLER_WEBAUTHN_DELEGATE_H_
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate_unittest.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate_unittest.cc
index 9c71a5c..1d6a324f 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate_unittest.cc
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate_unittest.cc
@@ -7,15 +7,19 @@
 #include <memory>
 #include <string>
 
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/password_manager/android/password_manager_launcher_android.h"
 #include "chrome/browser/touch_to_fill/password_manager/no_passkeys/android/no_passkeys_bottom_sheet_bridge.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller.h"
 #include "chrome/browser/webauthn/android/webauthn_request_delegate_android.h"
+#include "chrome/browser/webauthn/shared_types.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/password_manager/content/browser/mock_keyboard_replacing_surface_visibility_controller.h"
 #include "components/password_manager/core/browser/origin_credential_store.h"
 #include "components/password_manager/core/browser/passkey_credential.h"
+#include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/webauthn/android/cred_man_support.h"
 #include "components/webauthn/android/webauthn_cred_man_delegate.h"
 #include "content/public/browser/site_instance.h"
@@ -25,6 +29,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/android/window_android.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace {
 
@@ -41,6 +46,8 @@
 const std::vector<uint8_t> kCredentialId2 = {'e', 'f', 'g', 'h'};
 const std::vector<uint8_t> kUserId1 = {'1', '2', '3', '4'};
 constexpr char kUserName1[] = "John.Doe@example.com";
+const std::u16string kUserName2 = u"Jane.Doe@example.com";
+const std::u16string kPassword = u"hunter2";
 
 PasskeyCredential CreatePasskey(
     std::vector<uint8_t> credential_id = kCredentialId1,
@@ -53,19 +60,38 @@
       PasskeyCredential::Username(std::move(username)));
 }
 
-class MockWebAuthnRequestDelegateAndroid
-    : public WebAuthnRequestDelegateAndroid {
+UiCredential CreatePasswordCredential(std::u16string username = kUserName2,
+                                      std::u16string password = kPassword,
+                                      std::string origin = kExampleCom) {
+  return UiCredential(username, password, url::Origin::Create(GURL(origin)),
+                      std::string(origin),
+                      password_manager_util::GetLoginMatchType::kExact,
+                      base::Time::Now() - base::Minutes(2),
+                      UiCredential::IsBackupCredential(false));
+}
+
+class MockCredentialReceiver
+    : public TouchToFillControllerWebAuthnDelegate::CredentialReceiver {
  public:
-  explicit MockWebAuthnRequestDelegateAndroid(
-      content::WebContents* web_contents)
-      : WebAuthnRequestDelegateAndroid(web_contents) {}
-  ~MockWebAuthnRequestDelegateAndroid() override = default;
+  explicit MockCredentialReceiver(content::WebContents* web_contents)
+      : web_contents_(web_contents) {}
+  virtual ~MockCredentialReceiver() = default;
 
   MOCK_METHOD(void,
               OnWebAuthnAccountSelected,
               (const std::vector<uint8_t>& id),
               (override));
+  MOCK_METHOD(void,
+              OnPasswordCredentialSelected,
+              (const PasswordCredentialPair& password_credential),
+              (override));
+  MOCK_METHOD(void, OnCredentialSelectionDeclined, (), (override));
   MOCK_METHOD(void, OnHybridSignInSelected, (), (override));
+
+  content::WebContents* web_contents() override { return web_contents_; }
+
+ private:
+  raw_ptr<content::WebContents> web_contents_;
 };
 
 struct MockTouchToFillView : public TouchToFillView {
@@ -125,8 +151,8 @@
     window_.get()->get()->AddChild(web_contents_->GetNativeView());
     web_contents_tester()->NavigateAndCommit(GURL(kExampleCom));
 
-    request_delegate_ = std::make_unique<MockWebAuthnRequestDelegateAndroid>(
-        web_contents_.get());
+    request_delegate_ =
+        std::make_unique<MockCredentialReceiver>(web_contents_.get());
   }
 
   bool Show(base::span<const UiCredential> credentials,
@@ -145,9 +171,7 @@
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
-  MockWebAuthnRequestDelegateAndroid& request_delegate() {
-    return *request_delegate_;
-  }
+  MockCredentialReceiver& request_delegate() { return *request_delegate_; }
 
   MockTouchToFillView& view() { return *mock_view_; }
 
@@ -162,15 +186,16 @@
   }
 
   std::unique_ptr<TouchToFillControllerWebAuthnDelegate>
-  MakeTouchToFillControllerDelegate(bool should_show_hybrid_option) {
+  MakeTouchToFillControllerDelegate(bool should_show_hybrid_option,
+                                    bool is_immediate) {
     return std::make_unique<TouchToFillControllerWebAuthnDelegate>(
-        request_delegate_.get(), should_show_hybrid_option);
+        request_delegate_.get(), should_show_hybrid_option, is_immediate);
   }
 
  private:
   std::unique_ptr<content::WebContents> web_contents_;
   std::unique_ptr<ui::WindowAndroid::ScopedWindowAndroidForTesting> window_;
-  std::unique_ptr<MockWebAuthnRequestDelegateAndroid> request_delegate_;
+  std::unique_ptr<MockCredentialReceiver> request_delegate_;
   std::unique_ptr<
       password_manager::MockKeyboardReplacingSurfaceVisibilityController>
       visibility_controller_;
@@ -187,7 +212,8 @@
                    ElementsAreArray(std::vector<UiCredential>()),
                    ElementsAreArray(credentials), TouchToFillView::kNone));
   Show({}, credentials,
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/false));
 
   EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(kCredentialId1));
   touch_to_fill_controller().OnPasskeyCredentialSelected(credentials[0]);
@@ -202,7 +228,8 @@
                    ElementsAreArray(std::vector<UiCredential>()),
                    ElementsAreArray(credentials), TouchToFillView::kNone));
   Show({}, credentials,
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/false));
 
   EXPECT_CALL(request_delegate(), OnWebAuthnAccountSelected(kCredentialId2));
   touch_to_fill_controller().OnPasskeyCredentialSelected(credentials[1]);
@@ -216,13 +243,29 @@
                    ElementsAreArray(std::vector<UiCredential>()),
                    ElementsAreArray(credentials), TouchToFillView::kNone));
   Show({}, credentials,
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/false));
 
   EXPECT_CALL(request_delegate(),
               OnWebAuthnAccountSelected(std::vector<uint8_t>()));
   touch_to_fill_controller().Close();
 }
 
+TEST_F(TouchToFillControllerWebAuthnTest, ShowAndCancelImmediate) {
+  std::vector<PasskeyCredential> credentials({CreatePasskey()});
+
+  EXPECT_CALL(view(),
+              Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
+                   ElementsAreArray(std::vector<UiCredential>()),
+                   ElementsAreArray(credentials), TouchToFillView::kNone));
+  Show({}, credentials,
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/true));
+
+  EXPECT_CALL(request_delegate(), OnCredentialSelectionDeclined());
+  touch_to_fill_controller().Close();
+}
+
 TEST_F(TouchToFillControllerWebAuthnTest, ShowAndSelectHybrid) {
   std::vector<PasskeyCredential> credentials({CreatePasskey()});
 
@@ -231,7 +274,8 @@
                            ElementsAreArray(credentials),
                            TouchToFillView::kShouldShowHybridOption));
   Show({}, credentials,
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/true));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/true,
+                                         /*is_immediate=*/false));
   EXPECT_CALL(request_delegate(), OnHybridSignInSelected());
   touch_to_fill_controller().OnHybridSignInSelected();
 }
@@ -244,7 +288,8 @@
   EXPECT_CALL(view(), Show).Times(0);
   EXPECT_CALL(jni_delegate(), Show).Times(1);
   Show({}, {},
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/false));
 }
 
 TEST_F(TouchToFillControllerWebAuthnTest, ShowNothingIfGpmInCredMan) {
@@ -254,5 +299,24 @@
   EXPECT_CALL(view(), Show).Times(0);
   EXPECT_CALL(jni_delegate(), Show).Times(0);
   Show({}, {},
-       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false));
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/false));
+}
+
+TEST_F(TouchToFillControllerWebAuthnTest, ShowPasswordForImmediate) {
+  UiCredential password_credential = CreatePasswordCredential();
+  std::vector<PasskeyCredential> credentials({CreatePasskey()});
+  std::vector<UiCredential> passwords({password_credential});
+
+  EXPECT_CALL(view(),
+              Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
+                   ElementsAreArray(passwords), ElementsAreArray(credentials),
+                   TouchToFillView::kNone));
+  Show(passwords, credentials,
+       MakeTouchToFillControllerDelegate(/*should_show_hybrid_option=*/false,
+                                         /*is_immediate=*/true));
+
+  PasswordCredentialPair expected = {kUserName2, kPassword};
+  EXPECT_CALL(request_delegate(), OnPasswordCredentialSelected(expected));
+  touch_to_fill_controller().OnCredentialSelected(password_credential);
 }
diff --git a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java
index 84c6fc6..d84907f 100644
--- a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java
+++ b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java
@@ -17,7 +17,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Batch;
@@ -38,6 +39,8 @@
 @Batch(Batch.PER_CLASS)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public final class AutoTranslateSnackbarControllerJavaTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Rule
     public FreshCtaTransitTestRule mActivityTestRule =
             ChromeTransitTestRules.freshChromeTabbedActivityRule();
@@ -52,8 +55,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mPage = mActivityTestRule.startOnBlankPage();
         mSnackbarManager = mPage.getActivity().getSnackbarManager();
         WeakReference<Activity> weakReference = new WeakReference<>(mPage.getActivity());
diff --git a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerTest.java b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerTest.java
index 30e6ea12..9d13488 100644
--- a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerTest.java
+++ b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerTest.java
@@ -10,11 +10,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.UnownedUserDataHost;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -27,6 +29,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 public final class AutoTranslateSnackbarControllerTest {
     private static final int NATIVE_SNACKBAR_VIEW = 1001;
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock AutoTranslateSnackbarController.Natives mMockJni;
 
     @Mock private WebContents mWebContents;
@@ -34,7 +37,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         AutoTranslateSnackbarControllerJni.setInstanceForTesting(mMockJni);
     }
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d14a2add..0543f3c 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -85,11 +85,8 @@
     "simple_message_box_internal.cc",
     "simple_message_box_internal.h",
     "startup/bad_flags_prompt.cc",
-    "startup/bad_flags_prompt.h",
     "startup/bidding_and_auction_consented_debugging_infobar_delegate.cc",
-    "startup/bidding_and_auction_consented_debugging_infobar_delegate.h",
     "startup/test_third_party_cookie_phaseout_infobar_delegate.cc",
-    "startup/test_third_party_cookie_phaseout_infobar_delegate.h",
     "status_bubble.h",
     "storage_pressure_bubble.h",
     "tab_dialogs.cc",
@@ -381,6 +378,7 @@
     "//chrome/browser/ui/search_engines",
     "//chrome/browser/ui/serial",
     "//chrome/browser/ui/serial:impl",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/startup/default_browser_prompt",
     "//chrome/browser/ui/startup/default_browser_prompt:impl",
     "//chrome/browser/ui/sync",
@@ -1089,22 +1087,13 @@
       "singleton_tabs.cc",
       "singleton_tabs.h",
       "startup/automation_infobar_delegate.cc",
-      "startup/automation_infobar_delegate.h",
       "startup/google_api_keys_infobar_delegate.cc",
-      "startup/google_api_keys_infobar_delegate.h",
       "startup/infobar_utils.cc",
-      "startup/infobar_utils.h",
       "startup/launch_mode_recorder.cc",
-      "startup/launch_mode_recorder.h",
       "startup/obsolete_system_infobar_delegate.cc",
-      "startup/obsolete_system_infobar_delegate.h",
       "startup/startup_browser_creator.cc",
-      "startup/startup_browser_creator.h",
       "startup/startup_browser_creator_impl.cc",
-      "startup/startup_browser_creator_impl.h",
       "startup/startup_tab_provider.cc",
-      "startup/startup_tab_provider.h",
-      "startup/startup_types.h",
       "tab_modal_confirm_dialog_delegate.cc",
       "tab_modal_confirm_dialog_delegate.h",
       "tabs/glic_actor_task_icon_controller.cc",
@@ -1489,10 +1478,7 @@
     }
 
     if (is_chrome_for_testing) {
-      sources += [
-        "startup/chrome_for_testing_infobar_delegate.cc",
-        "startup/chrome_for_testing_infobar_delegate.h",
-      ]
+      sources += [ "startup/chrome_for_testing_infobar_delegate.cc" ]
     }
 
     # Non-android deps for "ui" target.
@@ -2894,7 +2880,6 @@
       "passwords/password_cross_domain_confirmation_popup_controller_impl.h",
       "passwords/password_cross_domain_confirmation_popup_controller_interface.h",
       "startup/web_app_startup_utils.cc",
-      "startup/web_app_startup_utils.h",
       "views/autofill/payments/webauthn_dialog_view.cc",
       "views/autofill/payments/webauthn_dialog_view.h",
       "views/close_bubble_on_tab_activation_helper.cc",
@@ -2942,9 +2927,7 @@
   if (is_win || is_mac || is_linux) {
     sources += [
       "startup/first_run_service.cc",
-      "startup/first_run_service.h",
       "startup/web_app_info_recorder_utils.cc",
-      "startup/web_app_info_recorder_utils.h",
       "views/media_preview/active_devices_media_coordinator.cc",
       "views/media_preview/active_devices_media_coordinator.h",
       "views/media_preview/camera_preview/camera_coordinator.cc",
@@ -3317,9 +3300,7 @@
       "network_profile_bubble.cc",
       "network_profile_bubble.h",
       "startup/credential_provider_signin_dialog_win.cc",
-      "startup/credential_provider_signin_dialog_win.h",
       "startup/credential_provider_signin_info_fetcher_win.cc",
-      "startup/credential_provider_signin_info_fetcher_win.h",
       "views/apps/app_window_desktop_native_widget_aura_win.cc",
       "views/apps/app_window_desktop_native_widget_aura_win.h",
       "views/apps/app_window_desktop_window_tree_host_win.cc",
@@ -3990,6 +3971,8 @@
       "views/intent_picker_bubble_view.h",
       "views/javascript_tab_modal_dialog_view_views.cc",
       "views/javascript_tab_modal_dialog_view_views.h",
+      "views/location_bar/ai_mode_page_action_icon_view.cc",
+      "views/location_bar/ai_mode_page_action_icon_view.h",
       "views/location_bar/content_setting_image_view.cc",
       "views/location_bar/content_setting_image_view.h",
       "views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.cc",
diff --git a/chrome/browser/ui/actions/chrome_action_id.h b/chrome/browser/ui/actions/chrome_action_id.h
index 96bca7d..a798449 100644
--- a/chrome/browser/ui/actions/chrome_action_id.h
+++ b/chrome/browser/ui/actions/chrome_action_id.h
@@ -333,6 +333,7 @@
     IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP) \
   E(kActionContentContextLensRegionSearch, \
     IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH) \
+  E(kActionAiMode) \
   E(kActionContentContextWebRegionSearch, \
     IDC_CONTENT_CONTEXT_WEB_REGION_SEARCH) \
   E(kActionContentContextGeneratePassword, \
diff --git a/chrome/browser/ui/android/default_browser_promo/java/src/org/chromium/chrome/browser/ui/default_browser_promo/DefaultBrowserPromoManagerTest.java b/chrome/browser/ui/android/default_browser_promo/java/src/org/chromium/chrome/browser/ui/default_browser_promo/DefaultBrowserPromoManagerTest.java
index b1e23ca1..dc76c0a1f 100644
--- a/chrome/browser/ui/android/default_browser_promo/java/src/org/chromium/chrome/browser/ui/default_browser_promo/DefaultBrowserPromoManagerTest.java
+++ b/chrome/browser/ui/android/default_browser_promo/java/src/org/chromium/chrome/browser/ui/default_browser_promo/DefaultBrowserPromoManagerTest.java
@@ -16,11 +16,13 @@
 import android.content.Intent;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Batch;
@@ -34,6 +36,7 @@
 @Batch(Batch.UNIT_TESTS)
 public class DefaultBrowserPromoManagerTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock WindowAndroid mWindowAndroid;
     @Mock Activity mActivity;
     @Mock RoleManager mRoleManager;
@@ -43,7 +46,6 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
         doReturn(mRoleManager).when(mActivity).getSystemService(Context.ROLE_SERVICE);
         doReturn(mIntent).when(mRoleManager).createRequestRoleIntent(RoleManager.ROLE_BROWSER);
     }
diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.cc b/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.cc
index c511ecc..b4c19fe4 100644
--- a/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.cc
+++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.cc
@@ -65,6 +65,25 @@
       *reinterpret_cast<input::NativeWebKeyboardEvent*>(nativeKeyEvent));
 }
 
+void ExclusiveAccessManagerAndroid::RequestKeyboardLock(
+    JNIEnv* env,
+    const jni_zero::JavaRef<jobject>& jweb_contents,
+    bool escKeyLocked) {
+  content::WebContents* wc =
+      content::WebContents::FromJavaWebContents(jweb_contents);
+  DCHECK_NE(wc, nullptr);
+  eam_.keyboard_lock_controller()->RequestKeyboardLock(wc, escKeyLocked);
+}
+
+void ExclusiveAccessManagerAndroid::CancelKeyboardLockRequest(
+    JNIEnv* env,
+    const jni_zero::JavaRef<jobject>& jweb_contents) {
+  content::WebContents* wc =
+      content::WebContents::FromJavaWebContents(jweb_contents);
+  DCHECK_NE(wc, nullptr);
+  eam_.keyboard_lock_controller()->CancelKeyboardLockRequest(wc);
+}
+
 void ExclusiveAccessManagerAndroid::Destroy(JNIEnv* env) {
   delete this;
 }
diff --git a/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.h b/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.h
index 7949ad9..80f825e 100644
--- a/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.h
+++ b/chrome/browser/ui/android/exclusive_access/exclusive_access_manager_android.h
@@ -42,6 +42,14 @@
 
   bool PreHandleKeyboardEvent(JNIEnv* env, jlong nativeKeyEvent);
 
+  void RequestKeyboardLock(JNIEnv* env,
+                           const jni_zero::JavaRef<jobject>& jweb_contents,
+                           bool escKeyLocked);
+
+  void CancelKeyboardLockRequest(
+      JNIEnv* env,
+      const jni_zero::JavaRef<jobject>& jweb_contents);
+
  private:
   // Our global reference to the Java ExclusiveAccessManagerAndroid.
   base::android::ScopedJavaGlobalRef<jobject> j_eam_;
diff --git a/chrome/browser/ui/android/multiwindow/BUILD.gn b/chrome/browser/ui/android/multiwindow/BUILD.gn
index b1cbb00..e91327a 100644
--- a/chrome/browser/ui/android/multiwindow/BUILD.gn
+++ b/chrome/browser/ui/android/multiwindow/BUILD.gn
@@ -15,6 +15,7 @@
     "java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceIphController.java",
     "java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java",
     "java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceState.java",
+    "java/src/org/chromium/chrome/browser/multiwindow/RenameWindowDialogView.java",
     "java/src/org/chromium/chrome/browser/multiwindow/TargetSelectorCoordinator.java",
     "java/src/org/chromium/chrome/browser/multiwindow/TargetSelectorItemProperties.java",
     "java/src/org/chromium/chrome/browser/multiwindow/TargetSelectorItemViewBinder.java",
@@ -73,6 +74,7 @@
     "java/res/layout/instance_switcher_item.xml",
     "java/res/layout/instance_switcher_item_v2.xml",
     "java/res/layout/instance_switcher_list.xml",
+    "java/res/layout/rename_window_dialog.xml",
     "java/res/layout/target_selector_dialog.xml",
     "java/res/layout/target_selector_dialog_v2.xml",
     "java/res/values/colors.xml",
diff --git a/chrome/browser/ui/android/multiwindow/java/res/layout/rename_window_dialog.xml b/chrome/browser/ui/android/multiwindow/java/res/layout/rename_window_dialog.xml
new file mode 100644
index 0000000..71a5aa1
--- /dev/null
+++ b/chrome/browser/ui/android/multiwindow/java/res/layout/rename_window_dialog.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<org.chromium.chrome.browser.multiwindow.RenameWindowDialogView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/dialog_bg_no_shadow">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <androidx.appcompat.widget.DialogTitle
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:ellipsize="end"
+            android:paddingHorizontal="@dimen/dialog_padding_sides"
+            android:paddingTop="@dimen/dialog_padding_sides"
+            android:textAppearance="@style/TextAppearance.AlertDialogTitleStyle" />
+
+        <com.google.android.material.textfield.TextInputLayout
+            android:id="@+id/new_window_title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
+            android:layout_marginVertical="@dimen/rename_window_dialog_input_text_vertical_margin">
+
+            <com.google.android.material.textfield.TextInputEditText
+                android:id="@+id/title_input_text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:imeOptions="flagNoExtractUi"
+                android:inputType="textCapSentences|textAutoCorrect"
+                android:selectAllOnFocus="true" />
+        </com.google.android.material.textfield.TextInputLayout>
+
+
+        <org.chromium.components.browser_ui.widget.DualControlLayout
+            android:id="@+id/button_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingVertical="?attr/dualControlLayoutVerticalPadding"
+            android:paddingHorizontal="?attr/dualControlLayoutHorizontalPadding"
+            app:stackedMargin="@dimen/button_bar_stacked_margin"
+            app:buttonAlignment="end">
+
+            <org.chromium.ui.widget.ButtonCompat
+                android:id="@+id/positive_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/save"
+                style="?attr/buttonBarPositiveButtonStyle"/>
+
+            <org.chromium.ui.widget.ButtonCompat
+                android:id="@+id/negative_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/cancel"
+                style="?attr/buttonBarNegativeButtonStyle" />
+        </org.chromium.components.browser_ui.widget.DualControlLayout>
+
+    </LinearLayout>
+</org.chromium.chrome.browser.multiwindow.RenameWindowDialogView>
\ No newline at end of file
diff --git a/chrome/browser/ui/android/multiwindow/java/res/values/dimens.xml b/chrome/browser/ui/android/multiwindow/java/res/values/dimens.xml
index f8b28e3..435624b 100644
--- a/chrome/browser/ui/android/multiwindow/java/res/values/dimens.xml
+++ b/chrome/browser/ui/android/multiwindow/java/res/values/dimens.xml
@@ -13,4 +13,5 @@
     <dimen name="instance_switcher_dialog_list_item_padding">2dp</dimen>
     <dimen name="instance_switcher_dialog_max_info_top_padding">16dp</dimen>
     <dimen name="instance_switcher_dialog_favicon_start_margin">16dp</dimen>
+    <dimen name="rename_window_dialog_input_text_vertical_margin">16dp</dimen>
 </resources>
diff --git a/chrome/browser/ui/android/multiwindow/java/res/values/styles.xml b/chrome/browser/ui/android/multiwindow/java/res/values/styles.xml
index 98719721..b67bdaa 100644
--- a/chrome/browser/ui/android/multiwindow/java/res/values/styles.xml
+++ b/chrome/browser/ui/android/multiwindow/java/res/values/styles.xml
@@ -26,4 +26,15 @@
     <style name="TextAppearance.TextLarge.Secondary.InstanceSwitcherItem" parent="TextAppearance.TextLarge.Secondary">
         <item name="android:textColor">@color/instance_switcher_item_secondary_text_color_list</item>
     </style>
+
+    <style name="Theme.Chromium.Multiwindow.RenameWindowDialog" parent="ThemeOverlay.Material3.Dialog">
+        <item name="android:windowFrame">@null</item>
+        <item name="android:backgroundDimAmount">0.65</item>
+        <item name="android:windowSoftInputMode">adjustResize|stateHidden</item>
+        <item name="buttonBarPositiveButtonStyle">@style/FilledButton</item>
+        <item name="buttonBarNegativeButtonStyle">@style/TextButton</item>
+        <item name="dualControlLayoutVerticalPadding">@dimen/modal_dialog_control_vertical_padding_filled</item>
+        <item name="dualControlLayoutHorizontalPadding">@dimen/modal_dialog_control_horizontal_padding_filled</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+    </style>
 </resources>
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
index a4113ae..29342f9 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
@@ -12,9 +12,13 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Resources;
+import android.text.TextUtils;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.Window;
+import android.view.WindowManager;
 import android.widget.CheckBox;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
@@ -31,6 +35,8 @@
 import com.google.android.material.tabs.TabLayout;
 import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
 import com.google.android.material.tabs.TabLayout.Tab;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
 
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordUserAction;
@@ -61,6 +67,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Coordinator to construct the instance switcher dialog. TODO: Resolve various inconsistencies that
@@ -84,6 +91,7 @@
     private final Context mContext;
     private final Callback<InstanceInfo> mOpenCallback;
     private final Callback<InstanceInfo> mCloseCallback;
+    private final Callback<Pair<Integer, String>> mRenameWindowCallback;
     private final Runnable mNewWindowAction;
     private final ModalDialogManager mModalDialogManager;
     private final int mMaxInstanceCount;
@@ -116,6 +124,7 @@
      * @param iconBridge An object that fetches favicons from local DB.
      * @param openCallback Callback to invoke to open a chosen instance.
      * @param closeCallback Callback to invoke to close a chosen instance.
+     * @param renameWindowCallback Callback to invoke to rename a chosen instance.
      * @param newWindowAction Runnable to invoke to open a new window.
      * @param maxInstanceCount The maximum number of instances whose state can be persisted.
      * @param instanceInfo List of {@link InstanceInfo} for available Chrome instances.
@@ -126,6 +135,7 @@
             LargeIconBridge iconBridge,
             Callback<InstanceInfo> openCallback,
             Callback<InstanceInfo> closeCallback,
+            Callback<Pair<Integer, String>> renameWindowCallback,
             Runnable newWindowAction,
             int maxInstanceCount,
             List<InstanceInfo> instanceInfo) {
@@ -135,6 +145,7 @@
                         iconBridge,
                         openCallback,
                         closeCallback,
+                        renameWindowCallback,
                         newWindowAction,
                         maxInstanceCount)
                 .show(instanceInfo);
@@ -146,12 +157,14 @@
             LargeIconBridge iconBridge,
             Callback<InstanceInfo> openCallback,
             Callback<InstanceInfo> closeCallback,
+            Callback<Pair<Integer, String>> renameWindowCallback,
             Runnable newWindowAction,
             int maxInstanceCount) {
         mContext = context;
         mModalDialogManager = modalDialogManager;
         mOpenCallback = openCallback;
         mCloseCallback = closeCallback;
+        mRenameWindowCallback = renameWindowCallback;
         mUiUtils = new UiUtils(mContext, iconBridge);
         mNewWindowAction = newWindowAction;
         mMaxInstanceCount = maxInstanceCount;
@@ -454,13 +467,23 @@
 
     private void buildMoreMenu(PropertyModel.Builder builder, InstanceInfo item) {
         ModelList moreMenu = new ModelList();
-        moreMenu.add(buildSimpleMenuItem(R.string.instance_switcher_close_window));
+        if (UiUtils.isInstanceSwitcherV2Enabled()) {
+            moreMenu.add(buildSimpleMenuItem(R.string.instance_switcher_name_window));
+            moreMenu.add(buildSimpleMenuItem(R.string.close));
+        } else {
+            moreMenu.add(buildSimpleMenuItem(R.string.instance_switcher_close_window));
+        }
+
         ListMenu.Delegate moreMenuDelegate =
                 (model) -> {
                     int textId = model.get(ListMenuItemProperties.TITLE_ID);
-                    if (textId == R.string.instance_switcher_close_window) {
+                    if (textId == R.string.instance_switcher_close_window
+                            || textId == R.string.close) {
                         closeWindow(item);
                     }
+                    if (textId == R.string.instance_switcher_name_window) {
+                        showNameWindowDialog(item);
+                    }
                 };
         BasicListMenu listMenu =
                 BrowserUiListMenuUtils.getBasicListMenu(mContext, moreMenu, moreMenuDelegate);
@@ -686,6 +709,58 @@
         dialog.show();
     }
 
+    private void showNameWindowDialog(InstanceInfo item) {
+        int style = R.style.Theme_Chromium_Multiwindow_RenameWindowDialog;
+        Dialog dialog = new Dialog(mContext, style);
+        dialog.setCanceledOnTouchOutside(true);
+        dialog.setContentView(R.layout.rename_window_dialog);
+
+        Resources res = mContext.getResources();
+        ((TextView) dialog.findViewById(R.id.title))
+                .setText(res.getString(R.string.instance_switcher_name_window_confirm_header));
+
+        TextInputLayout textInputLayout = dialog.findViewById(R.id.new_window_title);
+        TextInputEditText editText = dialog.findViewById(R.id.title_input_text);
+        editText.setText(mUiUtils.getItemTitle(item));
+        editText.requestFocus();
+        Window window = assumeNonNull(dialog.getWindow());
+        window.setSoftInputMode(
+                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
+                        | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
+        TextView positiveButton = dialog.findViewById(R.id.positive_button);
+        positiveButton.setOnClickListener(
+                v -> {
+                    String newTitle = Objects.toString(editText.getText(), "").trim();
+                    if (!TextUtils.isEmpty(newTitle)) {
+                        mRenameWindowCallback.onResult(new Pair<>(item.instanceId, newTitle));
+                        ModelList list =
+                                mIsInactiveListShowing ? mInactiveModelList : mActiveModelList;
+                        for (ListItem listItem : list) {
+                            if (listItem.model.get(InstanceSwitcherItemProperties.INSTANCE_ID)
+                                    == item.instanceId) {
+                                listItem.model.set(InstanceSwitcherItemProperties.TITLE, newTitle);
+                                break;
+                            }
+                        }
+                        dialog.dismiss();
+                    } else {
+                        textInputLayout.setError(
+                                mContext.getString(
+                                        R.string.instance_switcher_name_window_missing_title));
+                        textInputLayout.requestFocus();
+                    }
+                });
+
+        TextView negativeButton = dialog.findViewById(R.id.negative_button);
+        negativeButton.setOnClickListener(
+                v -> {
+                    dialog.dismiss();
+                });
+
+        dialog.show();
+    }
+
     private void updateTabTitle(int numActiveInstances, int numInactiveInstances) {
         if (mTabHeaderRow == null) return;
         Tab activeTab = mTabHeaderRow.getTabAt(0);
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
index 8bb7b6c..9ae97cd 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
@@ -7,6 +7,7 @@
 import static androidx.test.espresso.Espresso.onData;
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.replaceText;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
 import static androidx.test.espresso.matcher.RootMatchers.isDialog;
@@ -26,7 +27,9 @@
 import static org.hamcrest.Matchers.anything;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
 
+import android.util.Pair;
 import android.view.View;
 
 import androidx.recyclerview.widget.RecyclerView;
@@ -132,6 +135,7 @@
                             openCallback,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -158,6 +162,7 @@
                             openCallback,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -210,6 +215,7 @@
                             openCallback,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -264,6 +270,7 @@
                             openCallback,
                             closeCallback,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -318,6 +325,7 @@
                             openCallback,
                             closeCallback,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -369,6 +377,7 @@
                             null,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -419,6 +428,7 @@
                             openCallback,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -468,6 +478,7 @@
                             mIconBridge,
                             null,
                             null,
+                            null,
                             itemClickCallbackHelper::notifyCalled,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
@@ -495,6 +506,7 @@
                             null,
                             closeCallback,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -536,6 +548,7 @@
                             null,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -578,6 +591,7 @@
                             mIconBridge,
                             null,
                             closeCallback,
+                            null,
                             newWindowCallbackHelper::notifyCalled,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
@@ -640,6 +654,7 @@
                             mIconBridge,
                             null,
                             closeCallback,
+                            null,
                             newWindowCallbackHelper::notifyCalled,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
@@ -730,6 +745,7 @@
                             openCallback,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -790,6 +806,7 @@
                             null,
                             closeCallback,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -818,6 +835,7 @@
                             null,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -861,6 +879,7 @@
                             null,
                             null,
                             null,
+                            null,
                             MAX_INSTANCE_COUNT,
                             Arrays.asList(instances));
                 });
@@ -892,6 +911,177 @@
                                                         isDisplayed())))));
     }
 
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.INSTANCE_SWITCHER_V2)
+    public void testRenameWindow() throws Exception {
+        InstanceInfo[] instances =
+                createPersistedInstances(
+                        /* numActiveInstances= */ 3, /* numInactiveInstances= */ 0);
+        final CallbackHelper renameCallbackHelper = new CallbackHelper();
+        final int renameCallbackCount = renameCallbackHelper.getCallCount();
+        Callback<Pair<Integer, String>> renameCallback =
+                (result) -> {
+                    renameCallbackHelper.notifyCalled();
+                };
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    InstanceSwitcherCoordinator.showDialog(
+                            mActivityTestRule.getActivity(),
+                            mModalDialogManager,
+                            mIconBridge,
+                            null, // openCallback
+                            null, // closeCallback
+                            renameCallback,
+                            null, // newWindowAction
+                            MAX_INSTANCE_COUNT,
+                            Arrays.asList(instances));
+                });
+
+        // Click on the 'more' button for the second instance.
+        clickMoreButtonAtPosition(1, R.id.active_instance_list);
+
+        // Check that "Name" is an option and click it.
+        onView(withText(R.string.instance_switcher_name_window))
+                .inRoot(withDecorView(withClassName(containsString("Popup"))))
+                .check(matches(isDisplayed()))
+                .perform(click());
+
+        // Check that the "Name this window" dialog is shown.
+        Thread.sleep(5000);
+        onView(withText(R.string.instance_switcher_name_window_confirm_header))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()));
+
+        // Enter a new name and save.
+        final String newName = "test name";
+        onView(withId(R.id.title_input_text)).inRoot(isDialog()).perform(replaceText(newName));
+        onView(withText(R.string.save))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()))
+                .perform(click());
+
+        Thread.sleep(5000);
+
+        // Check that the instance title is updated in the list.
+        onView(withId(R.id.active_instance_list))
+                .inRoot(isDialog())
+                .check(matches(atPosition(1, hasDescendant(withText(newName)))));
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.INSTANCE_SWITCHER_V2)
+    public void testRenameWindowWithEmptyName() throws Exception {
+        InstanceInfo[] instances =
+                createPersistedInstances(
+                        /* numActiveInstances= */ 3, /* numInactiveInstances= */ 0);
+        final CallbackHelper renameCallbackHelper = new CallbackHelper();
+        Callback<Pair<Integer, String>> renameCallback =
+                (result) -> {
+                    renameCallbackHelper.notifyCalled();
+                };
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    InstanceSwitcherCoordinator.showDialog(
+                            mActivityTestRule.getActivity(),
+                            mModalDialogManager,
+                            mIconBridge,
+                            null, // openCallback
+                            null, // closeCallback
+                            renameCallback,
+                            null, // newWindowAction
+                            MAX_INSTANCE_COUNT,
+                            Arrays.asList(instances));
+                });
+
+        // Click on the 'more' button for the second instance.
+        clickMoreButtonAtPosition(1, R.id.active_instance_list);
+
+        // Check that "Name" is an option and click it.
+        onView(withText(R.string.instance_switcher_name_window))
+                .inRoot(withDecorView(withClassName(containsString("Popup"))))
+                .check(matches(isDisplayed()))
+                .perform(click());
+
+        // Check that the "Name this window" dialog is shown.
+        onView(withText(R.string.instance_switcher_name_window_confirm_header))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()));
+
+        // Enter an empty name and save.
+        onView(withId(R.id.title_input_text)).inRoot(isDialog()).perform(replaceText(""));
+        onView(withText(R.string.save)).inRoot(isDialog()).perform(click());
+
+        // Check that the error message is shown.
+        CriteriaHelper.pollInstrumentationThread(
+                () -> {
+                    try {
+                        onView(withText(R.string.instance_switcher_name_window_missing_title))
+                                .inRoot(isDialog())
+                                .check(matches(isDisplayed()));
+                        return true;
+                    } catch (AssertionError e) {
+                        return false;
+                    }
+                });
+
+        // Check that the rename callback was not called.
+        assertEquals(0, renameCallbackHelper.getCallCount());
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.INSTANCE_SWITCHER_V2)
+    public void testCancelRenameWindow() throws Exception {
+        InstanceInfo[] instances =
+                createPersistedInstances(
+                        /* numActiveInstances= */ 3, /* numInactiveInstances= */ 0);
+        final CallbackHelper renameCallbackHelper = new CallbackHelper();
+        Callback<Pair<Integer, String>> renameCallback =
+                (result) -> {
+                    renameCallbackHelper.notifyCalled();
+                };
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    InstanceSwitcherCoordinator.showDialog(
+                            mActivityTestRule.getActivity(),
+                            mModalDialogManager,
+                            mIconBridge,
+                            null, // openCallback
+                            null, // closeCallback
+                            renameCallback,
+                            null, // newWindowAction
+                            MAX_INSTANCE_COUNT,
+                            Arrays.asList(instances));
+                });
+
+        // Click on the 'more' button for the second instance.
+        clickMoreButtonAtPosition(1, R.id.active_instance_list);
+
+        // Check that "Name" is an option and click it.
+        onView(withText(R.string.instance_switcher_name_window))
+                .inRoot(withDecorView(withClassName(containsString("Popup"))))
+                .check(matches(isDisplayed()))
+                .perform(click());
+
+        // Check that the "Name this window" dialog is shown.
+        Thread.sleep(500);
+        onView(withText(R.string.instance_switcher_name_window_confirm_header))
+                .inRoot(isDialog())
+                .check(matches(isDisplayed()));
+
+        // Click the cancel button.
+        onView(withText(R.string.cancel)).inRoot(isDialog()).perform(click());
+        Thread.sleep(500);
+
+        // Check that the rename callback was not called.
+        assertEquals(0, renameCallbackHelper.getCallCount());
+    }
+
     private InstanceInfo[] createPersistedInstances(
             int numActiveInstances, int numInactiveInstances) {
         int totalInstances = numActiveInstances + numInactiveInstances;
@@ -975,7 +1165,7 @@
                                         v.performClick();
                                     }
                                 }));
-        onView(withText(R.string.instance_switcher_close_window))
+        onView(withText(R.string.close))
                 .inRoot(withDecorView(withClassName(containsString("Popup"))))
                 .perform(click());
         onView(withText(R.string.instance_switcher_close_confirm_header))
@@ -1004,4 +1194,28 @@
             }
         };
     }
+
+    private void clickMoreButtonAtPosition(int instanceIndex, int instanceListId) {
+        onView(withId(instanceListId))
+                .inRoot(isDialog())
+                .perform(
+                        actionOnItemAtPosition(
+                                instanceIndex,
+                                new ViewAction() {
+                                    @Override
+                                    public Matcher<View> getConstraints() {
+                                        return isDisplayed();
+                                    }
+
+                                    @Override
+                                    public String getDescription() {
+                                        return "Click on the more button.";
+                                    }
+
+                                    @Override
+                                    public void perform(UiController uiController, View view) {
+                                        view.findViewById(R.id.more).performClick();
+                                    }
+                                }));
+    }
 }
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/RenameWindowDialogView.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/RenameWindowDialogView.java
new file mode 100644
index 0000000..38622c32
--- /dev/null
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/RenameWindowDialogView.java
@@ -0,0 +1,36 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.multiwindow;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.widget.ScrollView;
+
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
+
+/** Content view class for rename window dialog. */
+@NullMarked
+public class RenameWindowDialogView extends ScrollView {
+    public RenameWindowDialogView(Context context) {
+        super(context);
+    }
+
+    public RenameWindowDialogView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Adjust the width to appropriately fit the dialog content in the parent view.
+        Resources res = getResources();
+        int screenWidth = res.getDisplayMetrics().widthPixels;
+        int defaultWidth = MeasureSpec.getSize(widthMeasureSpec);
+        int sideMargin = res.getDimensionPixelSize(R.dimen.confirmation_dialog_side_margin) * 2;
+        int width = Math.min(defaultWidth, screenWidth - sideMargin);
+        super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightMeasureSpec);
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
index d2952bcf..126d04d5 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
@@ -9,7 +9,6 @@
 
 import android.app.Activity;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.text.Spannable;
 
@@ -81,7 +80,6 @@
     private @Mock SuggestionHost mSuggestionHost;
     private @Mock UrlBarEditingTextStateProvider mUrlStateProvider;
     private @Mock OmniboxImageSupplier mImageSupplier;
-    private @Mock Bitmap mBitmap;
     private @Mock AutocompleteInput mInput;
 
     private AnswerSuggestionProcessor mProcessor;
@@ -206,7 +204,7 @@
     public void setUp() {
         mDefaultLocale = Locale.getDefault();
         mContext = Robolectric.buildActivity(Activity.class).setup().get();
-        mContext.setTheme(org.chromium.chrome.R.style.Theme_BrowserUI_DayNight);
+        mContext.setTheme(R.style.Theme_BrowserUI_DayNight);
         mProcessor =
                 new AnswerSuggestionProcessor(
                         mContext, mSuggestionHost, mUrlStateProvider, Optional.of(mImageSupplier));
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java
index a91b420..8ea06e6 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java
@@ -411,7 +411,7 @@
                             TestAccounts.AADC_UNRESOLVED_ACCOUNT.getId());
                 });
 
-        onViewWaiting(withId(org.chromium.chrome.R.id.button_secondary));
+        onViewWaiting(withId(R.id.button_secondary));
 
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index e0b6ec8..2aa2121 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -5627,6 +5627,15 @@
           =1 {1 tab}
           other {# tabs}}
       </message>
+      <message name="IDS_INSTANCE_SWITCHER_NAME_WINDOW" desc="The menu item for the 3-dot more button to name the window.">
+        Name
+      </message>
+       <message name="IDS_INSTANCE_SWITCHER_NAME_WINDOW_CONFIRM_HEADER" desc="The header of multi-instance switcher dialog confirming to name the selected window.">
+        Name this window
+      </message>
+       <message name="IDS_INSTANCE_SWITCHER_NAME_WINDOW_MISSING_TITLE" desc="Error message appearing when a user tries to rename a window without a title. s[CHAR_LIMIT=32]">
+        Title required
+      </message>
       <message name="IDS_INSTANCE_SWITCHER_CLOSE_WINDOW" desc="The menu item for the 3-dot more button to close the instance.">
         Close window
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW.png.sha1
new file mode 100644
index 0000000..1f918207
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW.png.sha1
@@ -0,0 +1 @@
+4112ff2f91603e3bccfc748153b11bfff512877d
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_CONFIRM_HEADER.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_CONFIRM_HEADER.png.sha1
new file mode 100644
index 0000000..c61638f
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_CONFIRM_HEADER.png.sha1
@@ -0,0 +1 @@
+1c6078b5500ec96eae78315b707f4e15590074d1
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_MISSING_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_MISSING_TITLE.png.sha1
new file mode 100644
index 0000000..589e619
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_INSTANCE_SWITCHER_NAME_WINDOW_MISSING_TITLE.png.sha1
@@ -0,0 +1 @@
+6e68b7a1b762c1a495f59b3666f3bf7007cceac8
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
index 9b27174e..edd7917 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
@@ -31,6 +31,7 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Features.DisableFeatures;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
 import org.chromium.chrome.browser.omnibox.NewTabPageDelegate;
@@ -104,8 +105,7 @@
         verify(mTabStripHeightSupplier).addObserver(captor.capture());
         Callback<Integer> tabStripHeightChangeCallback = captor.getValue();
         int newTabStripHeight =
-                mContext.getResources()
-                        .getDimensionPixelSize(org.chromium.chrome.R.dimen.tab_strip_height);
+                mContext.getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
         tabStripHeightChangeCallback.onResult(newTabStripHeight);
         assertEquals(
                 "Scrim top margin should be updated when tab strip height changes.",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index 7fbf64a..2c640d84 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -585,7 +585,7 @@
             // setTabSwitcherMode()/onTabSwitcherTransitionFinished() ->
             // updateVisualsForLocationBarState()
             if (!isInTabSwitcherMode()) {
-                invokeTransition(false);
+                invokeTransition();
             }
             if (!changed) return;
         } else {
@@ -866,7 +866,7 @@
             updateLocationBarForNtp(mVisualState, urlHasFocus());
         }
         updateUrlExpansionFraction();
-        invokeTransition(false);
+        invokeTransition();
     }
 
     /**
@@ -977,7 +977,7 @@
     private void setUrlFocusChangeFraction(float fraction) {
         mUrlFocusChangeFraction = fraction;
         updateUrlExpansionFraction();
-        invokeTransition(false);
+        invokeTransition();
     }
 
     private void updateUrlExpansionFraction() {
@@ -2228,7 +2228,7 @@
         boolean wasShowingNtp = ntpDelegate.wasShowingNtp();
         float previousNtpScrollFraction = mNtpSearchBoxScrollFraction;
 
-        invokeTransition(true);
+        invokeTransition(/* resetNtpTransition= */ true, /* skipUrlExpansion= */ false);
         ntpDelegate.setSearchBoxScrollListener(this::onNtpScrollChanged);
         if (ntpDelegate.isLocationBarShown()) {
             updateToNtpBackground();
@@ -2452,7 +2452,10 @@
             mLayoutUpdater.run();
         }
         updateShadowVisibility();
-        invokeTransition(false);
+        invokeTransition(
+                /* resetNtpTransition= */ false,
+                /* skipUrlExpansion= */ ChromeFeatureList.sToolbarPhoneAnimationRefactor
+                        .isEnabled());
 
         // This exception is to prevent early change of theme color when exiting the tab switcher
         // since currently visual state does not map correctly to tab switcher state. See
@@ -2810,13 +2813,20 @@
         mNtpSearchBoxScrollFraction = ntpSearchBoxScrollFraction;
     }
 
+    private void invokeTransition() {
+        invokeTransition(/* resetNtpTransition= */ false, /* skipUrlExpansion= */ false);
+    }
+
     /**
      * Triggers NTP transition animation (if toolbar is shown on NTP) and URL expansion animation.
      *
      * @param resetNtpTransition if the transition is to reset NTP animation.
+     * @param skipUrlExpansion if the URL expansion animation should be skipped.
      */
-    private void invokeTransition(boolean resetNtpTransition) {
+    private void invokeTransition(boolean resetNtpTransition, boolean skipUrlExpansion) {
         if (resetNtpTransition) {
+            // skipUrlExpansion should not be set when resetNtpTransition is true.
+            assert !skipUrlExpansion;
             resetNtpAnimationValues();
             return;
         }
@@ -2835,7 +2845,10 @@
         } else {
             resetNtpAnimationValues();
         }
-        updateUrlExpansionAnimation();
+
+        if (!skipUrlExpansion) {
+            updateUrlExpansionAnimation();
+        }
     }
 
     private boolean inOrEnteringTabSwitcher() {
diff --git a/chrome/browser/ui/autofill/address_bubbles_controller.cc b/chrome/browser/ui/autofill/address_bubbles_controller.cc
index a173c99..e39e892b 100644
--- a/chrome/browser/ui/autofill/address_bubbles_controller.cc
+++ b/chrome/browser/ui/autofill/address_bubbles_controller.cc
@@ -157,7 +157,7 @@
   if (decision == AutofillClient::AddressPromptUserDecision::kEditDeclined) {
     // Reopen this bubble if the user canceled editing.
     shown_by_user_gesture_ = false;
-    Show();
+    ShowBubble();
     return;
   }
   if (address_profile_save_prompt_callback_) {
@@ -191,7 +191,7 @@
     return;
   }
   shown_by_user_gesture_ = true;
-  Show();
+  ShowBubble();
 }
 
 bool AddressBubblesController::IsBubbleActive() const {
@@ -267,7 +267,7 @@
   is_migration_to_account_ = is_migration_to_account;
   user_has_any_profile_saved_ = user_has_any_profile_saved;
 
-  Show();
+  ShowBubble();
 }
 
 void AddressBubblesController::MaybeShowIOSDektopAddressPromo() {
diff --git a/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc b/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc
index 47e954f..8fc0217b 100644
--- a/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc
+++ b/chrome/browser/ui/autofill/autofill_bubble_controller_base.cc
@@ -22,11 +22,6 @@
 AutofillBubbleControllerBase::~AutofillBubbleControllerBase() {
   HideBubble();
 }
-void AutofillBubbleControllerBase::Show() {
-  UpdatePageActionIcon();
-  DoShowBubble();
-  UpdatePageActionIcon();
-}
 
 void AutofillBubbleControllerBase::OnVisibilityChanged(
     content::Visibility visibility) {
@@ -49,6 +44,12 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
 }
 
+void AutofillBubbleControllerBase::ShowBubble() {
+  UpdatePageActionIcon();
+  DoShowBubble();
+  UpdatePageActionIcon();
+}
+
 void AutofillBubbleControllerBase::HideBubble() {
   if (bubble_view_) {
     bubble_view_->Hide();
diff --git a/chrome/browser/ui/autofill/autofill_bubble_controller_base.h b/chrome/browser/ui/autofill/autofill_bubble_controller_base.h
index ebe949544..bcd1c94b 100644
--- a/chrome/browser/ui/autofill/autofill_bubble_controller_base.h
+++ b/chrome/browser/ui/autofill/autofill_bubble_controller_base.h
@@ -48,13 +48,14 @@
 
   virtual void UpdatePageActionIcon();
 
-  void Show();
-
   AutofillBubbleBase* bubble_view() const { return bubble_view_; }
   void set_bubble_view(AutofillBubbleBase* bubble_view) {
     bubble_view_ = bubble_view;
   }
 
+  // Shows the bubbles.
+  void ShowBubble();
+
   // Remove the |bubble_view_| and hide the bubble.
   void HideBubble();
 
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
index 4b507b5b..832fbc7 100644
--- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
+++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
@@ -416,9 +416,9 @@
   VirtualCardEnrollBubbleControllerImpl* controller =
       VirtualCardEnrollBubbleControllerImpl::FromWebContents(web_contents());
   DCHECK(controller);
-  controller->ShowBubble(virtual_card_enrollment_fields,
-                         std::move(accept_virtual_card_callback),
-                         std::move(decline_virtual_card_callback));
+  controller->SetupAndShowBubble(virtual_card_enrollment_fields,
+                                 std::move(accept_virtual_card_callback),
+                                 std::move(decline_virtual_card_callback));
 }
 
 void ChromePaymentsAutofillClient::VirtualCardEnrollCompleted(
@@ -473,7 +473,7 @@
   FilledCardInformationBubbleControllerImpl* controller =
       FilledCardInformationBubbleControllerImpl::FromWebContents(
           web_contents());
-  controller->ShowBubble(options);
+  controller->SetupAndShowBubble(options);
 #endif
 }
 
@@ -788,9 +788,9 @@
     base::RepeatingClosure close_mandatory_reauth_callback) {
   MandatoryReauthBubbleControllerImpl::CreateForWebContents(web_contents());
   MandatoryReauthBubbleControllerImpl::FromWebContents(web_contents())
-      ->ShowBubble(std::move(accept_mandatory_reauth_callback),
-                   std::move(cancel_mandatory_reauth_callback),
-                   std::move(close_mandatory_reauth_callback));
+      ->SetupAndShowBubble(std::move(accept_mandatory_reauth_callback),
+                           std::move(cancel_mandatory_reauth_callback),
+                           std::move(close_mandatory_reauth_callback));
 }
 
 IbanManager* ChromePaymentsAutofillClient::GetIbanManager() {
diff --git a/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.cc
index 7f7b734..78bd673 100644
--- a/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.cc
@@ -57,7 +57,7 @@
 FilledCardInformationBubbleControllerImpl::
     ~FilledCardInformationBubbleControllerImpl() = default;
 
-void FilledCardInformationBubbleControllerImpl::ShowBubble(
+void FilledCardInformationBubbleControllerImpl::SetupAndShowBubble(
     const FilledCardInformationBubbleOptions& options) {
   // If another bubble is visible, dismiss it and show a new one since the card
   // information can be different.
@@ -75,7 +75,7 @@
   // the same time.
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&FilledCardInformationBubbleControllerImpl::Show,
+      base::BindOnce(&FilledCardInformationBubbleControllerImpl::ShowBubble,
                      weak_ptr_factory_.GetWeakPtr()),
       kFilledCardInformationBubbleDelay);
 }
@@ -88,7 +88,7 @@
 
   is_user_gesture_ = true;
   should_icon_be_visible_ = true;
-  Show();
+  ShowBubble();
 }
 
 AutofillBubbleBase* FilledCardInformationBubbleControllerImpl::GetBubble()
@@ -353,7 +353,7 @@
   // to the tab.
   if (visibility == content::Visibility::VISIBLE && !bubble_has_been_shown_ &&
       should_icon_be_visible_) {
-    Show();
+    ShowBubble();
   } else if (visibility == content::Visibility::HIDDEN) {
     HideBubble();
   }
diff --git a/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.h
index 214d4437..ca27ac56 100644
--- a/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/filled_card_information_bubble_controller_impl.h
@@ -34,7 +34,7 @@
       const FilledCardInformationBubbleControllerImpl&) = delete;
 
   // Show the bubble view.
-  void ShowBubble(const FilledCardInformationBubbleOptions& options);
+  void SetupAndShowBubble(const FilledCardInformationBubbleOptions& options);
 
   // Invoked when the omnibox icon is clicked.
   void ReshowBubble();
diff --git a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
index 5e1c60c..1caf1be 100644
--- a/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/iban_bubble_controller_impl.cc
@@ -63,7 +63,7 @@
   CHECK(!save_iban_prompt_callback_.is_null());
 
   if (should_show_prompt) {
-    Show();
+    ShowBubble();
   } else {
     ShowIconOnly();
   }
@@ -89,7 +89,7 @@
   // Save callback should not be null for IBAN save.
   CHECK(!save_iban_prompt_callback_.is_null());
   if (should_show_prompt) {
-    Show();
+    ShowBubble();
   } else {
     ShowIconOnly();
   }
@@ -110,7 +110,7 @@
     CHECK(current_bubble_type_ == IbanBubbleType::kManageSavedIban ||
           current_bubble_type_ == IbanBubbleType::kUploadInProgress);
   }
-  Show();
+  ShowBubble();
 }
 
 void IbanBubbleControllerImpl::ShowConfirmationBubbleView(
diff --git a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.cc
index 72a97ee..d9c20b81 100644
--- a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.cc
@@ -45,7 +45,7 @@
 #endif
 }
 
-void MandatoryReauthBubbleControllerImpl::ShowBubble(
+void MandatoryReauthBubbleControllerImpl::SetupAndShowBubble(
     base::OnceClosure accept_mandatory_reauth_callback,
     base::OnceClosure cancel_mandatory_reauth_callback,
     base::RepeatingClosure close_mandatory_reauth_callback) {
@@ -64,7 +64,7 @@
       autofill_metrics::MandatoryReauthOptInBubbleOffer::kShown,
       /*is_reshow=*/false);
 
-  Show();
+  ShowBubble();
 }
 
 void MandatoryReauthBubbleControllerImpl::ReshowBubble() {
@@ -91,7 +91,7 @@
         autofill_metrics::MandatoryReauthOptInConfirmationBubbleMetric::kShown);
   }
 
-  Show();
+  ShowBubble();
 }
 
 std::u16string MandatoryReauthBubbleControllerImpl::GetWindowTitle() const {
diff --git a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.h
index 663ea95..a5e320f 100644
--- a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl.h
@@ -30,9 +30,10 @@
       const MandatoryReauthBubbleControllerImpl&) = delete;
   ~MandatoryReauthBubbleControllerImpl() override;
 
-  void ShowBubble(base::OnceClosure accept_mandatory_reauth_callback,
-                  base::OnceClosure cancel_mandatory_reauth_callback,
-                  base::RepeatingClosure close_mandatory_reauth_callback);
+  void SetupAndShowBubble(
+      base::OnceClosure accept_mandatory_reauth_callback,
+      base::OnceClosure cancel_mandatory_reauth_callback,
+      base::RepeatingClosure close_mandatory_reauth_callback);
   void ReshowBubble();
 
   // MandatoryReauthBubbleController:
diff --git a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl_unittest.cc
index f7e27be..82eaefc6 100644
--- a/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/payments/mandatory_reauth_bubble_controller_impl_unittest.cc
@@ -49,8 +49,8 @@
   }
 
   void ShowBubble() {
-    controller()->ShowBubble(accept_callback.Get(), cancel_callback.Get(),
-                             close_callback.Get());
+    controller()->SetupAndShowBubble(
+        accept_callback.Get(), cancel_callback.Get(), close_callback.Get());
   }
 
   void ReshowBubble() { controller()->ReshowBubble(); }
diff --git a/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc
index 50d5e68..ef398b2 100644
--- a/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/offer_notification_bubble_controller_impl.cc
@@ -157,7 +157,7 @@
   is_user_gesture_ = false;
 
   if (options.show_notification_automatically) {
-    Show();
+    ShowBubble();
   } else {
     HideBubbleAndClearTimestamp(/*should_show_icon=*/true);
   }
@@ -171,7 +171,7 @@
 
   is_user_gesture_ = true;
 
-  Show();
+  ShowBubble();
 }
 
 void OfferNotificationBubbleControllerImpl::DismissNotification() {
@@ -182,7 +182,7 @@
     content::Visibility visibility) {
   if (visibility == content::Visibility::VISIBLE && !bubble_view() &&
       bubble_state_ == BubbleState::kShowingIconAndBubble) {
-    Show();
+    ShowBubble();
   } else if (visibility == content::Visibility::HIDDEN) {
     HideBubbleAndClearTimestamp(bubble_state_ == BubbleState::kShowingIcon);
   }
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
index 2576192..7af332b 100644
--- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
@@ -113,7 +113,7 @@
           : BubbleType::LOCAL_SAVE;
 
   if (options.show_prompt) {
-    ShowBubble();
+    SetupAndShowBubble();
   } else {
     ShowIconOnly();
   }
@@ -159,7 +159,7 @@
   }
 
   if (options_.show_prompt) {
-    ShowBubble();
+    SetupAndShowBubble();
   } else {
     ShowIconOnly();
   }
@@ -170,7 +170,7 @@
     const CreditCard& card) {
   card_ = card;
   current_bubble_type_ = BubbleType::MANAGE_CARDS;
-  ShowBubble();
+  SetupAndShowBubble();
 }
 
 void SaveCardBubbleControllerImpl::ReshowBubble(
@@ -182,7 +182,7 @@
 
   is_reshow_ = true;
   is_triggered_by_user_gesture_ = is_triggered_by_user_gesture;
-  ShowBubble();
+  SetupAndShowBubble();
 }
 
 void SaveCardBubbleControllerImpl::ShowConfirmationBubbleView(
@@ -204,7 +204,7 @@
   on_confirmation_closed_callback_ = std::move(on_confirmation_closed_callback);
 
   // Show upload confirmation bubble.
-  ShowBubble();
+  SetupAndShowBubble();
 
   // Auto close confirmation bubble when card saved is successful.
   if (card_saved) {
@@ -774,7 +774,7 @@
   }
 }
 
-void SaveCardBubbleControllerImpl::ShowBubble() {
+void SaveCardBubbleControllerImpl::SetupAndShowBubble() {
   CHECK(current_bubble_type_ != BubbleType::INACTIVE);
   // Upload save callback should not be null for UPLOAD_SAVE or
   // UPLOAD_CVC_SAVE state.
@@ -787,7 +787,7 @@
         (current_bubble_type_ != BubbleType::LOCAL_SAVE &&
          current_bubble_type_ != BubbleType::LOCAL_CVC_SAVE));
   CHECK(!bubble_view());
-  Show();
+  ShowBubble();
 }
 
 void SaveCardBubbleControllerImpl::ShowIconOnly() {
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
index 6890bdf..d7b47be 100644
--- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
@@ -177,7 +177,7 @@
   friend class SaveCardBubbleViewsFullFormBrowserTest;
 
   // Displays both the offer-to-save bubble and is associated omnibox icon.
-  void ShowBubble();
+  void SetupAndShowBubble();
 
   // Displays the omnibox icon without popping up the offer-to-save bubble.
   void ShowIconOnly();
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
index 8fa80e5..f59d167 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.cc
@@ -49,7 +49,7 @@
   return VirtualCardEnrollBubbleControllerImpl::FromWebContents(web_contents);
 }
 
-void VirtualCardEnrollBubbleControllerImpl::ShowBubble(
+void VirtualCardEnrollBubbleControllerImpl::SetupAndShowBubble(
     const VirtualCardEnrollmentFields& virtual_card_enrollment_fields,
     base::OnceClosure accept_virtual_card_callback,
     base::OnceClosure decline_virtual_card_callback) {
@@ -59,7 +59,7 @@
   decline_virtual_card_callback_ = std::move(decline_virtual_card_callback);
 
   is_user_gesture_ = false;
-  Show();
+  ShowBubble();
 
   VirtualCardEnrollMetricsLogger::OnCardArtAvailable(
       ui_model_->enrollment_fields().card_art_image,
@@ -74,7 +74,7 @@
   }
 
   is_user_gesture_ = true;
-  Show();
+  ShowBubble();
 }
 
 void VirtualCardEnrollBubbleControllerImpl::ShowConfirmationBubbleView(
@@ -98,7 +98,7 @@
                     /*card_label=*/ui_model_->enrollment_fields()
                         .credit_card.NetworkAndLastFourDigits());
   // Show enrollment confirmation bubble.
-  Show();
+  ShowBubble();
 #endif
 }
 
@@ -288,7 +288,7 @@
 #if !BUILDFLAG(IS_ANDROID)
   if (visibility == content::Visibility::VISIBLE && !bubble_view() &&
       bubble_state_ == BubbleState::kShowingIconAndBubble) {
-    Show();
+    ShowBubble();
   } else if (visibility == content::Visibility::HIDDEN) {
     HideBubble();
     if (bubble_state_ != BubbleState::kShowingIcon) {
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 398af7c..400710d 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
@@ -42,7 +42,7 @@
   // Displays both the virtual card enroll bubble and its associated omnibox
   // icon. Sets virtual card enrollment fields as well as the closure for the
   // accept and decline bubble events.
-  void ShowBubble(
+  void SetupAndShowBubble(
       const VirtualCardEnrollmentFields& virtual_card_enrollment_fields,
       base::OnceClosure accept_virtual_card_callback,
       base::OnceClosure decline_virtual_card_callback);
diff --git a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
index 81c1045a..358fae84 100644
--- a/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl_unittest.cc
@@ -157,7 +157,7 @@
   }
 
   void ShowBubble() {
-    controller()->ShowBubble(
+    controller()->SetupAndShowBubble(
         virtual_card_enrollment_fields(),
         /*accept_virtual_card_callback=*/base::DoNothing(),
         /*decline_virtual_card_callback=*/base::DoNothing());
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc
index 2b89aff1..35a7fcd 100644
--- a/chrome/browser/ui/browser_element_identifiers.cc
+++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -9,6 +9,7 @@
 
 // Please keep this list alphabetized.
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAddCurrentTabToReadingListElementId);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kAiModePageActionIconElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(
     kAnonymizedUrlCollectionPersonalizationSettingId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kAppUninstallDialogOkButtonId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h
index 2883393..befc3fe 100644
--- a/chrome/browser/ui/browser_element_identifiers.h
+++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -18,6 +18,7 @@
 // These should gradually replace values in view_ids.h.
 // Please keep this list alphabetized.
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAddCurrentTabToReadingListElementId);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kAiModePageActionIconElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(
     kAnonymizedUrlCollectionPersonalizationSettingId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kAppUninstallDialogOkButtonId);
diff --git a/chrome/browser/ui/browser_finder.cc b/chrome/browser/ui/browser_finder.cc
index 4a5d1a3..414f1471 100644
--- a/chrome/browser/ui/browser_finder.cc
+++ b/chrome/browser/ui/browser_finder.cc
@@ -257,10 +257,16 @@
                                         /*match_not_closing=*/false);
 }
 
-std::vector<Browser*> FindAllTabbedBrowsersWithProfile(Profile* profile) {
+std::vector<Browser*> FindAllTabbedBrowsersWithProfile(
+    Profile* profile,
+    bool ignore_closing_browsers) {
+  uint32_t match_types = kMatchNormal;
+  if (ignore_closing_browsers) {
+    match_types |= kMatchNotClosing;
+  }
   std::vector<Browser*> browsers;
   for (Browser* browser : *BrowserList::GetInstance()) {
-    if (BrowserMatches(browser, profile, Browser::FEATURE_NONE, kMatchNormal,
+    if (BrowserMatches(browser, profile, Browser::FEATURE_NONE, match_types,
                        display::kInvalidDisplayId)) {
       browsers.emplace_back(browser);
     }
diff --git a/chrome/browser/ui/browser_finder.h b/chrome/browser/ui/browser_finder.h
index 8ea535e..0b84e7c 100644
--- a/chrome/browser/ui/browser_finder.h
+++ b/chrome/browser/ui/browser_finder.h
@@ -110,7 +110,9 @@
 
 // Returns all tabbed browsers with the provided profile. Returns an empty
 // vector if no such browsers currently exist.
-std::vector<Browser*> FindAllTabbedBrowsersWithProfile(Profile* profile);
+std::vector<Browser*> FindAllTabbedBrowsersWithProfile(
+    Profile* profile,
+    bool ignore_closing_browsers = false);
 
 // Returns all browsers of any type with the provided profile. Returns an empty
 // vector if no such browsers currently exist.
diff --git a/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc b/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
index 1682ed6..c13f9bd 100644
--- a/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
+++ b/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
@@ -541,7 +541,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kShoppingInsights),
       base::BindRepeating(&CommerceUiTabHelper::CreateShoppingInsightsWebView,
                           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth);
+      /*default_content_width_callback=*/base::NullCallback());
   side_panel_registry_->Register(std::move(entry));
 }
 
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
index 2f01a27..08ef8be 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
@@ -49,10 +49,11 @@
   kMaxValue = kKeyboardAndPointerLocked,
 };
 
-// Check whether `event` is a kRawKeyDown type and doesn't have non-stateful
-// modifiers (i.e. shift, ctrl etc.).
+// Check whether `event` is a kKeyDown or kRawKeyDown type and doesn't have
+// non-stateful modifiers (i.e. shift, ctrl etc.).
 bool IsUnmodifiedEscKeyDownEvent(const input::NativeWebKeyboardEvent& event) {
-  if (event.GetType() != input::NativeWebKeyboardEvent::Type::kRawKeyDown) {
+  if (event.GetType() != input::NativeWebKeyboardEvent::Type::kRawKeyDown &&
+      event.GetType() != input::NativeWebKeyboardEvent::Type::kKeyDown) {
     return false;
   }
   if (event.GetModifiers() & blink::WebInputEvent::kKeyModifiers) {
diff --git a/chrome/browser/ui/extensions/BUILD.gn b/chrome/browser/ui/extensions/BUILD.gn
index 21cd0c7..b7e5666 100644
--- a/chrome/browser/ui/extensions/BUILD.gn
+++ b/chrome/browser/ui/extensions/BUILD.gn
@@ -156,6 +156,7 @@
       "//chrome/browser/search_engines",
       "//chrome/browser/ui/location_bar",
       "//chrome/browser/ui/profiles",
+      "//chrome/browser/ui/startup",
       "//chrome/browser/web_applications",
       "//components/prefs",
       "//components/security_state/content",
diff --git a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc
index 7fdc0bd..c11704f 100644
--- a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc
+++ b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/lens/lens_overlay_entry_point_controller.h"
 
+#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/system/sys_info.h"
 #include "chrome/browser/command_updater.h"
@@ -32,6 +33,7 @@
 #include "components/lens/lens_features.h"
 #include "components/lens/lens_overlay_permission_utils.h"
 #include "components/omnibox/browser/omnibox_prefs.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "components/tabs/public/tab_interface.h"
 #include "content/public/browser/navigation_entry.h"
 
@@ -157,7 +159,8 @@
 }
 
 bool LensOverlayEntryPointController::AreVisible() const {
-  return IsEnabled() && !IsOverlayActive();
+  return IsEnabled() && !IsOverlayActive() &&
+         !base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint);
 }
 
 void LensOverlayEntryPointController::UpdateEntryPointsState(
diff --git a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h
index 5be3b7d..1c0f32a2 100644
--- a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h
+++ b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h
@@ -58,6 +58,8 @@
   // this current moment in time. Sometimes, entrypoints are hidden ephermally,
   // such as when the Lens Overlay is currently active, so entrypoints do
   // nothing.
+  // When the AIM Omnibox entrypoint is enabled, the Lens Overlay entrypoints
+  // should be hidden in order to mitigate non-deterministic Omnibox behavior.
   bool AreVisible() const;
 
   // Updates the enable/disable and visibility state of entry points. If
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
index d2a964b..0894d708 100644
--- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
+++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
@@ -970,9 +970,9 @@
             &LensOverlaySidePanelCoordinator::GetOpenInNewTabUrl,
             base::Unretained(this)),
         GetMoreInfoCallback(),
-        lens::features::IsLensSearchSidePanelDefaultWidthChangeEnabled()
-            ? lens::features::GetLensSearchSidePanelDefaultWidth()
-            : SidePanelEntry::kSidePanelDefaultContentWidth);
+        base::BindRepeating(
+            &LensOverlaySidePanelCoordinator::GetPreferredDefaultWidth,
+            base::Unretained(this)));
     entry->SetProperty(kShouldShowTitleInSidePanelHeaderKey, false);
     registry->Register(std::move(entry));
 
@@ -1022,6 +1022,12 @@
   }
 }
 
+int LensOverlaySidePanelCoordinator::GetPreferredDefaultWidth() {
+  return lens::features::IsLensSearchSidePanelDefaultWidthChangeEnabled()
+             ? lens::features::GetLensSearchSidePanelDefaultWidth()
+             : SidePanelEntry::kSidePanelDefaultContentWidth;
+}
+
 base::RepeatingCallback<std::unique_ptr<ui::MenuModel>()>
 LensOverlaySidePanelCoordinator::GetMoreInfoCallback() {
   if (lens::IsLensOverlayContextualSearchboxEnabled()) {
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
index ae9cbd0..1074120 100644
--- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
+++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
@@ -327,6 +327,9 @@
   // Called to get the URL for the "open in new tab" button.
   GURL GetOpenInNewTabUrl();
 
+  // Called to get the lens side panel's preferred default width.
+  int GetPreferredDefaultWidth();
+
   std::unique_ptr<views::View> CreateLensOverlayResultsView(
       SidePanelEntryScope& scope);
 
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java
index c7a17f8..2192f6b7 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java
@@ -12,12 +12,13 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.BlockJUnit4ClassRunner;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
@@ -28,13 +29,9 @@
     private static final String ACTION_TITLE = "stack";
     private static final String NOTIFICATION_TITLE = "queue";
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private SnackbarController mMockController;
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
     @Test
     @Feature({"Browser", "Snackbar"})
     public void testActionCoversNotification() {
diff --git a/chrome/browser/ui/page_action/page_action_icon_type.h b/chrome/browser/ui/page_action/page_action_icon_type.h
index c63565e..92a9331 100644
--- a/chrome/browser/ui/page_action/page_action_icon_type.h
+++ b/chrome/browser/ui/page_action/page_action_icon_type.h
@@ -48,7 +48,8 @@
   kCollaborationMessaging = 32,
   // DEPRECATED: kChangePassword = 33,
   kLensOverlayHomework = 34,
-  kMaxValue = kLensOverlayHomework,
+  kAiMode = 35,
+  kMaxValue = kAiMode,
 };
 // LINT.ThenChange(//tools/metrics/histograms/metadata/page/enums.xml:PageActionIconType)
 
@@ -84,6 +85,7 @@
 static_assert(static_cast<int>(PageActionIconType::kCollaborationMessaging) ==
               32);
 static_assert(static_cast<int>(PageActionIconType::kLensOverlayHomework) == 34);
+static_assert(static_cast<int>(PageActionIconType::kAiMode) == 35);
 
 // Returns a bool indicating whether the given page action type has been
 // migrated to the new framework, which is based on ActionItems instead of
diff --git a/chrome/browser/ui/profiles/BUILD.gn b/chrome/browser/ui/profiles/BUILD.gn
index 3f000676..cef86dd 100644
--- a/chrome/browser/ui/profiles/BUILD.gn
+++ b/chrome/browser/ui/profiles/BUILD.gn
@@ -94,7 +94,10 @@
       "profile_customization_util.cc",
       "profile_picker.cc",
     ]
-    deps += [ "//chrome/browser/ui:ui_features" ]
+    deps += [
+      "//chrome/browser/ui:ui_features",
+      "//chrome/browser/ui/startup",
+    ]
 
     if (enable_dice_support) {
       sources += [
@@ -165,7 +168,10 @@
       "profile_customization_util_unittest.cc",
       "profile_picker_unittest.cc",
     ]
-    deps += [ "//chrome/browser/ui:ui_features" ]
+    deps += [
+      "//chrome/browser/ui:ui_features",
+      "//chrome/browser/ui/startup",
+    ]
   }
 }
 
diff --git a/chrome/browser/ui/startup/BUILD.gn b/chrome/browser/ui/startup/BUILD.gn
index 61a544f1..62e4fb7e 100644
--- a/chrome/browser/ui/startup/BUILD.gn
+++ b/chrome/browser/ui/startup/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/chrome_build.gni")
+import("//build/config/ui.gni")
 
 # Allow browser tests that startup with --gcpw-signin flag only on
 # non-Google Chrome builds.
@@ -23,3 +24,73 @@
 
   public_deps = [ "//url" ]
 }
+
+source_set("startup") {
+  sources = [
+    "bad_flags_prompt.h",
+    "bidding_and_auction_consented_debugging_infobar_delegate.h",
+    "test_third_party_cookie_phaseout_infobar_delegate.h",
+  ]
+  public_deps = [
+    "//components/infobars/core",
+    "//url",
+  ]
+
+  if (!is_android) {
+    sources += [
+      "automation_infobar_delegate.h",
+      "google_api_keys_infobar_delegate.h",
+      "infobar_utils.h",
+      "launch_mode_recorder.h",
+      "obsolete_system_infobar_delegate.h",
+      "startup_browser_creator.h",
+      "startup_browser_creator_impl.h",
+      "startup_tab_provider.h",
+      "startup_types.h",
+    ]
+    public_deps += [
+      ":startup_tab",
+      "//base",
+      "//chrome/browser/prefs:util",
+      "//chrome/browser/sessions",
+      "//components/infobars/content",
+      "//components/signin/public/base:signin_buildflags",
+    ]
+  }
+
+  if (is_chrome_for_testing) {
+    sources += [ "chrome_for_testing_infobar_delegate.h" ]
+  }
+
+  if (is_win || is_mac || is_linux || is_chromeos) {
+    sources += [ "web_app_startup_utils.h" ]
+    public_deps += [ "//components/services/app_service/public/cpp:app_types" ]
+  }
+
+  if (is_win || is_mac || is_linux) {
+    sources += [
+      "first_run_service.h",
+      "web_app_info_recorder_utils.h",
+    ]
+
+    public_deps += [
+      "//chrome/browser/profiles:profile",
+      "//chrome/browser/ui/profiles",
+      "//components/keyed_service/core",
+    ]
+  }
+
+  if (is_win) {
+    assert(toolkit_views)
+    assert(use_aura)
+
+    sources += [
+      "credential_provider_signin_dialog_win.h",
+      "credential_provider_signin_info_fetcher_win.h",
+    ]
+    public_deps += [
+      ":buildflags",
+      "//google_apis",
+    ]
+  }
+}
diff --git a/chrome/browser/ui/startup/default_browser_prompt/BUILD.gn b/chrome/browser/ui/startup/default_browser_prompt/BUILD.gn
index a4c6e62..d472ac8 100644
--- a/chrome/browser/ui/startup/default_browser_prompt/BUILD.gn
+++ b/chrome/browser/ui/startup/default_browser_prompt/BUILD.gn
@@ -117,6 +117,7 @@
       "//chrome/browser:shell_integration",
       "//chrome/browser/profiles:profile",
       "//chrome/browser/ui:browser_element_identifiers",
+      "//chrome/browser/ui/startup",
       "//chrome/browser/ui/toolbar",
       "//chrome/browser/ui/views/infobars",
       "//chrome/common",
diff --git a/chrome/browser/ui/tabs/public/tab_features.h b/chrome/browser/ui/tabs/public/tab_features.h
index 002ad71..c68eed6 100644
--- a/chrome/browser/ui/tabs/public/tab_features.h
+++ b/chrome/browser/ui/tabs/public/tab_features.h
@@ -24,6 +24,7 @@
 class PwaInstallPageActionController;
 class ReadAnythingSidePanelController;
 class SidePanelRegistry;
+class TabCaptureContentsBorderHelper;
 class TabResourceUsageTabHelper;
 class TabUIHelper;
 class TranslatePageActionController;
@@ -31,7 +32,7 @@
 class ManagePasswordsPageActionController;
 
 namespace actor::ui {
-class ActorUiTabController;
+class ActorUiTabControllerInterface;
 }  // namespace actor::ui
 
 namespace commerce {
@@ -247,7 +248,7 @@
   TabUIHelper* tab_ui_helper() { return tab_ui_helper_.get(); }
 
   // actor_ui_tab_controller_ is only initialized for normal browser windows
-  actor::ui::ActorUiTabController* actor_ui_tab_controller() {
+  actor::ui::ActorUiTabControllerInterface* actor_ui_tab_controller() const {
     return actor_ui_tab_controller_.get();
   }
 
@@ -405,11 +406,15 @@
 
   std::unique_ptr<QwacWebContentsObserver> qwac_web_contents_observer_;
 
-  std::unique_ptr<actor::ui::ActorUiTabController> actor_ui_tab_controller_;
+  std::unique_ptr<actor::ui::ActorUiTabControllerInterface>
+      actor_ui_tab_controller_;
 
   std::unique_ptr<TabCreationMetricsController>
       tab_creation_metrics_controller_;
 
+  std::unique_ptr<TabCaptureContentsBorderHelper>
+      tab_capture_contents_border_helper_;
+
   // Must be the last member.
   base::WeakPtrFactory<TabFeatures> weak_factory_{this};
 };
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc
index aba7db1..5284ac5 100644
--- a/chrome/browser/ui/tabs/tab_features.cc
+++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -68,6 +68,7 @@
 #include "chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h"
 #include "chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.h"
 #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h"
+#include "chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h"
 #include "chrome/browser/ui/views/translate/translate_page_action_controller.h"
 #include "chrome/browser/ui/views/zoom/zoom_view_controller.h"
 #include "chrome/browser/ui/web_applications/pwa_install_page_action.h"
@@ -364,6 +365,10 @@
     qwac_web_contents_observer_ =
         std::make_unique<QwacWebContentsObserver>(tab);
   }
+
+  tab_capture_contents_border_helper_ =
+      GetUserDataFactory().CreateInstance<TabCaptureContentsBorderHelper>(tab,
+                                                                          tab);
 }
 
 TabResourceUsageTabHelper* TabFeatures::SetResourceUsageHelperForTesting(
diff --git a/chrome/browser/ui/toolbar/BUILD.gn b/chrome/browser/ui/toolbar/BUILD.gn
index cfb495f..892a4ed8 100644
--- a/chrome/browser/ui/toolbar/BUILD.gn
+++ b/chrome/browser/ui/toolbar/BUILD.gn
@@ -76,6 +76,7 @@
     deps += [
       "//chrome/browser/ui:ui_features",
       "//chrome/browser/ui/actions:actions_headers",
+      "//components/user_education/common",
     ]
   }
 
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 4a8a60d..5dc7ebe9 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -1037,11 +1037,6 @@
 
 AppMenuModel::~AppMenuModel() = default;
 
-void AppMenuModel::SetHighlightedIdentifier(
-    ui::ElementIdentifier highlighted_menu_identifier) {
-  highlighted_menu_identifier_ = highlighted_menu_identifier;
-}
-
 void AppMenuModel::Init() {
   Build();
 
@@ -1771,10 +1766,6 @@
   return false;
 }
 
-bool AppMenuModel::IsElementIdAlerted(ui::ElementIdentifier element_id) const {
-  return highlighted_menu_identifier_ == element_id;
-}
-
 bool AppMenuModel::GetAcceleratorForCommandId(
     int command_id,
     ui::Accelerator* accelerator) const {
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h
index 8c6d1de..72e17f29 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.h
+++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -14,6 +14,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/safety_hub/safety_hub_constants.h"
 #include "components/prefs/pref_change_registrar.h"
+#include "components/user_education/common/menu/highlighting_simple_menu_model_delegate.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/models/button_menu_item_model.h"
@@ -165,7 +166,7 @@
 
 // A menu model that builds the contents of the app menu.
 class AppMenuModel : public ui::SimpleMenuModel,
-                     public ui::SimpleMenuModel::Delegate,
+                     public user_education::HighlightingSimpleMenuModelDelegate,
                      public ui::ButtonMenuItemModel::Delegate {
  public:
   DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kProfileMenuItem);
@@ -220,9 +221,6 @@
   // Runs Build() and registers observers.
   void Init();
 
-  void SetHighlightedIdentifier(
-      ui::ElementIdentifier highlighted_menu_identifier);
-
   // Overridden for ButtonMenuItemModel::Delegate:
   bool DoesCommandIdDismissMenu(int command_id) const override;
 
@@ -231,7 +229,6 @@
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
   bool IsCommandIdAlerted(int command_id) const override;
-  bool IsElementIdAlerted(ui::ElementIdentifier element_id) const override;
   bool GetAcceleratorForCommandId(int command_id,
                                   ui::Accelerator* accelerator) const override;
 
@@ -317,8 +314,6 @@
   PrefChangeRegistrar local_state_pref_change_registrar_;
 
   const AlertMenuItem alert_item_;
-
-  ui::ElementIdentifier highlighted_menu_identifier_;
 };
 
 #endif  // CHROME_BROWSER_UI_TOOLBAR_APP_MENU_MODEL_H_
diff --git a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
index 6c3f81fb..c26f15d 100644
--- a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
+++ b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
@@ -18,6 +18,10 @@
     TabSearchBubbleHost* tab_search_bubble_host)
     : browser_view_(browser_view) {
   tab_search_bubble_host_observation_.Observe(tab_search_bubble_host);
+  // https://crbug.com/435137909: This class is created post window
+  // construction. Need to call this again because this class does not exist
+  // when ToolbarView tries to call it from init.
+  UpdateForWebUITabStrip();
 }
 
 TabSearchToolbarButtonController::~TabSearchToolbarButtonController() = default;
diff --git a/chrome/browser/ui/views/autofill/payments/filled_card_information_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/filled_card_information_bubble_views_interactive_uitest.cc
index ed27344..2a0416b 100644
--- a/chrome/browser/ui/views/autofill/payments/filled_card_information_bubble_views_interactive_uitest.cc
+++ b/chrome/browser/ui/views/autofill/payments/filled_card_information_bubble_views_interactive_uitest.cc
@@ -129,7 +129,7 @@
     options.filled_card = *filled_card;
     options.cvc = cvc;
     options.card_image = card_image_;
-    GetController()->ShowBubble(options);
+    GetController()->SetupAndShowBubble(options);
     ASSERT_TRUE(event_waiter_->Wait());
   }
 
diff --git a/chrome/browser/ui/views/autofill/payments/mandatory_reauth_bubble_view_uitest.cc b/chrome/browser/ui/views/autofill/payments/mandatory_reauth_bubble_view_uitest.cc
index 01f4ef7..bc42bb0 100644
--- a/chrome/browser/ui/views/autofill/payments/mandatory_reauth_bubble_view_uitest.cc
+++ b/chrome/browser/ui/views/autofill/payments/mandatory_reauth_bubble_view_uitest.cc
@@ -61,8 +61,8 @@
 
   void ShowBubble() {
     MandatoryReauthBubbleControllerImpl* controller = GetController();
-    controller->ShowBubble(accept_callback.Get(), cancel_callback.Get(),
-                           close_callback.Get());
+    controller->SetupAndShowBubble(accept_callback.Get(), cancel_callback.Get(),
+                                   close_callback.Get());
     views::test::WidgetVisibleWaiter visible_waiter(
         GetOptInBubbleView()->GetWidget());
     visible_waiter.Wait();
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
index 08d86d9..33f8c1a5 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
@@ -104,18 +104,21 @@
   }
 
   if (controller()) {
-    controller()->OnSaveButton(
-        {cardholder_name_textfield_
-             ? std::u16string(cardholder_name_textfield_->GetText())
-             : std::u16string(),
-         month_input_dropdown_
-             ? month_input_dropdown_->GetModel()->GetItemAt(
-                   month_input_dropdown_->GetSelectedIndex().value())
-             : std::u16string(),
-         year_input_dropdown_
-             ? year_input_dropdown_->GetModel()->GetItemAt(
-                   year_input_dropdown_->GetSelectedIndex().value())
-             : std::u16string()});
+    payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+    if (cardholder_name_textfield_) {
+      details.cardholder_name = cardholder_name_textfield_->GetText();
+    }
+    if (month_input_dropdown_) {
+      details.expiration_date_month =
+          month_input_dropdown_->GetModel()->GetItemAt(
+              month_input_dropdown_->GetSelectedIndex().value());
+    }
+    if (year_input_dropdown_) {
+      details.expiration_date_year =
+          year_input_dropdown_->GetModel()->GetItemAt(
+              year_input_dropdown_->GetSelectedIndex().value());
+    }
+    controller()->OnSaveButton(details);
   }
 
   // If a throbber is shown, don't automatically close the bubble view upon
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
index 5e551cde..2250cff 100644
--- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
+++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views_interactive_uitest.cc
@@ -101,7 +101,7 @@
     test_api(*GetController())
         .SetBubbleShownClosure(bubble_shown_closure_for_testing_);
 
-    GetController()->ShowBubble(
+    GetController()->SetupAndShowBubble(
         virtual_card_enrollment_fields,
         /*accept_virtual_card_callback*/ base::DoNothing(),
         /*decline_virtual_card_callback*/ base::DoNothing());
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 6e7581ef..07e14ff 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1920,7 +1920,7 @@
       FROM_HERE,
       base::BindOnce(&BookmarkBarView::ShowDropFolderForNode,
                      show_folder_method_factory_.GetWeakPtr(), folder),
-      base::Milliseconds(views::GetMenuShowDelay()));
+      views::GetMenuShowDelay());
 }
 
 void BookmarkBarView::CalculateDropLocation(
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
index 253ab7a..2aa627e 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -1118,8 +1118,7 @@
   // Verify that the Ok button can be interacted with after input protection.
   ui::KeyEvent press_enter_delayed(
       ui::EventType::kKeyPressed, ui::VKEY_RETURN, ui::EF_NONE,
-      ui::EventTimeForNow() +
-          base::Milliseconds(views::GetDoubleClickInterval()));
+      ui::EventTimeForNow() + views::GetDoubleClickInterval());
   views::test::ButtonTestApi(delegate_view->GetOkButton())
       .NotifyClick(press_enter_delayed);
   EXPECT_TRUE(delegate_view->GetWidget()->IsClosed());
diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
index 6701ff9..cc01344 100644
--- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
@@ -190,8 +190,7 @@
 
   ui::KeyEvent press_enter_delayed(
       ui::EventType::kKeyPressed, ui::VKEY_RETURN, ui::EF_NONE,
-      ui::EventTimeForNow() +
-          base::Milliseconds(views::GetDoubleClickInterval()));
+      ui::EventTimeForNow() + views::GetDoubleClickInterval());
   views::test::ButtonTestApi(dialog_->GetOkButton())
       .NotifyClick(press_enter_delayed);
   EXPECT_TRUE(url_did_launch_);
diff --git a/chrome/browser/ui/views/frame/app_menu_button.cc b/chrome/browser/ui/views/frame/app_menu_button.cc
index ca6da8b..ece5ddb 100644
--- a/chrome/browser/ui/views/frame/app_menu_button.cc
+++ b/chrome/browser/ui/views/frame/app_menu_button.cc
@@ -11,13 +11,10 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/toolbar/app_menu_model.h"
-#include "chrome/browser/ui/user_education/browser_user_education_interface.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/frame/app_menu_button_observer.h"
 #include "chrome/browser/ui/views/toolbar/app_menu.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
-#include "chrome/browser/user_education/user_education_service.h"
-#include "chrome/browser/user_education/user_education_service_factory.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/views/controls/button/menu_button_controller.h"
 #include "ui/views/view_class_properties.h"
@@ -57,7 +54,6 @@
 }
 
 void AppMenuButton::OnMenuClosed() {
-  promo_handle_.Release();
   observer_list_.Notify(&AppMenuButtonObserver::AppMenuClosed);
 }
 
@@ -72,7 +68,7 @@
   // in the class declaration.
   menu_.reset();
   menu_model_ = std::move(menu_model);
-  MaybeCloseIphAndHighlight(browser);
+  highlighter_.MaybeHighlight(browser, this, menu_model_.get());
   menu_model_->Init();
 
   menu_ = std::make_unique<AppMenu>(browser, menu_model_.get(), run_flags);
@@ -85,31 +81,5 @@
   menu_->SetTimerForTesting(std::move(timer));  // IN-TEST
 }
 
-void AppMenuButton::MaybeCloseIphAndHighlight(Browser* browser) {
-  // TODO(https://crbug.com/434898223): Make this a utility available to all
-  // menu buttons and revisit/unify behavior.
-  if (auto* const service = UserEducationServiceFactory::GetForBrowserContext(
-          browser->GetProfile())) {
-    if (auto* controller = service->GetFeaturePromoController(
-            base::PassKey<AppMenuButton>())) {
-      if (auto* const promo_specification =
-              controller->GetCurrentPromoSpecificationForAnchor(
-                  GetProperty(views::kElementIdentifierKey))) {
-        if (auto* const user_education =
-                BrowserUserEducationInterface::From(browser)) {
-          if (auto highlighted_identifier =
-                  promo_specification->highlighted_menu_identifier()) {
-            promo_handle_ = user_education->CloseFeaturePromoAndContinue(
-                *controller->GetCurrentPromoFeature());
-            if (promo_handle_.is_valid()) {
-              menu_model_->SetHighlightedIdentifier(highlighted_identifier);
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
 BEGIN_METADATA(AppMenuButton)
 END_METADATA
diff --git a/chrome/browser/ui/views/frame/app_menu_button.h b/chrome/browser/ui/views/frame/app_menu_button.h
index 1196fad7..a0849eb 100644
--- a/chrome/browser/ui/views/frame/app_menu_button.h
+++ b/chrome/browser/ui/views/frame/app_menu_button.h
@@ -11,7 +11,7 @@
 #include "base/observer_list.h"
 #include "base/timer/elapsed_timer.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
-#include "components/user_education/common/feature_promo/feature_promo_handle.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 
 class AppMenu;
@@ -66,11 +66,6 @@
                int run_flags);
 
  private:
-  // If there's an IPH attached to the menu button, when the menu opens, the IPH
-  // needs to close. In addition, some IPH then cause a particular item in the
-  // menu to become highlighted.
-  void MaybeCloseIphAndHighlight(Browser* browser);
-
   // App model and menu.
   // Note that the menu should be destroyed before the model it uses, so the
   // menu should be listed later.
@@ -82,7 +77,7 @@
   base::ObserverList<AppMenuButtonObserver>::Unchecked observer_list_;
 
   raw_ptr<views::MenuButtonController> menu_button_controller_;
-  user_education::FeaturePromoHandle promo_handle_;
+  ToolbarButtonMenuHighlighter highlighter_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_APP_MENU_BUTTON_H_
diff --git a/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.cc b/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.cc
new file mode 100644
index 0000000..c7ec7185
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.cc
@@ -0,0 +1,119 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/actions/chrome_action_id.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/search/omnibox_utils.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "chrome/grit/branded_strings.h"
+#include "components/omnibox/browser/omnibox_edit_model.h"
+#include "components/omnibox/browser/vector_icons.h"
+#include "components/vector_icons/vector_icons.h"
+#include "net/base/url_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/view_class_properties.h"
+#include "url/gurl.h"
+
+namespace {
+
+constexpr char kAiModeBaseUrl[] =
+    "https://www.google.com/search?sourceid=chrome&udm=50&aep=48";
+
+}
+
+AiModePageActionIconView::AiModePageActionIconView(
+    IconLabelBubbleView::Delegate* parent_delegate,
+    Delegate* delegate,
+    BrowserWindowInterface* browser)
+    : PageActionIconView(nullptr,
+                         0,
+                         parent_delegate,
+                         delegate,
+                         "AiMode",
+                         kActionAiMode),
+      browser_(browser) {
+  CHECK(browser_);
+  image_container_view()->SetFlipCanvasOnPaintForRTLUI(false);
+
+  SetProperty(views::kElementIdentifierKey, kAiModePageActionIconElementId);
+
+  SetLabel(l10n_util::GetStringUTF16(IDS_AI_MODE_ENTRYPOINT_LABEL));
+  SetUseTonalColorsWhenExpanded(true);
+  SetBackgroundVisibility(BackgroundVisibility::kWithLabel);
+}
+
+AiModePageActionIconView::~AiModePageActionIconView() = default;
+
+void AiModePageActionIconView::UpdateImpl() {
+  SetVisible(ShouldShow());
+  ResetSlideAnimation(true);
+}
+
+bool AiModePageActionIconView::ShouldShow() {
+  auto* web_contents = GetWebContents();
+  if (!web_contents) {
+    return false;
+  }
+  OmniboxView* omnibox_view = search::GetOmniboxView(web_contents);
+  if (!omnibox_view) {
+    return false;
+  }
+  // Show the AIM chip ONLY IF the Omnibox is visibly focused.
+  return omnibox_view->model()->is_caret_visible();
+}
+
+void AiModePageActionIconView::OnExecuting(
+    PageActionIconView::ExecuteSource source) {
+  GURL ai_mode_url = GURL(kAiModeBaseUrl);
+
+  auto* web_contents = GetWebContents();
+  CHECK(web_contents);
+  OmniboxView* omnibox_view = search::GetOmniboxView(web_contents);
+  CHECK(omnibox_view);
+
+  const auto match = omnibox_view->model()->CurrentMatch(nullptr);
+  if (AutocompleteMatch::IsSearchType(match.type) &&
+      !omnibox_view->model()->is_keyword_selected()) {
+    auto query_text = match.contents;
+    if (!query_text.empty()) {
+      ai_mode_url = net::AppendQueryParameter(ai_mode_url, "q",
+                                              base::UTF16ToUTF8(query_text));
+    }
+  }
+
+  // TODO(crbug.com/432744091): Replace direct URL navigation with invocation
+  // of OmniboxEditModel::OpenSelection().
+  // A transition type of `PAGE_TRANSITION_AUTO_BOOKMARK` is used here in order
+  // to signal that this URL is loaded as a result of the user clicking on a UI
+  // control (AIM page action button) which is located in the location bar.
+  web_contents->OpenURL(
+      content::OpenURLParams(
+          ai_mode_url, content::Referrer(), WindowOpenDisposition::CURRENT_TAB,
+          ui::PAGE_TRANSITION_AUTO_BOOKMARK, /*is_renderer_initiated=*/false),
+      /*navigation_handle_callback=*/{});
+}
+
+views::BubbleDialogDelegate* AiModePageActionIconView::GetBubble() const {
+  return nullptr;
+}
+
+const gfx::VectorIcon& AiModePageActionIconView::GetVectorIcon() const {
+  return omnibox::kSearchSparkIcon;
+}
+
+void AiModePageActionIconView::ExecuteWithKeyboardSourceForTesting() {
+  CHECK(GetVisible());
+  OnExecuting(EXECUTE_SOURCE_KEYBOARD);
+}
+
+BEGIN_METADATA(AiModePageActionIconView)
+END_METADATA
diff --git a/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.h b/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.h
new file mode 100644
index 0000000..7f567b0
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.h
@@ -0,0 +1,42 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AI_MODE_PAGE_ACTION_ICON_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AI_MODE_PAGE_ACTION_ICON_VIEW_H_
+
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+
+class BrowserWindowInterface;
+
+class AiModePageActionIconView : public PageActionIconView {
+  METADATA_HEADER(AiModePageActionIconView, PageActionIconView)
+
+ public:
+  AiModePageActionIconView(IconLabelBubbleView::Delegate* parent_delegate,
+                           Delegate* delegate,
+                           BrowserWindowInterface* browser);
+  AiModePageActionIconView(const AiModePageActionIconView&) = delete;
+  AiModePageActionIconView& operator=(const AiModePageActionIconView&) = delete;
+  ~AiModePageActionIconView() override;
+
+  // PageActionIconView:
+  views::BubbleDialogDelegate* GetBubble() const override;
+  void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
+  const gfx::VectorIcon& GetVectorIcon() const override;
+
+  void ExecuteWithKeyboardSourceForTesting();
+
+ protected:
+  // PageActionIconView:
+  void UpdateImpl() override;
+
+ private:
+  bool ShouldShow();
+
+  const raw_ptr<BrowserWindowInterface> browser_;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AI_MODE_PAGE_ACTION_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index c08ad2f..d59bc135 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -48,6 +48,7 @@
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/lens/lens_overlay_entry_point_controller.h"
 #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
+#include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h"
@@ -71,6 +72,7 @@
 #include "chrome/browser/ui/views/page_action/page_action_icon_container.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_params.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_properties_provider.h"
 #include "chrome/browser/ui/views/page_action/page_action_view_params.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_specification.h"
@@ -95,9 +97,12 @@
 #include "components/favicon/content/content_favicon_driver.h"
 #include "components/lens/lens_features.h"
 #include "components/omnibox/browser/location_bar_model.h"
+#include "components/omnibox/browser/omnibox_client.h"
+#include "components/omnibox/browser/omnibox_controller.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
+#include "components/omnibox/browser/omnibox_prefs.h"
 #include "components/omnibox/browser/omnibox_text_util.h"
 #include "components/omnibox/browser/vector_icons.h"
 #include "components/omnibox/common/omnibox_feature_configs.h"
@@ -109,6 +114,7 @@
 #include "components/permissions/permission_request_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/features.h"
+#include "components/search/search.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/security_state/content/security_state_tab_helper.h"
@@ -446,6 +452,19 @@
                                 PageActionIconType::kLensOverlayHomework);
   }
 
+  // - Restricted to DSE Google.
+  // - Restricted to locale EN.
+  // - Restricted to when `kAIModeSettings` policy is enabled.
+  OmniboxClient* client = omnibox_view_->controller()->client();
+  if (browser_ &&
+      base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint) &&
+      search::DefaultSearchProviderIsGoogle(client->GetTemplateURLService()) &&
+      l10n_util::GetLanguage(g_browser_process->GetApplicationLocale()) ==
+          "en" &&
+      omnibox::IsAimAllowedByPolicy(client->GetPrefs())) {
+    params.types_enabled.push_back(PageActionIconType::kAiMode);
+  }
+
   if (browser_ && tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) {
     params.types_enabled.push_back(PageActionIconType::kCollaborationMessaging);
   }
@@ -1129,7 +1148,7 @@
       browser_view->toolbar()->pinned_toolbar_actions_container();
   return pinned_toolbar_actions_container &&
          pinned_toolbar_actions_container->IsActionPinnedOrPoppedOut(
-             icon_view->action_id().value());
+             icon_view->action_id().value_or(-1));
 }
 
 // static
@@ -1282,6 +1301,14 @@
   return visibility_changed;
 }
 
+void LocationBarView::RefreshAimPageActionIcon() {
+  PageActionIconView* aim_page_action_icon_view =
+      page_action_icon_controller_->GetIconView(PageActionIconType::kAiMode);
+  if (aim_page_action_icon_view) {
+    aim_page_action_icon_view->Update();
+  }
+}
+
 void LocationBarView::RefreshPageActionIconViews() {
   if (web_app::AppBrowserController::IsWebApp(browser_)) {
     // For web apps, the location bar is normally hidden and icons appear in
@@ -1557,6 +1584,9 @@
   // the omnibox is intentional, snapping is better than transitioning here.
   hover_animation_.Reset();
   RefreshBackground();
+
+  // Ensure AIM page action button reacts to changes in Omnibox focus state.
+  RefreshAimPageActionIcon();
 }
 
 void LocationBarView::OnOmniboxBlurred() {
@@ -1564,6 +1594,9 @@
     views::FocusRing::Get(this)->SchedulePaint();
   }
   RefreshBackground();
+
+  // Ensure AIM page action button reacts to changes in Omnibox focus state.
+  RefreshAimPageActionIcon();
 }
 
 void LocationBarView::OnOmniboxHovered(bool is_hovering) {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 98a005a9..d47fe124 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -315,6 +315,9 @@
   // of at least one of the views in |content_setting_views_| changed.
   bool RefreshContentSettingViews();
 
+  // Updates the visibility state of the AIM page action button in particular.
+  void RefreshAimPageActionIcon();
+
   // Updates the visibility state of the PageActionIconViews to reflect what
   // actions are available on the current page.
   void RefreshPageActionIconViews();
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc
index b73bc0f..22f5b7d 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/ui/views/commerce/price_tracking_icon_view.h"
 #include "chrome/browser/ui/views/commerce/product_specifications_icon_view.h"
 #include "chrome/browser/ui/views/file_system_access/file_system_access_icon_view.h"
+#include "chrome/browser/ui/views/location_bar/ai_mode_page_action_icon_view.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.h"
 #include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 #include "chrome/browser/ui/views/location_bar/intent_picker_view.h"
@@ -276,6 +277,12 @@
                       params.browser, params.icon_label_bubble_delegate,
                       params.page_action_icon_delegate));
         break;
+      case PageActionIconType::kAiMode:
+        add_page_action_icon(
+            type, std::make_unique<AiModePageActionIconView>(
+                      params.icon_label_bubble_delegate,
+                      params.page_action_icon_delegate, params.browser));
+        break;
       case PageActionIconType::kLensOverlayHomework:
         add_page_action_icon(
             type, std::make_unique<LensOverlayHomeworkPageActionIconView>(
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
index 6f16f76..351ae70 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/command_updater.h"
+#include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/omnibox/omnibox_theme.h"
 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
@@ -256,9 +257,13 @@
 }
 
 void PageActionIconView::Update() {
-  // Currently no page action icon should be visible during user input.
-  // A future subclass may need a hook here if that changes.
-  if (delegate_->ShouldHidePageActionIcons()) {
+  // In general, no page action icon should be visible during user input.
+  // However, the AIM page action is an exception to this rule since it has
+  // special visibility criteria.
+  // TODO(crbug.com/432744091): Roll the AIM button edge-case logic into the
+  // implementation of `ShouldHidePageActionIcons()`.
+  if (delegate_->ShouldHidePageActionIcons() &&
+      this->action_id_ != kActionAiMode) {
     ResetSlideAnimation(/*show=*/false);
     SetVisible(false);
   } else {
diff --git a/chrome/browser/ui/views/page_info/about_this_site_side_panel_coordinator.cc b/chrome/browser/ui/views/page_info/about_this_site_side_panel_coordinator.cc
index 186abbdd..1bc14878 100644
--- a/chrome/browser/ui/views/page_info/about_this_site_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/page_info/about_this_site_side_panel_coordinator.cc
@@ -90,7 +90,7 @@
             &AboutThisSideSidePanelCoordinator::GetOpenInNewTabUrl,
             base::Unretained(this)),
         /*more_info_callback=*/base::NullCallback(),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     registry->Register(std::move(entry));
   }
 }
diff --git a/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator.cc b/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator.cc
index 9ea118c9..26ad6c7a 100644
--- a/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/page_info/merchant_trust_side_panel_coordinator.cc
@@ -86,7 +86,7 @@
             &MerchantTrustSidePanelCoordinator::GetOpenInNewTabUrl,
             base::Unretained(this)),
         /*more_info_callback=*/base::NullCallback(),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     registry->Register(std::move(entry));
   }
 }
diff --git a/chrome/browser/ui/views/side_panel/bookmarks/bookmarks_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/bookmarks/bookmarks_side_panel_coordinator.cc
index 75f9791..cc464dc 100644
--- a/chrome/browser/ui/views/side_panel/bookmarks/bookmarks_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/bookmarks/bookmarks_side_panel_coordinator.cc
@@ -40,7 +40,7 @@
       base::BindRepeating(
           &BookmarksSidePanelCoordinator::CreateBookmarksWebView,
           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
 
 std::unique_ptr<views::View>
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc
index 462bfc1..6c02761 100644
--- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc
@@ -49,28 +49,49 @@
     TabStripModel* tab_strip_model,
     const TabStripModelChange& change,
     const TabStripSelectionChange& selection) {
-  // TODO(crbug.com/433773768): This should also handle when the current tab
-  // group becomes shared or when the active tab is added to a shared group.
-  if (selection.active_tab_changed()) {
-    // Only update the title if change contains a new tab.
-    if (selection.new_tab) {
-      UpdateSidePanelTitle(GetSharedTabGroupName(selection.new_tab));
-    }
-
-    const bool should_show_comments_action =
-        ShouldShowCommentsAction(selection);
-    UpdateCommentsActionVisibility(should_show_comments_action);
-    UpdateCommentsSidePanelVisibility(should_show_comments_action);
+  // Only handle changing the active tab.
+  if (!selection.active_tab_changed()) {
+    return;
   }
+
+  UpdateVisuals(selection.new_tab);
+}
+
+void CommentsSidePanelCoordinator::TabGroupedStateChanged(
+    TabStripModel* tab_strip_model,
+    std::optional<tab_groups::TabGroupId> old_group,
+    std::optional<tab_groups::TabGroupId> new_group,
+    tabs::TabInterface* tab,
+    int index) {
+  // Only handle group changes to the active tab.
+  if (!tab->IsActivated() || old_group == new_group) {
+    return;
+  }
+
+  UpdateVisuals(tab);
+}
+
+// TODO(crbug.com/433773768): This should also be called when the current tab
+// group becomes shared/unshared.
+void CommentsSidePanelCoordinator::UpdateVisuals(
+    const tabs::TabInterface* tab) {
+  // Only update the title if change contains a new tab.
+  if (tab) {
+    UpdateSidePanelTitle(GetSharedTabGroupName(tab));
+  }
+
+  const bool should_show_comments_action = ShouldShowCommentsAction(tab);
+  UpdateCommentsActionVisibility(should_show_comments_action);
+  UpdateCommentsSidePanelVisibility(should_show_comments_action);
 }
 
 bool CommentsSidePanelCoordinator::ShouldShowCommentsAction(
-    const TabStripSelectionChange& selection) {
-  if (!selection.new_tab) {
+    const tabs::TabInterface* tab) {
+  if (!tab) {
     return false;
   }
 
-  std::optional<tab_groups::TabGroupId> group = selection.new_tab->GetGroup();
+  std::optional<tab_groups::TabGroupId> group = tab->GetGroup();
   if (!group.has_value()) {
     return false;
   }
@@ -193,7 +214,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kComments),
       base::BindRepeating(&CommentsSidePanelCoordinator::CreateCommentsWebView,
                           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
 
 std::unique_ptr<views::View>
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h
index a1f38f9f..cbd450b 100644
--- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h
@@ -40,6 +40,11 @@
       TabStripModel* tab_strip_model,
       const TabStripModelChange& change,
       const TabStripSelectionChange& selection) override;
+  void TabGroupedStateChanged(TabStripModel* tab_strip_model,
+                              std::optional<tab_groups::TabGroupId> old_group,
+                              std::optional<tab_groups::TabGroupId> new_group,
+                              tabs::TabInterface* tab,
+                              int index) override;
 
   // Returns whether CommentsSidePanelCoordinator is supported.
   // If this returns false, it should not be registered with the side
@@ -57,7 +62,10 @@
 
   // Determine if the comments action should be shown in the toolbar for the
   // active tab.
-  bool ShouldShowCommentsAction(const TabStripSelectionChange& selection);
+  bool ShouldShowCommentsAction(const tabs::TabInterface* tab);
+
+  // Updates the visuals of the comments action and side panel.
+  void UpdateVisuals(const tabs::TabInterface* tab);
 
   // Updates the visibility of the comments action in the toolbar.
   void UpdateCommentsActionVisibility(bool should_show_comments_action);
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc
index 287f61d..fa89c2f 100644
--- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc
+++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc
@@ -168,6 +168,34 @@
       WaitForShow(kSharedTabGroupCommentsActionElementId));
 }
 
+// Verify the comments action is shown when a tab is added to a shared group.
+IN_PROC_BROWSER_TEST_F(CommentsSidePanelCoordinatorInteractiveUiTest,
+                       CommentActionIsVisible_AddingTabToGroup) {
+  tab_groups::TabGroupId group_id = CreateNewTabGroup();
+  ShareTabGroup(group_id, syncer::CollaborationId("fake_collaboration_id"),
+                data_sharing::MemberRole::kOwner, /*should_sign_in=*/false);
+
+  // Simplest way to add a tab to group is to add the tab at the beginning of
+  // the tab strip and drag it to group header to its right.
+  EXPECT_TRUE(
+      AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED));
+  const int ungrouped_tab_index = 0;
+
+  browser()->tab_strip_model()->ActivateTabAt(ungrouped_tab_index);
+
+  RunTestSequence(WaitForShow(kTabGroupHeaderElementId),
+                  EnsureNotPresent(kSharedTabGroupCommentsActionElementId),
+                  HoverTabAt(ungrouped_tab_index),
+                  DragMouseTo(kTabGroupHeaderElementId), Do([&]() {
+                    // Verify the tab was added to the group.
+                    TabGroupModel* tab_group_model =
+                        browser()->tab_strip_model()->group_model();
+                    EXPECT_EQ(
+                        tab_group_model->GetTabGroup(group_id)->tab_count(), 2);
+                  }),
+                  WaitForShow(kSharedTabGroupCommentsActionElementId));
+}
+
 // Verify the comments side panel will resume visilibity when switching to a
 // non-shared tab and back.
 IN_PROC_BROWSER_TEST_F(CommentsSidePanelCoordinatorInteractiveUiTest,
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc
index dc26434..b4211d8 100644
--- a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc
+++ b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc
@@ -146,7 +146,7 @@
       base::BindRepeating(
           &SidePanelControllerViews::CreateCustomizeChromeWebView,
           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth);
+      /*default_content_width_callback=*/base::NullCallback());
   entry->AddObserver(this);
   registry->Register(std::move(entry));
 }
diff --git a/chrome/browser/ui/views/side_panel/extensions/extension_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/extensions/extension_side_panel_coordinator.cc
index 2f136d5e..782e4953 100644
--- a/chrome/browser/ui/views/side_panel/extensions/extension_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/extensions/extension_side_panel_coordinator.cc
@@ -211,7 +211,7 @@
       GetEntryKey(),
       base::BindRepeating(&ExtensionSidePanelCoordinator::CreateView,
                           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
 
 std::unique_ptr<views::View> ExtensionSidePanelCoordinator::CreateView(
diff --git a/chrome/browser/ui/views/side_panel/history/history_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/history/history_side_panel_coordinator.cc
index 72adb6b..84c8154 100644
--- a/chrome/browser/ui/views/side_panel/history/history_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/history/history_side_panel_coordinator.cc
@@ -54,7 +54,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kHistory),
       base::BindRepeating(&HistorySidePanelCoordinator::CreateHistoryWebView,
                           base::Unretained(this)),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
 
 std::unique_ptr<views::View> HistorySidePanelCoordinator::CreateHistoryWebView(
diff --git a/chrome/browser/ui/views/side_panel/history_clusters/history_clusters_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/history_clusters/history_clusters_side_panel_coordinator.cc
index 20cc79c..7c26092 100644
--- a/chrome/browser/ui/views/side_panel/history_clusters/history_clusters_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/history_clusters/history_clusters_side_panel_coordinator.cc
@@ -77,7 +77,7 @@
           &HistoryClustersSidePanelCoordinator::GetOpenInNewTabURL,
           base::Unretained(this)),
       /*more_info_callback=*/base::NullCallback(),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
 
 std::unique_ptr<views::View>
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.cc
index a31317e..fa65a8e 100644
--- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.cc
+++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.cc
@@ -29,6 +29,7 @@
 #include "components/language/core/browser/language_model_manager.h"
 #include "components/language/core/common/locale_util.h"
 #include "components/user_education/common/feature_promo/feature_promo_controller.h"
+#include "read_anything_side_panel_controller.h"
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_types.h"
@@ -58,10 +59,9 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kReadAnything),
       base::BindRepeating(&ReadAnythingSidePanelController::CreateContainerView,
                           base::Unretained(this)),
-      // Use the max width allowed.
-      // BrowserViewLayout::CalculateContentsContainerLayout will clamp the
-      // value to the max allowed.
-      SHRT_MAX);
+      base::BindRepeating(
+          &ReadAnythingSidePanelController::GetPreferredDefaultWidth,
+          base::Unretained(this)));
   side_panel_entry->AddObserver(this);
   side_panel_registry_->Register(std::move(side_panel_entry));
 
@@ -166,6 +166,13 @@
   return std::move(web_view);
 }
 
+int ReadAnythingSidePanelController::GetPreferredDefaultWidth() {
+  // Use the max width allowed.
+  // BrowserViewLayout::CalculateContentsContainerLayout will clamp the
+  // value to the max allowed.
+  return SHRT_MAX;
+}
+
 bool ReadAnythingSidePanelController::IsActivePageDistillable() const {
   auto url = tab_->GetContents()->GetLastCommittedURL();
 
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h
index 9736d1f..e4d1b27e 100644
--- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h
+++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h
@@ -95,6 +95,9 @@
   // Creates the container view and all its child views for side panel entry.
   std::unique_ptr<views::View> CreateContainerView(SidePanelEntryScope& scope);
 
+  // Returns the preferred default width for the side panel.
+  int GetPreferredDefaultWidth();
+
   // Decides whether the active page is distillable.
   bool IsActivePageDistillable() const;
 
diff --git a/chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.cc
index 372b8ce..c7504e02 100644
--- a/chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.cc
@@ -38,5 +38,5 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kReadingList),
       base::BindRepeating(&CreateReadingListWebView, &profile_.get(),
                           &tab_strip_model_.get()),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 }
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator_browsertest.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator_browsertest.cc
index fc1ea13..5341e24 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator_browsertest.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator_browsertest.cc
@@ -82,7 +82,7 @@
       key, base::BindRepeating([](SidePanelEntryScope&) {
         return std::make_unique<views::View>();
       }),
-      SidePanelEntry::kSidePanelDefaultContentWidth);
+      /*default_content_width_callback=*/base::NullCallback());
 }
 
 }  // namespace
@@ -107,7 +107,7 @@
         base::BindRepeating([](SidePanelEntryScope&) {
           return std::make_unique<views::View>();
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth));
+        /*default_content_width_callback=*/base::NullCallback()));
     contextual_registries_.push_back(registry);
 
     // Add some entries to the second tab.
@@ -121,7 +121,7 @@
         base::BindRepeating([](SidePanelEntryScope&) {
           return std::make_unique<views::View>();
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth));
+        /*default_content_width_callback=*/base::NullCallback()));
     contextual_registries_.push_back(browser()
                                          ->GetActiveTabInterface()
                                          ->GetTabFeatures()
@@ -139,13 +139,13 @@
           return std::unique_ptr<ui::MenuModel>(
               new ui::SimpleMenuModel(nullptr));
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth));
+        /*default_content_width_callback=*/base::NullCallback()));
     registry->Register(std::make_unique<SidePanelEntry>(
         SidePanelEntry::Key(SidePanelEntry::Id::kShoppingInsights),
         base::BindRepeating([](SidePanelEntryScope&) {
           return std::make_unique<views::View>();
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth));
+        /*default_content_width_callback=*/base::NullCallback()));
 
     coordinator()->SetNoDelaysForTesting(true);
   }
@@ -159,7 +159,7 @@
         base::BindRepeating([](SidePanelEntryScope&) {
           return std::make_unique<views::View>();
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth));
+        /*default_content_width_callback=*/base::NullCallback()));
     contextual_registries_.push_back(registry);
   }
 
@@ -1620,7 +1620,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kAboutThisSite),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth);
+      /*default_content_width_callback=*/base::NullCallback());
   entry->AddObserver(observer.get());
   contextual_registries_[0]->Register(std::move(entry));
   coordinator()->Show(SidePanelEntry::Id::kAboutThisSite);
@@ -1651,7 +1651,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kAboutThisSite),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth);
+      /*default_content_width_callback=*/base::NullCallback());
   entry->AddObserver(observer.get());
   contextual_registries_[0]->Register(std::move(entry));
   coordinator()->Show(SidePanelEntry::Id::kAboutThisSite);
@@ -1684,7 +1684,7 @@
             return std::make_unique<views::View>();
           },
           &count),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
   coordinator()->Show(SidePanelEntry::Id::kLens);
   ASSERT_EQ(1, count);
   coordinator()->Show(SidePanelEntry::Id::kLens);
@@ -2056,7 +2056,7 @@
               ->SetAvailable(false);
           return view;
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     loading_content_entry1_ = entry1.get();
     EXPECT_TRUE(global_registry()->Register(std::move(entry1)));
 
@@ -2070,7 +2070,7 @@
               ->SetAvailable(false);
           return view;
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     loading_content_entry2_ = entry2.get();
     EXPECT_TRUE(global_registry()->Register(std::move(entry2)));
 
@@ -2083,7 +2083,7 @@
               ->SetAvailable(true);
           return view;
         }),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     loaded_content_entry1_ = entry3.get();
     EXPECT_TRUE(global_registry()->Register(std::move(entry3)));
   }
diff --git a/chrome/browser/ui/views/side_panel/side_panel_entry.cc b/chrome/browser/ui/views/side_panel/side_panel_entry.cc
index 2e3a95a..e2d3675 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_entry.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_entry.cc
@@ -19,28 +19,24 @@
     base::RepeatingCallback<GURL()> open_in_new_tab_url_callback,
     base::RepeatingCallback<std::unique_ptr<ui::MenuModel>()>
         more_info_callback,
-    int default_content_width)
+    base::RepeatingCallback<int()> default_content_width_callback)
     : key_(key),
       create_content_callback_(std::move(create_content_callback)),
       open_in_new_tab_url_callback_(std::move(open_in_new_tab_url_callback)),
       more_info_callback_(std::move(more_info_callback)),
-      default_content_width_(default_content_width) {
+      default_content_width_callback_(default_content_width_callback) {
   DCHECK(create_content_callback_);
-  CHECK(!default_content_width ||
-        default_content_width >= kSidePanelDefaultContentWidth)
-      << "The default width must be greater than or equal to the default side "
-         "panel width: "
-      << kSidePanelDefaultContentWidth;
 }
 
-SidePanelEntry::SidePanelEntry(Key key,
-                               CreateContentCallback create_content_callback,
-                               int default_content_width)
+SidePanelEntry::SidePanelEntry(
+    Key key,
+    CreateContentCallback create_content_callback,
+    base::RepeatingCallback<int()> default_content_width_callback)
     : SidePanelEntry(key,
                      std::move(create_content_callback),
                      base::NullCallback(),
                      base::NullCallback(),
-                     default_content_width) {}
+                     default_content_width_callback) {}
 
 SidePanelEntry::~SidePanelEntry() = default;
 
@@ -118,5 +114,14 @@
 }
 
 int SidePanelEntry::GetDefaultContentWidth() const {
-  return default_content_width_;
+  if (default_content_width_callback_.is_null()) {
+    return default_content_width_;
+  }
+
+  int preferred_default_width = default_content_width_callback_.Run();
+  // The default width must be greater than or equal to the default side panel
+  // width.
+  return preferred_default_width >= kSidePanelDefaultContentWidth
+             ? preferred_default_width
+             : default_content_width_;
 }
diff --git a/chrome/browser/ui/views/side_panel/side_panel_entry.h b/chrome/browser/ui/views/side_panel/side_panel_entry.h
index 12527f8..2b2aa09c 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_entry.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_entry.h
@@ -46,7 +46,7 @@
                  base::RepeatingCallback<GURL()> open_in_new_tab_url_callback,
                  base::RepeatingCallback<std::unique_ptr<ui::MenuModel>()>
                      more_info_callback,
-                 int default_content_width);
+                 base::RepeatingCallback<int()> default_content_width_callback);
 
   // This constructor is primarily used for extensions.Extensions don't have
   // `Open in New Tab` functionality. Other side panels can use this if nothing
@@ -54,7 +54,7 @@
   // base::NullCallback()).
   SidePanelEntry(Key key,
                  CreateContentCallback create_content_callback,
-                 int default_content_width);
+                 base::RepeatingCallback<int()> default_content_width_callback);
   SidePanelEntry(const SidePanelEntry&) = delete;
   SidePanelEntry& operator=(const SidePanelEntry&) = delete;
   ~SidePanelEntry() override;
@@ -127,6 +127,12 @@
   // If this returns null, the more info button is hidden.
   base::RepeatingCallback<std::unique_ptr<ui::MenuModel>()> more_info_callback_;
 
+  // When specified sets the default starting width for this entry. However, if
+  // the user manually changes the size of the side panel that preference is
+  // used instead (prefs::kSidePanelIdToWidth). If nothing is specified, then
+  // the default minimum content width of the side panel is used.
+  base::RepeatingCallback<int()> default_content_width_callback_;
+
   // Timestamp of when the side panel was triggered to be shown.
   base::TimeTicks entry_show_triggered_timestamp_;
 
@@ -134,10 +140,10 @@
 
   base::ObserverList<SidePanelEntryObserver> observers_;
 
-  // When specified sets the default starting width for this entry. However, if
-  // the user manually changes the size of the side panel that preference is
-  // used instead (prefs::kSidePanelIdToWidth). If nothing is specified, then
-  // the default minimum content width of the side panel is used.
+  // The default minimum content width for the side panel that can be overridden
+  // for testing. This is used if the default_content_width_callback_ is not
+  // set. However, if the user manually changes the size of the side panel that
+  // preference is used instead (prefs::kSidePanelIdToWidth).
   int default_content_width_ = kSidePanelDefaultContentWidth;
 
   base::WeakPtrFactory<SidePanelEntry> weak_factory_{this};
diff --git a/chrome/browser/ui/views/side_panel/side_panel_interactive_uitest.cc b/chrome/browser/ui/views/side_panel/side_panel_interactive_uitest.cc
index 003adf2..004ca36 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_interactive_uitest.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_interactive_uitest.cc
@@ -95,7 +95,7 @@
             base::BindRepeating([](SidePanelEntryScope&) {
               return std::make_unique<views::View>();
             }),
-            SidePanelEntry::kSidePanelDefaultContentWidth));
+            /*default_content_width_callback=*/base::NullCallback()));
         coordinator->Show(SidePanelEntry::Id::kCustomizeChrome);
       })),
       WaitForShow(kSidePanelElementId),
@@ -235,7 +235,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kReadAnything),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 
   SidePanelCoordinator* const coordinator =
       browser()->GetFeatures().side_panel_coordinator();
@@ -263,7 +263,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kCustomizeChrome),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 
   SidePanelCoordinator* const coordinator =
       browser()->GetFeatures().side_panel_coordinator();
@@ -289,7 +289,7 @@
       SidePanelEntry::Key(SidePanelEntry::Id::kHistoryClusters),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 
   SidePanelCoordinator* const coordinator =
       browser()->GetFeatures().side_panel_coordinator();
@@ -355,7 +355,7 @@
       SidePanelEntryKey(SidePanelEntry::Id::kReadAnything),
       base::BindRepeating(
           [](SidePanelEntryScope&) { return std::make_unique<views::View>(); }),
-      SidePanelEntry::kSidePanelDefaultContentWidth));
+      /*default_content_width_callback=*/base::NullCallback()));
 
   PinnedToolbarActionsModel* const actions_model =
       PinnedToolbarActionsModel::Get(browser()->profile());
diff --git a/chrome/browser/ui/views/side_panel/side_panel_web_ui_view_browsertest.cc b/chrome/browser/ui/views/side_panel/side_panel_web_ui_view_browsertest.cc
index 1e94810..dfaff6ad 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_web_ui_view_browsertest.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_web_ui_view_browsertest.cc
@@ -90,7 +90,7 @@
                   scope, std::make_unique<TestWebUIContentsWrapper>(profile));
             },
             browser()->profile()),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
 
     GetSidePanelCoordinator()->GetWindowRegistry()->Register(std::move(entry));
   }
@@ -107,7 +107,7 @@
                   scope, std::make_unique<TestWebUIContentsWrapper>(profile));
             },
             browser()->profile()),
-        SidePanelEntry::kSidePanelDefaultContentWidth);
+        /*default_content_width_callback=*/base::NullCallback());
     browser()
         ->tab_strip_model()
         ->GetActiveTab()
diff --git a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc
index 855fc48f..d4109c8 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc
+++ b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc
@@ -6,14 +6,18 @@
 
 #include "base/containers/contains.h"
 #include "base/feature_list.h"
+#include "base/functional/bind.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "components/tabs/public/tab_interface.h"
 #include "content/public/browser/browser_thread.h"
+#include "ui/base/unowned_user_data/scoped_unowned_user_data.h"
 #include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/rect.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "ui/views/widget/native_widget_aura.h"
@@ -40,58 +44,24 @@
         GetColorProvider()->GetColor(kColorCapturedTabContentsBorder)));
   }
 };
-
-void InitContentsBorderWidget(content::WebContents* web_contents) {
-  Browser* const browser = chrome::FindBrowserWithTab(web_contents);
-  if (!browser) {
-    return;
-  }
-
-  BrowserView* const browser_view =
-      BrowserView::GetBrowserViewForBrowser(browser);
-  if (!browser_view || browser_view->contents_border_widget()) {
-    return;
-  }
-
-  views::Widget* widget = new views::Widget;
-  views::Widget::InitParams params(
-      views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET,
-      views::Widget::InitParams::TYPE_POPUP);
-  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
-  views::Widget* frame = browser_view->contents_web_view()->GetWidget();
-  params.parent = frame->GetNativeView();
-  params.context = frame->GetNativeWindow();
-  // Make the widget non-top level.
-  params.child = true;
-  params.name = "TabSharingContentsBorder";
-  params.remove_standard_frame = true;
-  // Let events go through to underlying view.
-  params.accept_events = false;
-  params.activatable = views::Widget::InitParams::Activatable::kNo;
-#if BUILDFLAG(IS_WIN)
-  params.native_widget = new views::NativeWidgetAura(widget);
-#endif  // BUILDFLAG(IS_WIN)
-
-  widget->Init(std::move(params));
-  widget->SetContentsView(std::make_unique<BorderView>());
-  widget->SetVisibilityChangedAnimationsEnabled(false);
-  widget->SetOpacity(0.50f);
-
-  // TODO(crbug.com/40207590): Associate each captured tab with its own widget.
-  // Otherwise, if tab A captures B, and tab C captures D, and all are in
-  // the same browser window, then either the A<-B or C<-D sessions ending,
-  // hides the widget, and there's no good way of avoiding it (other than
-  // associating distinct captured tabs with their own border).
-  // After this fix, capturing a given tab X twice will still yield one widget.
-  browser_view->set_contents_border_widget(widget);
-}
-
 }  // namespace
 
+DEFINE_USER_DATA(TabCaptureContentsBorderHelper);
+
+// static:
+TabCaptureContentsBorderHelper* TabCaptureContentsBorderHelper::From(
+    tabs::TabInterface* tab_interface) {
+  return Get(tab_interface->GetUnownedUserDataHost());
+}
+
 TabCaptureContentsBorderHelper::TabCaptureContentsBorderHelper(
-    content::WebContents* web_contents)
-    : content::WebContentsUserData<TabCaptureContentsBorderHelper>(
-          *web_contents) {}
+    tabs::TabInterface& tab_interface)
+    : tab_interface_(tab_interface),
+      scoped_unowned_user_data_(tab_interface.GetUnownedUserDataHost(), *this) {
+  tab_will_detach_subscription_ = tab_interface_->RegisterWillDetach(
+      base::BindRepeating(&TabCaptureContentsBorderHelper::TabWillDetach,
+                          base::Unretained(this)));
+}
 
 TabCaptureContentsBorderHelper::~TabCaptureContentsBorderHelper() = default;
 
@@ -139,6 +109,52 @@
   UpdateBlueBorderLocation();
 }
 
+void TabCaptureContentsBorderHelper::InitContentsBorderWidget() {
+  Browser* const browser =
+      tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly();
+  if (!browser) {
+    return;
+  }
+
+  BrowserView* const browser_view =
+      BrowserView::GetBrowserViewForBrowser(browser);
+  if (!browser_view || browser_view->contents_border_widget()) {
+    return;
+  }
+
+  views::Widget* widget = new views::Widget;
+  views::Widget::InitParams params(
+      views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET,
+      views::Widget::InitParams::TYPE_POPUP);
+  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
+  views::Widget* frame = browser_view->contents_web_view()->GetWidget();
+  params.parent = frame->GetNativeView();
+  params.context = frame->GetNativeWindow();
+  // Make the widget non-top level.
+  params.child = true;
+  params.name = "TabSharingContentsBorder";
+  params.remove_standard_frame = true;
+  // Let events go through to underlying view.
+  params.accept_events = false;
+  params.activatable = views::Widget::InitParams::Activatable::kNo;
+#if BUILDFLAG(IS_WIN)
+  params.native_widget = new views::NativeWidgetAura(widget);
+#endif  // BUILDFLAG(IS_WIN)
+
+  widget->Init(std::move(params));
+  widget->SetContentsView(std::make_unique<BorderView>());
+  widget->SetVisibilityChangedAnimationsEnabled(false);
+  widget->SetOpacity(0.50f);
+
+  // TODO(crbug.com/40207590): Associate each captured tab with its own widget.
+  // Otherwise, if tab A captures B, and tab C captures D, and all are in
+  // the same browser window, then either the A<-B or C<-D sessions ending,
+  // hides the widget, and there's no good way of avoiding it (other than
+  // associating distinct captured tabs with their own border).
+  // After this fix, capturing a given tab X twice will still yield one widget.
+  browser_view->set_contents_border_widget(widget);
+}
+
 void TabCaptureContentsBorderHelper::Update() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -150,22 +166,15 @@
     return;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
-
-  content::WebContents* const web_contents = &GetWebContents();
-
-  Browser* const browser = chrome::FindBrowserWithTab(web_contents);
-  if (!browser) {
-    return;
-  }
-
+  Browser* const browser =
+      tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly();
   BrowserView* const browser_view =
       BrowserView::GetBrowserViewForBrowser(browser);
   if (!browser_view) {
     return;
   }
 
-  const bool tab_visible =
-      (web_contents == browser->tab_strip_model()->GetActiveWebContents());
+  const bool tab_visible = tab_interface_->IsActivated();
   const bool contents_border_needed =
       tab_visible && !session_to_bounds_.empty();
 
@@ -173,7 +182,7 @@
     if (!contents_border_needed) {
       return;
     }
-    InitContentsBorderWidget(web_contents);
+    InitContentsBorderWidget();
   }
 
   views::Widget* const contents_border_widget =
@@ -190,13 +199,8 @@
 void TabCaptureContentsBorderHelper::UpdateBlueBorderLocation() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!session_to_bounds_.empty()) << "No blue border should be shown.";
-
-  content::WebContents* const web_contents = &GetWebContents();
-
-  Browser* const browser = chrome::FindBrowserWithTab(web_contents);
-  if (!browser) {
-    return;
-  }
+  Browser* const browser =
+      tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly();
 
   BrowserView* const browser_view =
       BrowserView::GetBrowserViewForBrowser(browser);
@@ -219,4 +223,9 @@
                                            : std::nullopt;
 }
 
-WEB_CONTENTS_USER_DATA_KEY_IMPL(TabCaptureContentsBorderHelper);
+void TabCaptureContentsBorderHelper::TabWillDetach(
+    tabs::TabInterface* tab_interface,
+    tabs::TabInterface::DetachReason reason) {
+  session_to_bounds_.clear();
+  Update();
+}
diff --git a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h
index 27fdfb0..523cd54 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h
+++ b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h
@@ -5,24 +5,32 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_
 #define CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_
 
-#include "content/public/browser/web_contents_user_data.h"
+#include "base/callback_list.h"
+#include "base/memory/raw_ref.h"
+#include "components/tabs/public/tab_interface.h"
+#include "ui/base/unowned_user_data/scoped_unowned_user_data.h"
 
-namespace content {
-class WebContents;
+namespace gfx {
+class Rect;
 }
 
 // Helps track whether the contents-border should be drawn.
 // TODO(crbug.com/40207590): Support dynamic borders for tabs that only
 // have a single capturer.
-class TabCaptureContentsBorderHelper
-    : public content::WebContentsUserData<TabCaptureContentsBorderHelper> {
+class TabCaptureContentsBorderHelper {
  public:
+  DECLARE_USER_DATA(TabCaptureContentsBorderHelper);
+
+  static TabCaptureContentsBorderHelper* From(
+      tabs::TabInterface* tab_interface);
+
   // Used to identify |TabSharingUIViews| instances to
   // |TabCaptureContentsBorderHelper|, without passing pointers,
   // which is less robust lifetime-wise.
   using CaptureSessionId = uint32_t;
 
-  ~TabCaptureContentsBorderHelper() override;
+  explicit TabCaptureContentsBorderHelper(tabs::TabInterface& tab_interface);
+  ~TabCaptureContentsBorderHelper();
 
   void OnCapturerAdded(CaptureSessionId capture_session_id);
   void OnCapturerRemoved(CaptureSessionId capture_session_id);
@@ -34,9 +42,7 @@
       const std::optional<gfx::Rect>& region_capture_rect);
 
  private:
-  friend WebContentsUserData;
-
-  explicit TabCaptureContentsBorderHelper(content::WebContents* web_contents);
+  void InitContentsBorderWidget();
 
   // Decide whether the blue border should be shown, and where.
   void Update();
@@ -44,7 +50,7 @@
   // Given that the blue border should be shown, draw it at the right location.
   void UpdateBlueBorderLocation();
 
-  // Determines the correct location of the ble border.
+  // Determines the correct location of the blue border.
   // 1. If multiple captures of the WebContents exist, the blue border is drawn
   //    around the entire tab's content area.
   // 2. If a single capture of the WebContents exists, the blue border
@@ -53,6 +59,9 @@
   //    and aroun  the cropped area if cropping is used.
   std::optional<gfx::Rect> GetBlueBorderLocation() const;
 
+  void TabWillDetach(tabs::TabInterface* tab_interface,
+                     tabs::TabInterface::DetachReason reason);
+
   // Each capture session has a unique |uint32_t| ID, and is mapped to
   // an optional<Rect>, whose value is as follows:
   // * If the capture session's last known state was uncropped - nullopt.
@@ -61,7 +70,12 @@
   //   capture-target consisted of zero pixels within the viewport.
   std::map<CaptureSessionId, std::optional<gfx::Rect>> session_to_bounds_;
 
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
+  raw_ref<tabs::TabInterface> tab_interface_;
+
+  base::CallbackListSubscription tab_will_detach_subscription_;
+
+  ui::ScopedUnownedUserData<TabCaptureContentsBorderHelper>
+      scoped_unowned_user_data_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
index ccba212..cd9c4cfa 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
+++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h"
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/infobars/core/infobar.h"
+#include "components/tabs/public/tab_interface.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/desktop_media_id.h"
@@ -255,12 +256,8 @@
     return;
   }
 
-  auto* const helper =
-      TabCaptureContentsBorderHelper::FromWebContents(shared_tab_);
-  if (!helper) {
-    return;
-  }
-
+  auto* const helper = TabCaptureContentsBorderHelper::From(
+      tabs::TabInterface::GetFromContents(shared_tab_));
   helper->OnRegionCaptureRectChanged(capture_session_id_, region_capture_rect);
 }
 
@@ -573,14 +570,20 @@
 
 void TabSharingUIViews::UpdateTabCaptureData(WebContents* contents,
                                              TabCaptureUpdate update) {
-  if (!contents) {
+  // Only update tab capture data `contents` aren't being destroyed
+  // because the capture data should be automatically updated on
+  // destruction.
+  if (!contents || contents->IsBeingDestroyed()) {
     return;
   }
 
-  TabCaptureContentsBorderHelper::CreateForWebContents(contents);
-  auto* const helper =
-      TabCaptureContentsBorderHelper::FromWebContents(contents);
+  tabs::TabInterface* const tab_interface =
+      tabs::TabInterface::MaybeGetFromContents(contents);
+  if (!tab_interface || !tab_interface->GetTabFeatures()) {
+    return;
+  }
 
+  auto* const helper = TabCaptureContentsBorderHelper::From(tab_interface);
   switch (update) {
     case TabCaptureUpdate::kCaptureAdded:
       helper->OnCapturerAdded(capture_session_id_);
diff --git a/chrome/browser/ui/views/toolbar/BUILD.gn b/chrome/browser/ui/views/toolbar/BUILD.gn
index c6c9eed..1818896a 100644
--- a/chrome/browser/ui/views/toolbar/BUILD.gn
+++ b/chrome/browser/ui/views/toolbar/BUILD.gn
@@ -54,6 +54,8 @@
     "toolbar_actions_bar_bubble_views.h",
     "toolbar_button.cc",
     "toolbar_button.h",
+    "toolbar_button_menu_highlighter.cc",
+    "toolbar_button_menu_highlighter.h",
     "toolbar_chip_button.cc",
     "toolbar_chip_button.h",
     "toolbar_controller.cc",
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button_interactive_uitest.cc
index d6f1b49..09b524e9 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button_interactive_uitest.cc
@@ -27,6 +27,7 @@
 #include "chrome/test/interaction/webcontents_interaction_test_util.h"
 #include "chrome/test/user_education/interactive_feature_promo_test.h"
 #include "components/user_education/common/feature_promo/feature_promo_controller.h"
+#include "components/user_education/views/help_bubble_view.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -110,11 +111,21 @@
   RunTestSequence(
       InstrumentTab(kPrimaryTabPageElementId),
       MaybeShowPromo(kMenuPromoTestFeature),
+      // Open the menu with the IPH. This should close the bubble.
+      PressButton(kToolbarAppMenuButtonElementId),
+      WaitForHide(
+          user_education::HelpBubbleView::kHelpBubbleElementIdForTesting),
+      SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
+      // Verify that the promo is still active and the item is highlighted.
+      CheckPromoActive(kMenuPromoTestFeature, true),
+      CheckAlertStatus(BookmarkSubMenuModel::kShowBookmarkSidePanelItem, true),
+      CloseMenu(),
+      // Open the menu again, this time without the IPH.
       PressButton(kToolbarAppMenuButtonElementId),
       SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
-      CheckAlertStatus(BookmarkSubMenuModel::kShowBookmarkSidePanelItem, true),
-      CloseMenu(), PressButton(kToolbarAppMenuButtonElementId),
-      SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
+      // Verify that the promo is not still active and the item is not
+      // highlighted.
+      CheckPromoActive(kMenuPromoTestFeature, false),
       CheckAlertStatus(BookmarkSubMenuModel::kShowBookmarkSidePanelItem,
                        false));
 }
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index cc9bf0e..98b678c94 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -45,8 +45,7 @@
       reload_touch_icon_(kReloadTouchIcon),
       stop_icon_(kNavigateStopChromeRefreshIcon),
       stop_touch_icon_(kNavigateStopTouchIcon),
-      double_click_timer_delay_(
-          base::Milliseconds(views::GetDoubleClickInterval())),
+      double_click_timer_delay_(views::GetDoubleClickInterval()),
       mode_switch_timer_delay_(base::Milliseconds(1350)) {
   SetVisibleMode(Mode::kReload);
   SetTriggerableEventFlags(ui::EF_LEFT_MOUSE_BUTTON |
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.cc b/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.cc
new file mode 100644
index 0000000..6c726653
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.cc
@@ -0,0 +1,25 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.h"
+
+#include "base/types/pass_key.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/user_education/user_education_service.h"
+#include "chrome/browser/user_education/user_education_service_factory.h"
+#include "ui/views/view_class_properties.h"
+
+void ToolbarButtonMenuHighlighter::MaybeHighlight(
+    Browser* browser,
+    ToolbarButton* button,
+    user_education::HighlightingSimpleMenuModelDelegate* menu_model) {
+  if (auto* const service = UserEducationServiceFactory::GetForBrowserContext(
+          browser->GetProfile())) {
+    HighlightingMenuButtonHelper::MaybeHighlight(
+        service->GetFeaturePromoController(
+            base::PassKey<ToolbarButtonMenuHighlighter>()),
+        button->GetProperty(views::kElementIdentifierKey), menu_model);
+  }
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.h b/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.h
new file mode 100644
index 0000000..02905d2
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_menu_highlighter.h
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_BUTTON_MENU_HIGHLIGHTER_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_BUTTON_MENU_HIGHLIGHTER_H_
+
+#include "chrome/browser/lifetime/browser_close_manager.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
+#include "components/user_education/common/menu/highlighting_menu_button_helper.h"
+#include "components/user_education/common/menu/highlighting_simple_menu_model_delegate.h"
+
+// In order to have automatic toolbar button menu highlighting:
+//  - Derive your model from user_education::HighlightingSimpleMenuModelDelegate
+//    instead of ui::SimpleMenuModel::Delegate.
+//  - Have a ToolbarButtonMenuHighlighter member of your button object.
+//  - Call MaybeHighlight() when your menu is about to be shown.
+
+// Handles closing an attached IPH and possibly highlighting a menu item when a
+// toolbar button menu is about to be shown.
+class ToolbarButtonMenuHighlighter
+    : public user_education::HighlightingMenuButtonHelper {
+ public:
+  // This is the "nicer" version of `MaybeHighlight()` that should actually be
+  // used by toolbar buttons.
+  void MaybeHighlight(
+      Browser* browser,
+      ToolbarButton* button,
+      user_education::HighlightingSimpleMenuModelDelegate* menu_model);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_BUTTON_MENU_HIGHLIGHTER_H_
diff --git a/chrome/browser/ui/web_applications/BUILD.gn b/chrome/browser/ui/web_applications/BUILD.gn
index 61100aa8..ce618ac 100644
--- a/chrome/browser/ui/web_applications/BUILD.gn
+++ b/chrome/browser/ui/web_applications/BUILD.gn
@@ -119,6 +119,7 @@
     "//chrome/browser/themes",
     "//chrome/browser/ui:ui_features",
     "//chrome/browser/ui/page_info",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/window_sizer",
     "//chrome/browser/web_applications:prevent_close_test_support",
     "//chrome/browser/web_applications:web_applications_test_support",
diff --git a/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc b/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc
index 68e9659..e1b816a7 100644
--- a/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc
+++ b/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc
@@ -8,6 +8,7 @@
 
 #include "base/functional/bind.h"
 #include "base/logging.h"
+#include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chromeos/ash/components/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/ash/components/dbus/dbus_thread_manager.h"
@@ -85,8 +86,9 @@
       base::BindOnce(&CryptohomeWebUIHandler::OnPkcs11IsTpmTokenReady,
                      weak_ptr_factory_.GetWeakPtr()));
 
+  // Add 1 to compensate for the first recovery ID, which is not displayed.
   user_data_auth::GetAuthFactorExtendedInfoRequest req =
-      GenerateAuthFactorExtendedInfoRequest(kRecoveryIdHistoryDepth);
+      GenerateAuthFactorExtendedInfoRequest(kRecoveryIdHistoryDepth + 1);
   userdataauth_client->GetAuthFactorExtendedInfo(
       req, base::BindOnce(&CryptohomeWebUIHandler::OnGetAuthFactorExtendedInfo,
                           weak_ptr_factory_.GetWeakPtr()));
@@ -128,13 +130,12 @@
     std::optional<user_data_auth::GetAuthFactorExtendedInfoReply> reply) {
   std::string recovery_ids = "<empty>";
   if (reply.has_value() &&
-      !reply->recovery_info_reply().recovery_ids().empty()) {
-    recovery_ids =
-        std::accumulate(reply->recovery_info_reply().recovery_ids().begin(),
-                        reply->recovery_info_reply().recovery_ids().end(),
-                        std::string(), [](std::string ss, std::string s) {
-                          return ss.empty() ? s : ss + " " + s;
-                        });
+      reply->recovery_info_reply().recovery_ids().size() > 1) {
+    // The first recovery id is the most recent one and should not be
+    // displayed as it has not yet been used for a recovery attempt.
+    const auto& ids = reply->recovery_info_reply().recovery_ids();
+    recovery_ids = base::JoinString(
+        std::vector<std::string>(std::next(ids.begin()), ids.end()), " ");
   }
 
   std::string recovery_seed = "<empty>";
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 6b7bf380..76e5d77 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1446,8 +1446,7 @@
        IDS_SETTINGS_AUTOFILL_AI_ADD_OR_EDIT_DIALOG_VALIDATION_ERROR},
       {"autofillAiSubpageSublabelLoggingManagedDisabled",
        IDS_SETTINGS_AUTOFILL_AI_ENTERPRISE_LOGGING_MANAGED_DISABLED},
-      {"autofillPayOverTimeSettingsLabel",
-       IDS_AUTOFILL_BNPL_PAY_LATER_OPTIONS_TEXT},
+      {"autofillPayOverTimeSettingsLabel", IDS_AUTOFILL_BNPL_SETTINGS_LABEL},
       {"editAddressInAccount", IDS_SETTINGS_HOME_AND_WORK_ADDRESS_EDIT},
       {"removeFromChrome", IDS_SETTINGS_HOME_AND_WORK_ADDRESS_REMOVE},
       {"homeAddressIconA11yLabel", IDS_AUTOFILL_HOME_ADDRESS_ICON_A11Y_LABEL},
diff --git a/chrome/browser/user_education/user_education_service.h b/chrome/browser/user_education/user_education_service.h
index 2dbf8e1..a48d58cc 100644
--- a/chrome/browser/user_education/user_education_service.h
+++ b/chrome/browser/user_education/user_education_service.h
@@ -32,9 +32,9 @@
 // Kill switch for recent session tracking. Enabled by default.
 BASE_DECLARE_FEATURE(kAllowRecentSessionTracking);
 
-class AppMenuButton;
 class BrowserHelpBubble;
 class BrowserUserEducationInterfaceImpl;
+class ToolbarButtonMenuHighlighter;
 class UserEducationInternalsPageHandlerImpl;
 
 namespace web_app {
@@ -95,9 +95,9 @@
   // Only a limited number of non-test classes are allowed direct access to the
   // feature promo controller.
   template <typename T>
-    requires std::same_as<T, AppMenuButton> ||
-             std::same_as<T, BrowserHelpBubble> ||
+    requires std::same_as<T, BrowserHelpBubble> ||
              std::same_as<T, BrowserUserEducationInterfaceImpl> ||
+             std::same_as<T, ToolbarButtonMenuHighlighter> ||
              std::same_as<T, UserEducationInternalsPageHandlerImpl> ||
              std::same_as<T, web_app::WebAppUiManagerImpl>
   const user_education::FeaturePromoController* GetFeaturePromoController(
diff --git a/chrome/browser/wallet/android/javatests/src/org/chromium/chrome/browser/wallet/BoardingPassControllerTest.java b/chrome/browser/wallet/android/javatests/src/org/chromium/chrome/browser/wallet/BoardingPassControllerTest.java
index 0cd4483..bc0ff612 100644
--- a/chrome/browser/wallet/android/javatests/src/org/chromium/chrome/browser/wallet/BoardingPassControllerTest.java
+++ b/chrome/browser/wallet/android/javatests/src/org/chromium/chrome/browser/wallet/BoardingPassControllerTest.java
@@ -12,12 +12,14 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.Callback;
@@ -32,6 +34,7 @@
 @Config(manifest = Config.NONE)
 public class BoardingPassControllerTest {
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private ObservableSupplier<Tab> mMockTabProvider;
 
     @Mock private Tab mMockTab;
@@ -46,7 +49,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         BoardingPassBridgeJni.setInstanceForTesting(mMockBoardingPassBridgeJni);
         createControllerAndVerify();
     }
diff --git a/chrome/browser/webauthn/BUILD.gn b/chrome/browser/webauthn/BUILD.gn
index bc81676..d1c1579 100644
--- a/chrome/browser/webauthn/BUILD.gn
+++ b/chrome/browser/webauthn/BUILD.gn
@@ -4,6 +4,7 @@
 
 source_set("webauthn") {
   sources = [
+    "shared_types.h",
     "webauthn_metrics_util.h",
     "webauthn_switches.h",
   ]
diff --git a/chrome/browser/webauthn/android/chrome_webauthn_client_android.cc b/chrome/browser/webauthn/android/chrome_webauthn_client_android.cc
index a0919a0..4ccfb43 100644
--- a/chrome/browser/webauthn/android/chrome_webauthn_client_android.cc
+++ b/chrome/browser/webauthn/android/chrome_webauthn_client_android.cc
@@ -16,18 +16,23 @@
 
 void ChromeWebAuthnClientAndroid::OnWebAuthnRequestPending(
     content::RenderFrameHost* frame_host,
-    const std::vector<device::DiscoverableCredentialMetadata>& credentials,
-    bool is_conditional_request,
+    std::vector<device::DiscoverableCredentialMetadata> credentials,
+    webauthn::AssertionMediationType mediation_type,
     base::RepeatingCallback<void(const std::vector<uint8_t>& id)>
-        getAssertionCallback,
-    base::RepeatingCallback<void()> hybridCallback) {
+        passkey_callback,
+    base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+        password_callback,
+    base::RepeatingCallback<void()> hybrid_callback,
+    base::RepeatingCallback<void(webauthn::ImmediateRequestRejectionReason)>
+        reject_immediate_callback) {
   WebAuthnRequestDelegateAndroid* delegate =
       WebAuthnRequestDelegateAndroid::GetRequestDelegate(
           content::WebContents::FromRenderFrameHost(frame_host));
 
   delegate->OnWebAuthnRequestPending(
-      frame_host, credentials, is_conditional_request,
-      std::move(getAssertionCallback), std::move(hybridCallback));
+      frame_host, std::move(credentials), mediation_type,
+      std::move(passkey_callback), std::move(password_callback),
+      std::move(hybrid_callback), std::move(reject_immediate_callback));
 }
 
 void ChromeWebAuthnClientAndroid::CleanupWebAuthnRequest(
diff --git a/chrome/browser/webauthn/android/chrome_webauthn_client_android.h b/chrome/browser/webauthn/android/chrome_webauthn_client_android.h
index 3988bc25..40a9ad7e 100644
--- a/chrome/browser/webauthn/android/chrome_webauthn_client_android.h
+++ b/chrome/browser/webauthn/android/chrome_webauthn_client_android.h
@@ -7,6 +7,7 @@
 
 #include "base/functional/callback_forward.h"
 #include "components/webauthn/android/webauthn_client_android.h"
+#include "device/fido/discoverable_credential_metadata.h"
 
 // Chrome implementation of WebAuthnClientAndroid.
 class ChromeWebAuthnClientAndroid : public webauthn::WebAuthnClientAndroid {
@@ -21,11 +22,16 @@
   // webauthn::WebAuthnClientAndroid:
   void OnWebAuthnRequestPending(
       content::RenderFrameHost* frame_host,
-      const std::vector<device::DiscoverableCredentialMetadata>& credentials,
-      bool is_conditional_request,
+      std::vector<device::DiscoverableCredentialMetadata> credentials,
+      webauthn::AssertionMediationType mediation_type,
       base::RepeatingCallback<void(const std::vector<uint8_t>& id)>
-          getAssertionCallback,
-      base::RepeatingCallback<void()> hybridCallback) override;
+          passkey_callback,
+      base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+          password_callback,
+      base::RepeatingCallback<void()> hybrid_callback,
+      base::RepeatingCallback<void(webauthn::ImmediateRequestRejectionReason)>
+          reject_immediate_callback) override;
+
   void CleanupWebAuthnRequest(content::RenderFrameHost* frame_host) override;
 };
 
diff --git a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
index ff6496e7..0af4ba3 100644
--- a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
+++ b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h"
+#include "chrome/browser/webauthn/password_credential_controller.h"
 #include "chrome/browser/webauthn/webauthn_metrics_util.h"
 #include "components/password_manager/content/browser/content_password_manager_driver.h"
 #include "components/password_manager/content/browser/keyboard_replacing_surface_visibility_controller_impl.h"
@@ -24,6 +25,7 @@
 #include "components/password_manager/core/browser/passkey_credential.h"
 #include "components/webauthn/android/webauthn_cred_man_delegate.h"
 #include "components/webauthn/android/webauthn_cred_man_delegate_factory.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "device/fido/discoverable_credential_metadata.h"
 
@@ -57,19 +59,27 @@
 
 WebAuthnRequestDelegateAndroid::~WebAuthnRequestDelegateAndroid() = default;
 
+// TODO(https://crbug.com/434882145): The logic here has gotten pretty complex
+// and we should add unit tests to cover it.
 void WebAuthnRequestDelegateAndroid::OnWebAuthnRequestPending(
     content::RenderFrameHost* frame_host,
-    const std::vector<device::DiscoverableCredentialMetadata>& credentials,
-    bool is_conditional_request,
+    std::vector<device::DiscoverableCredentialMetadata> credentials,
+    webauthn::AssertionMediationType mediation_type,
     base::RepeatingCallback<void(const std::vector<uint8_t>& id)>
-        get_assertion_callback,
-    base::RepeatingClosure hybrid_callback) {
-  get_assertion_callback_ = std::move(get_assertion_callback);
+        passkey_or_dismiss_callback,
+    base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+        password_callback,
+    base::RepeatingCallback<void()> hybrid_callback,
+    base::RepeatingCallback<void(webauthn::ImmediateRequestRejectionReason)>
+        reject_immediate_callback) {
+  passkey_or_dismiss_callback_ = std::move(passkey_or_dismiss_callback);
+  password_callback_ = std::move(password_callback);
   hybrid_callback_ = std::move(hybrid_callback);
+  reject_immediate_callback_ = std::move(reject_immediate_callback);
 
-  std::vector<PasskeyCredential> display_credentials;
+  std::vector<PasskeyCredential> passkey_credentials;
   std::ranges::transform(
-      credentials, std::back_inserter(display_credentials),
+      credentials, std::back_inserter(passkey_credentials),
       [](const auto& credential) {
         return PasskeyCredential(
             PasskeyCredential::Source::kAndroidPhone,
@@ -81,23 +91,76 @@
                 credential.user.display_name.value_or("")));
       });
 
-  if (is_conditional_request) {
-    conditional_request_in_progress_ = true;
-    ReportConditionalUiPasskeyCount(credentials.size());
-    ChromeWebAuthnCredentialsDelegate* credentials_delegate =
-        ChromeWebAuthnCredentialsDelegateFactory::GetFactory(
-            content::WebContents::FromRenderFrameHost(frame_host))
-            ->GetDelegateForFrame(frame_host);
-    if (!credentials_delegate) {
+  bool is_immediate = false;
+  switch (mediation_type) {
+    case webauthn::AssertionMediationType::kConditional: {
+      conditional_request_in_progress_ = true;
+      ReportConditionalUiPasskeyCount(credentials.size());
+      ChromeWebAuthnCredentialsDelegate* credentials_delegate =
+          ChromeWebAuthnCredentialsDelegateFactory::GetFactory(
+              content::WebContents::FromRenderFrameHost(frame_host))
+              ->GetDelegateForFrame(frame_host);
+      if (!credentials_delegate) {
+        return;
+      }
+      credentials_delegate->OnCredentialsReceived(
+          std::move(passkey_credentials),
+          ChromeWebAuthnCredentialsDelegate::SecurityKeyOrHybridFlowAvailable(
+              !hybrid_callback_.is_null()));
       return;
     }
-    credentials_delegate->OnCredentialsReceived(
-        std::move(display_credentials),
-        ChromeWebAuthnCredentialsDelegate::SecurityKeyOrHybridFlowAvailable(
-            !hybrid_callback_.is_null()));
+    case webauthn::AssertionMediationType::kImmediateWithPasswords: {
+      // Only valid for the main frame.
+      if (!password_controller_ && frame_host->IsInPrimaryMainFrame()) {
+        password_controller_ = std::make_unique<PasswordCredentialController>(
+            frame_host->GetGlobalId());
+      }
+      password_controller_->FetchPasswords(
+          frame_host->GetLastCommittedURL(),
+          base::BindOnce(
+              &WebAuthnRequestDelegateAndroid::MaybeShowTouchToFillSheet,
+              weak_ptr_factory_.GetWeakPtr(), frame_host->GetGlobalId(),
+              /*is_immediate=*/true, std::move(passkey_credentials)));
+      return;
+    }
+    case webauthn::AssertionMediationType::kImmediatePasskeysOnly:
+      CHECK(!passkey_credentials.empty());
+      is_immediate = true;
+      break;
+    case webauthn::AssertionMediationType::kModal:
+      break;
+  }
+
+  MaybeShowTouchToFillSheet(frame_host->GetGlobalId(), is_immediate,
+                            std::move(passkey_credentials), {});
+}
+
+void WebAuthnRequestDelegateAndroid::MaybeShowTouchToFillSheet(
+    content::GlobalRenderFrameHostId render_frame_host_id,
+    bool is_immediate,
+    std::vector<PasskeyCredential> passkey_credentials,
+    std::vector<std::unique_ptr<password_manager::PasswordForm>>
+        password_credentials) {
+  auto* frame_host = content::RenderFrameHost::FromID(render_frame_host_id);
+  if (!frame_host) {
     return;
   }
 
+  if (is_immediate && passkey_credentials.empty() &&
+      password_credentials.empty()) {
+    reject_immediate_callback_.Run(
+        webauthn::ImmediateRequestRejectionReason::kNoCredentials);
+    return;
+  }
+
+  std::vector<password_manager::UiCredential> passwords;
+  std::ranges::transform(password_credentials, std::back_inserter(passwords),
+                         [=](const auto& password_form) {
+                           return password_manager::UiCredential(
+                               *password_form,
+                               frame_host->GetLastCommittedOrigin());
+                         });
+
   if (!visibility_controller_) {
     visibility_controller_ = std::make_unique<
         password_manager::KeyboardReplacingSurfaceVisibilityControllerImpl>();
@@ -109,12 +172,13 @@
         /*grouped_credential_sheet_controller=*/nullptr);
   }
   touch_to_fill_controller_->InitData(
-      std::vector<password_manager::UiCredential>(), display_credentials,
+      passwords, std::move(passkey_credentials),
       ContentPasswordManagerDriver::GetForRenderFrameHost(frame_host)
           ->AsWeakPtrImpl());
+  bool should_show_hybrid_option = !hybrid_callback_.is_null() && !is_immediate;
   touch_to_fill_controller_->Show(
       std::make_unique<TouchToFillControllerWebAuthnDelegate>(
-          this, !hybrid_callback_.is_null()),
+          this, should_show_hybrid_option, is_immediate),
       WebAuthnCredManDelegateFactory::GetFactory(web_contents())
           ->GetRequestDelegate(frame_host));
 }
@@ -136,13 +200,31 @@
   }
 
   conditional_request_in_progress_ = false;
-  get_assertion_callback_.Reset();
+  passkey_or_dismiss_callback_.Reset();
+  password_callback_.Reset();
+  hybrid_callback_.Reset();
+  reject_immediate_callback_.Reset();
 }
 
 void WebAuthnRequestDelegateAndroid::OnWebAuthnAccountSelected(
     const std::vector<uint8_t>& user_id) {
-  if (get_assertion_callback_) {
-    get_assertion_callback_.Run(user_id);
+  if (passkey_or_dismiss_callback_) {
+    passkey_or_dismiss_callback_.Run(user_id);
+  }
+}
+
+void WebAuthnRequestDelegateAndroid::OnPasswordCredentialSelected(
+    const PasswordCredentialPair& password_credential) {
+  if (password_callback_) {
+    password_callback_.Run(password_credential.first,
+                           password_credential.second);
+  }
+}
+
+void WebAuthnRequestDelegateAndroid::OnCredentialSelectionDeclined() {
+  if (reject_immediate_callback_) {
+    reject_immediate_callback_.Run(
+        webauthn::ImmediateRequestRejectionReason::kUserDismissed);
   }
 }
 
diff --git a/chrome/browser/webauthn/android/webauthn_request_delegate_android.h b/chrome/browser/webauthn/android/webauthn_request_delegate_android.h
index fb7d1a8..d954226 100644
--- a/chrome/browser/webauthn/android/webauthn_request_delegate_android.h
+++ b/chrome/browser/webauthn/android/webauthn_request_delegate_android.h
@@ -10,8 +10,14 @@
 
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/supports_user_data.h"
 #include "chrome/browser/touch_to_fill/password_manager/touch_to_fill_controller_webauthn_delegate.h"
+#include "chrome/browser/webauthn/shared_types.h"
+#include "components/password_manager/core/browser/passkey_credential.h"
+#include "components/password_manager/core/browser/password_form.h"
+#include "components/webauthn/android/webauthn_client_android.h"
+#include "content/public/browser/global_routing_id.h"
 
 namespace content {
 class RenderFrameHost;
@@ -26,6 +32,7 @@
 class KeyboardReplacingSurfaceVisibilityController;
 }
 
+class PasswordCredentialController;
 class TouchToFillController;
 
 // Helper class for connecting the autofill implementation to the WebAuthn
@@ -45,17 +52,21 @@
 
   ~WebAuthnRequestDelegateAndroid() override;
 
-  // Called when a Web Authentication Conditional UI request is received. This
+  // Called when a Web Authentication GetAssertion request is received. This
   // provides a callback that will complete the request if and when a user
-  // selects a credential from a form autofill dialog, and also a closure that
+  // selects a credential from a touch to fill sheet, and also a closure that
   // is invoked if the user starts a hybrid authentication.
   void OnWebAuthnRequestPending(
       content::RenderFrameHost* frame_host,
-      const std::vector<device::DiscoverableCredentialMetadata>& credentials,
-      bool is_conditional_request,
+      std::vector<device::DiscoverableCredentialMetadata> credentials,
+      webauthn::AssertionMediationType mediation_type,
       base::RepeatingCallback<void(const std::vector<uint8_t>& id)>
-          get_assertion_callback,
-      base::RepeatingClosure hybrid_callback);
+          passkey_or_dismiss_callback,
+      base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+          password_callback,
+      base::RepeatingCallback<void()> hybrid_callback,
+      base::RepeatingCallback<void(webauthn::ImmediateRequestRejectionReason)>
+          reject_immediate_callback);
 
   // Called when an outstanding request is ended, either because it was aborted
   // by the RP, or because it completed successfully. Its main purpose is to
@@ -64,6 +75,9 @@
 
   // TouchToFillControllerWebAuthnDelegate::CredentialReceiver:
   void OnWebAuthnAccountSelected(const std::vector<uint8_t>& id) override;
+  void OnPasswordCredentialSelected(
+      const PasswordCredentialPair& password_credential) override;
+  void OnCredentialSelectionDeclined() override;
   void OnHybridSignInSelected() override;
   content::WebContents* web_contents() override;
 
@@ -75,9 +89,22 @@
       content::WebContents* web_contents);
 
  private:
+  // This takes the RenderFrameHost's GlobalID rather than a pointer, so that
+  // it can be called asynchronously without having to worry about lifetimes.
+  void MaybeShowTouchToFillSheet(
+      content::GlobalRenderFrameHostId render_frame_host_id,
+      bool isImmediate,
+      std::vector<password_manager::PasskeyCredential> passkey_credentials,
+      std::vector<std::unique_ptr<password_manager::PasswordForm>>
+          password_credentials);
+
   base::RepeatingCallback<void(const std::vector<uint8_t>& user_id)>
-      get_assertion_callback_;
+      passkey_or_dismiss_callback_;
+  base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+      password_callback_;
   base::RepeatingClosure hybrid_callback_;
+  base::RepeatingCallback<void(webauthn::ImmediateRequestRejectionReason)>
+      reject_immediate_callback_;
 
   // Controller for using the Touch To Fill bottom sheet for non-conditional
   // requests.
@@ -91,6 +118,10 @@
   raw_ptr<content::WebContents> web_contents_;
 
   bool conditional_request_in_progress_ = false;
+
+  std::unique_ptr<PasswordCredentialController> password_controller_;
+
+  base::WeakPtrFactory<WebAuthnRequestDelegateAndroid> weak_ptr_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_WEBAUTHN_ANDROID_WEBAUTHN_REQUEST_DELEGATE_ANDROID_H_
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index 3a194803..175e0fbe 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -22,6 +22,7 @@
 #include "chrome/browser/webauthn/authenticator_transport.h"
 #include "chrome/browser/webauthn/gpm_enclave_transaction.h"
 #include "chrome/browser/webauthn/local_authentication_token.h"
+#include "chrome/browser/webauthn/shared_types.h"
 #include "content/public/browser/authenticator_request_client_delegate.h"
 #include "content/public/browser/global_routing_id.h"
 #include "device/fido/discoverable_credential_metadata.h"
@@ -43,8 +44,6 @@
 class AuthenticatorRequestDialogViewController;
 class Profile;
 
-using PasswordCredentialPair = std::pair<std::u16string, std::u16string>;
-
 enum class EnclaveEnabledStatus {
   kDisabled,
   kEnabled,
diff --git a/chrome/browser/webauthn/password_credential_controller.cc b/chrome/browser/webauthn/password_credential_controller.cc
index c2277dec..a781fc92 100644
--- a/chrome/browser/webauthn/password_credential_controller.cc
+++ b/chrome/browser/webauthn/password_credential_controller.cc
@@ -13,7 +13,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
-#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
 #include "components/password_manager/core/browser/form_fetcher_impl.h"
 #include "content/public/browser/render_frame_host.h"
@@ -45,6 +44,7 @@
   return ChromePasswordManagerClient::FromWebContents(web_contents);
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 std::u16string GetAuthenticationMessage(std::string_view rp_id) {
 #if BUILDFLAG(IS_LINUX)
   return u"";
@@ -53,15 +53,22 @@
                                     base::UTF8ToUTF16(rp_id));
 #endif  // BUILDFLAG(IS_LINUX)
 }
+#endif  // !BUILDFLAG(IS_ANDROID)
 
 }  // namespace
 
+#if BUILDFLAG(IS_ANDROID)
+PasswordCredentialController::PasswordCredentialController(
+    GlobalRenderFrameHostId render_frame_host_id)
+    : render_frame_host_id_(render_frame_host_id) {}
+#else
 PasswordCredentialController::PasswordCredentialController(
     GlobalRenderFrameHostId render_frame_host_id,
     AuthenticatorRequestDialogModel* model)
     : render_frame_host_id_(render_frame_host_id), model_(model) {
   model_observer_.Observe(model_);
 }
+#endif  // BUILDFLAG(IS_ANDROID)
 
 PasswordCredentialController::~PasswordCredentialController() = default;
 
@@ -74,51 +81,6 @@
   form_fetcher_->AddConsumer(this);
 }
 
-bool PasswordCredentialController::IsAuthRequired() {
-  // TODO(crbug.com/392549444): For the prototype, require screen lock only if
-  // it's enabled (e.g. via PWM settings). This may change.
-  auto* pwm_client = GetPasswordManagerClient(*GetRenderFrameHost());
-  return pwm_client && pwm_client->GetPasswordFeatureManager()
-                           ->IsBiometricAuthenticationBeforeFillingEnabled();
-}
-
-void PasswordCredentialController::SetPasswordSelectedCallback(
-    content::AuthenticatorRequestClientDelegate::PasswordSelectedCallback
-        callback) {
-  password_selected_callback_ = callback;
-}
-
-void PasswordCredentialController::OnPasswordCredentialSelected(
-    PasswordCredentialPair password) {
-  if (!IsAuthRequired() || model_->local_auth_token.has_value()) {
-    password_selected_callback_.Run(password_manager::CredentialInfo(
-        password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD,
-        password.first, password.first, GURL(), password.second,
-        url::SchemeHostPort()));
-    return;
-  }
-  filling_password_ = std::move(password);
-  model_->SetStep(AuthenticatorRequestDialogModel::Step::kPasswordOsAuth);
-}
-
-void PasswordCredentialController::OnStepTransition() {
-  if (model_->step() ==
-      AuthenticatorRequestDialogModel::Step::kPasswordOsAuth) {
-    CHECK(filling_password_.has_value());
-    auto manage_passwords_ui_controller = PasswordsModelDelegateFromWebContents(
-        WebContents::FromRenderFrameHost(GetRenderFrameHost()));
-    if (!manage_passwords_ui_controller) {
-      return;
-    }
-    manage_passwords_ui_controller->AuthenticateUserWithMessage(
-        GetAuthenticationMessage(model_->relying_party_id),
-        base::BindOnce(&PasswordCredentialController::OnAuthenticationCompleted,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       std::move(filling_password_.value())));
-    return;
-  }
-}
-
 void PasswordCredentialController::OnFetchCompleted() {
   CHECK(!callback_.is_null());
   PasswordCredentials credentials;
@@ -147,6 +109,57 @@
   return ret;
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+
+bool PasswordCredentialController::IsAuthRequired() {
+  // TODO(crbug.com/392549444): For the prototype, require screen lock only if
+  // it's enabled (e.g. via PWM settings). This may change.
+  auto* pwm_client = GetPasswordManagerClient(*GetRenderFrameHost());
+  return pwm_client && pwm_client->GetPasswordFeatureManager()
+                           ->IsBiometricAuthenticationBeforeFillingEnabled();
+}
+
+void PasswordCredentialController::SetPasswordSelectedCallback(
+    content::AuthenticatorRequestClientDelegate::PasswordSelectedCallback
+        callback) {
+  password_selected_callback_ = callback;
+}
+
+void PasswordCredentialController::OnPasswordCredentialSelected(
+    PasswordCredentialPair password) {
+  if (!IsAuthRequired() || model_->local_auth_token.has_value()) {
+    password_selected_callback_.Run(password_manager::CredentialInfo(
+        password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD,
+        password.first, password.first, GURL(), password.second,
+        url::SchemeHostPort()));
+    return;
+  }
+  filling_password_ = std::move(password);
+  model_->SetStep(AuthenticatorRequestDialogModel::Step::kPasswordOsAuth);
+}
+
+void PasswordCredentialController::OnStepTransition() {
+  if (!model_) {
+    return;
+  }
+
+  if (model_->step() ==
+      AuthenticatorRequestDialogModel::Step::kPasswordOsAuth) {
+    CHECK(filling_password_.has_value());
+    auto manage_passwords_ui_controller = PasswordsModelDelegateFromWebContents(
+        WebContents::FromRenderFrameHost(GetRenderFrameHost()));
+    if (!manage_passwords_ui_controller) {
+      return;
+    }
+    manage_passwords_ui_controller->AuthenticateUserWithMessage(
+        GetAuthenticationMessage(model_->relying_party_id),
+        base::BindOnce(&PasswordCredentialController::OnAuthenticationCompleted,
+                       weak_ptr_factory_.GetWeakPtr(),
+                       std::move(filling_password_.value())));
+    return;
+  }
+}
+
 void PasswordCredentialController::OnAuthenticationCompleted(
     PasswordCredentialPair password,
     bool success) {
@@ -159,3 +172,5 @@
       password.first, password.first, GURL(), password.second,
       url::SchemeHostPort()));
 }
+
+#endif  // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/webauthn/password_credential_controller.h b/chrome/browser/webauthn/password_credential_controller.h
index 7548fb7..c05647d 100644
--- a/chrome/browser/webauthn/password_credential_controller.h
+++ b/chrome/browser/webauthn/password_credential_controller.h
@@ -13,36 +13,54 @@
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/scoped_observation.h"
-#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
+#include "build/buildflag.h"
+#include "chrome/browser/webauthn/shared_types.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
 #include "components/password_manager/core/browser/form_fetcher_impl.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_digest.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
-#include "content/public/browser/authenticator_request_client_delegate.h"
-#include "content/public/browser/document_user_data.h"
 #include "content/public/browser/global_routing_id.h"
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "base/scoped_observation.h"
+#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
+#endif
+
+namespace content {
+class RenderFrameHost;
+}
+
 // This class is responsible for fetching `PasswordCredentials` for the given
 // `render_frame_host` and responding with the found credentials for a `url`.
 class PasswordCredentialController
+#if BUILDFLAG(IS_ANDROID)
+    : public password_manager::FormFetcher::Consumer {
+#else
     : public password_manager::FormFetcher::Consumer,
       public AuthenticatorRequestDialogModel::Observer {
+#endif
  public:
   using PasswordCredentials =
       std::vector<std::unique_ptr<password_manager::PasswordForm>>;
   using PasswordCredentialsReceivedCallback =
       base::OnceCallback<void(PasswordCredentials)>;
 
+#if BUILDFLAG(IS_ANDROID)
+  explicit PasswordCredentialController(
+      content::GlobalRenderFrameHostId render_frame_host_id);
+#else
   PasswordCredentialController(
       content::GlobalRenderFrameHostId render_frame_host_id,
       AuthenticatorRequestDialogModel* model);
+#endif
   ~PasswordCredentialController() override;
 
   virtual void FetchPasswords(const GURL& url,
                               PasswordCredentialsReceivedCallback callback);
 
+#if !BUILDFLAG(IS_ANDROID)
   // Returns `true` if the user is required to pass screen lock before using a
   // credential.
   virtual bool IsAuthRequired();
@@ -54,6 +72,7 @@
   // AuthenticatorRequestDialogModel::Observer
   void OnPasswordCredentialSelected(PasswordCredentialPair password) override;
   void OnStepTransition() override;
+#endif
 
  private:
   // FormFetcher::Consumer:
@@ -64,18 +83,23 @@
 
   content::RenderFrameHost* GetRenderFrameHost() const;
 
+#if !BUILDFLAG(IS_ANDROID)
   void OnAuthenticationCompleted(PasswordCredentialPair password, bool success);
+#endif
 
   const content::GlobalRenderFrameHostId render_frame_host_id_;
-  raw_ptr<AuthenticatorRequestDialogModel> model_;
 
-  std::unique_ptr<password_manager::FormFetcher> form_fetcher_;
-  PasswordCredentialsReceivedCallback callback_;
-  content::AuthenticatorRequestClientDelegate::PasswordSelectedCallback
-      password_selected_callback_;
+#if !BUILDFLAG(IS_ANDROID)
+  raw_ptr<AuthenticatorRequestDialogModel> model_;
   base::ScopedObservation<AuthenticatorRequestDialogModel,
                           AuthenticatorRequestDialogModel::Observer>
       model_observer_{this};
+  content::AuthenticatorRequestClientDelegate::PasswordSelectedCallback
+      password_selected_callback_;
+#endif
+
+  std::unique_ptr<password_manager::FormFetcher> form_fetcher_;
+  PasswordCredentialsReceivedCallback callback_;
 
   std::optional<PasswordCredentialPair> filling_password_;
 
diff --git a/chrome/browser/webauthn/shared_types.h b/chrome/browser/webauthn/shared_types.h
new file mode 100644
index 0000000..5921dfc
--- /dev/null
+++ b/chrome/browser/webauthn/shared_types.h
@@ -0,0 +1,12 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEBAUTHN_SHARED_TYPES_H_
+#define CHROME_BROWSER_WEBAUTHN_SHARED_TYPES_H_
+
+#include <string>
+
+using PasswordCredentialPair = std::pair<std::u16string, std::u16string>;
+
+#endif  // CHROME_BROWSER_WEBAUTHN_SHARED_TYPES_H_
diff --git a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProviderTest.java b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProviderTest.java
index 588646e..228c7f8 100644
--- a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProviderTest.java
+++ b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProviderTest.java
@@ -10,10 +10,12 @@
 import static org.mockito.Mockito.when;
 
 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.chromium.base.ServiceLoaderUtil;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -23,12 +25,12 @@
 /** Tests for {@link XSurfaceProcessScopeProvider}. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class XSurfaceProcessScopeProviderTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private XSurfaceHooks mXSurfaceHooks;
     @Mock private ProcessScope mProcessScope;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         ServiceLoaderUtil.setInstanceForTesting(XSurfaceHooks.class, mXSurfaceHooks);
     }
 
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index a8edfcbd..d88bd844 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1754051353-42ff3405c36a51eb63cd6032c87d20b153e60f31-153ce578b4abc60f575d38917e47f7fc3cba7638.profdata
+chrome-android64-main-1754063676-23f3118fc63cc39f5ea48a4e552f38425ec51c77-16c2cccb581a821b8b617c1f67f74eb5c3d794ef.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 68c26ae..4c5c0aa 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1754049475-785253290588cacd56c9b10b4a133179e57102d5-d12ec3e84f1c806a891ff657c4c7f3abb126f533.profdata
+chrome-mac-arm-main-1754063976-b1ac521f5590e9ad6f7ec58cf1f02c9a92852576-e3ed81b4aeea523d041f3d62d4ae5779ca1c9fd2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 22152e22..9fecd13 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1754038735-8f85b853caac30df5ffa7c34052bd8677a61f765-23426a5dbe914450e6657ca6ec8e4e602edfadf0.profdata
+chrome-win32-main-1754049475-8902e5ed61d545ff04c327f3c0b9dfc3709cd3e0-d12ec3e84f1c806a891ff657c4c7f3abb126f533.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 3d636c3..5af867b 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1754038735-6eb02260d4d282b315f4434d6913850518d974e0-23426a5dbe914450e6657ca6ec8e4e602edfadf0.profdata
+chrome-win64-main-1754049475-40c492ccea415348c29a3f766718e1b31b587423-d12ec3e84f1c806a891ff657c4c7f3abb126f533.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index b92c473..17dbead 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -638,7 +638,7 @@
 // when trying to scroll all documents except PDFs (and fail the request if
 // it's not set).
 const base::FeatureParam<bool> kGlicScrollToEnforceDocumentId{
-    &kGlicScrollTo, "glic-scroll-to-enforce-document-id", false};
+    &kGlicScrollTo, "glic-scroll-to-enforce-document-id", true};
 // Expand the scrollTo capability to PDF documents.
 const base::FeatureParam<bool> kGlicScrollToPDF{&kGlicScrollTo,
                                                 "glic-scroll-to-pdf", false};
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
index 514f78f..cd456e6 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
@@ -538,6 +538,26 @@
   }
 }
 
+void ReadAnythingAppController::OnStringAttributeChanged(
+    ui::AXTree* tree,
+    ui::AXNode* node,
+    ax::mojom::StringAttribute attr,
+    const std::string& old_value,
+    const std::string& new_value) {
+  ui::AXNode* rm_node = model_.GetAXNode(node->id());
+  if (!rm_node) {
+    return;
+  }
+  // When the src for an image changes (e.g if an image was lazy loaded and
+  // previously had a placeholder image), request the updated image. The info
+  // will be returned via OnImageDataDownloaded.
+  if (features::IsReadAnythingImagesViaAlgorithmEnabled() &&
+      attr == ax::mojom::StringAttribute::kUrl &&
+      rm_node->GetRole() == ax::mojom::Role::kImage) {
+    RequestImageDataUrl(node->id());
+  }
+}
+
 void ReadAnythingAppController::AccessibilityEventReceived(
     const ui::AXTreeID& tree_id,
     const std::vector<ui::AXTreeUpdate>& updates,
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.h
index cdf8f0c5..d30f3307 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.h
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.h
@@ -161,6 +161,12 @@
                          const ui::AXTreeData& old_data,
                          const ui::AXTreeData& new_data) override;
 
+  void OnStringAttributeChanged(ui::AXTree* tree,
+                                ui::AXNode* node,
+                                ax::mojom::StringAttribute attr,
+                                const std::string& old_value,
+                                const std::string& new_value) override;
+
   // gin templates:
   ui::AXNodeID RootId() const;
   ui::AXNodeID StartNodeId() const;
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
index 19304bf0..abd7d1c 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
@@ -3827,6 +3827,57 @@
   EXPECT_FALSE(model.IsAvailable());
 }
 
+TEST_F(ReadAnythingAppControllerTest,
+       OnStringAttributeChanged_ImageSrcChange_RequestsImageData) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kReadAnythingImagesViaAlgorithm);
+
+  // Create an image node with a placeholder "data:" URL, mimicking a
+  // lazy-loaded image.
+  static constexpr ui::AXNodeID kImageNodeId = 2;
+  std::string placeholder_src = "data:image/svg+xml,...";
+  ui::AXNodeData image_node = test::ImageNode(kImageNodeId, placeholder_src);
+  SendUpdateAndDistillNodes({std::move(image_node)});
+
+  // Now update with the actual image url.
+  std::string final_src = "https://example.com/real_image.png";
+  ui::AXNodeData updated_image_node = test::ImageNode(kImageNodeId, final_src);
+  SendUpdateAndDistillNodes({std::move(updated_image_node)});
+
+  EXPECT_CALL(page_handler_, OnImageDataRequested(tree_id_, kImageNodeId))
+      .Times(2);
+}
+
+TEST_F(ReadAnythingAppControllerTest,
+       OnStringAttributeChanged_NonImageNode_DoesNothing) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kReadAnythingImagesViaAlgorithm);
+
+  static constexpr ui::AXNodeID kLinkNodeId = 2;
+  std::string placeholder_url = "data:image/svg+xml,...";
+  ui::AXNodeData link_node = test::LinkNode(kLinkNodeId, placeholder_url);
+  SendUpdateAndDistillNodes({std::move(link_node)});
+
+  std::string final_url = "https://example.com/real_image.png";
+  ui::AXNodeData updated_link_node = test::LinkNode(kLinkNodeId, final_url);
+  SendUpdateAndDistillNodes({std::move(updated_link_node)});
+
+  EXPECT_CALL(page_handler_, OnImageDataRequested).Times(0);
+}
+
+TEST_F(ReadAnythingAppControllerTest,
+       OnStringAttributeChanged_ImageFlagDisabled_DoesNothing) {
+  static constexpr ui::AXNodeID kImageNodeId = 2;
+  std::string placeholder_src = "data:image/svg+xml,...";
+  ui::AXNodeData image_node = test::ImageNode(kImageNodeId, placeholder_src);
+  SendUpdateAndDistillNodes({std::move(image_node)});
+  std::string final_src = "https://example.com/real_image.png";
+  ui::AXNodeData updated_image_node = test::ImageNode(kImageNodeId, final_src);
+  SendUpdateAndDistillNodes({std::move(updated_image_node)});
+
+  EXPECT_CALL(page_handler_, OnImageDataRequested).Times(0);
+}
+
 class ReadAnythingAppControllerScreen2xDataCollectionModeTest
     : public ReadAnythingAppControllerTest {
  public:
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_test_utils.cc b/chrome/renderer/accessibility/read_anything/read_anything_test_utils.cc
index 68fc49d..7a7dc045 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_test_utils.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_test_utils.cc
@@ -59,6 +59,14 @@
   return node;
 }
 
+ui::AXNodeData ImageNode(ui::AXNodeID id, const std::string& src) {
+  ui::AXNodeData node;
+  node.id = id;
+  node.role = ax::mojom::Role::kImage;
+  node.AddStringAttribute(ax::mojom::StringAttribute::kUrl, src);
+  return node;
+}
+
 ui::AXNodeData LinkNode(ui::AXNodeID id, const std::string& url) {
   ui::AXNodeData node;
   node.id = id;
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_test_utils.h b/chrome/renderer/accessibility/read_anything/read_anything_test_utils.h
index 82cb4da..59f1153f 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_test_utils.h
+++ b/chrome/renderer/accessibility/read_anything/read_anything_test_utils.h
@@ -39,6 +39,7 @@
 ui::AXNodeData TextNode(ui::AXNodeID id);
 ui::AXNodeData TextNodeWithTextFromId(ui::AXNodeID id);
 ui::AXNodeData ExplicitlyEmptyTextNode(ui::AXNodeID id);
+ui::AXNodeData ImageNode(ui::AXNodeID id, const std::string& src);
 ui::AXNodeData LinkNode(ui::AXNodeID id, const std::string& url);
 ui::AXNodeData GenericContainerNode(ui::AXNodeID id);
 ui::AXNodeData SuperscriptNode(ui::AXNodeID id,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c9547d9..34f9edf1 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2755,7 +2755,6 @@
       "//components/supervised_user/core/browser:mocked",
       "//components/supervised_user/core/browser/proto",
       "//components/supervised_user/core/common",
-      "//components/supervised_user/core/common:test_utils",
       "//components/supervised_user/test_support",
       "//components/supervised_user/test_support",
       "//components/sync",
@@ -3956,6 +3955,7 @@
       "//chrome/browser/ui/passwords/bubble_controllers",
       "//chrome/browser/ui/profiles",
       "//chrome/browser/ui/search",
+      "//chrome/browser/ui/startup",
       "//chrome/browser/ui/startup/default_browser_prompt",
       "//chrome/browser/ui/sync",
       "//chrome/browser/ui/toolbar",
@@ -6939,6 +6939,7 @@
     "//chrome/browser/ui/safety_hub:test_support",
     "//chrome/browser/ui/search_engines:unit_tests",
     "//chrome/browser/ui/serial:unit_tests",
+    "//chrome/browser/ui/startup",
     "//chrome/browser/ui/sync:unit_tests",
     "//chrome/browser/ui/toolbar/chrome_labs",
     "//chrome/browser/ui/toolbar/pinned_toolbar",
@@ -10857,6 +10858,7 @@
       "//chrome/browser/ui/browser_window",
       "//chrome/browser/ui/location_bar",
       "//chrome/browser/ui/signin",
+      "//chrome/browser/ui/startup",
       "//chrome/browser/ui/user_education",
       "//chrome/browser/ui/views/page_action",
       "//chrome/browser/ui/views/page_info",
@@ -11463,6 +11465,7 @@
       "//chrome/browser:flags",
       "//chrome/browser/privacy_sandbox:test_support",
       "//chrome/browser/ui/location_bar",
+      "//chrome/browser/ui/startup",
     ]
 
     if (!is_chrome_for_testing) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
index 6b01eed..1bca8d45 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -287,7 +287,7 @@
      * @return {@link LoadUrlResult} from Tab#loadUrl.
      */
     public LoadUrlResult loadUrl(String url, long secondsToWait) throws IllegalArgumentException {
-        Tab tab = ThreadUtils.runOnUiThreadBlocking(() -> getActivity().getActivityTab());
+        Tab tab = getActivityTab();
         return loadUrlInTab(
                 url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, tab, secondsToWait);
     }
@@ -300,7 +300,7 @@
      * @return {@link LoadUrlResult} from Tab#loadUrl.
      */
     public LoadUrlResult loadUrl(String url) throws IllegalArgumentException {
-        Tab tab = ThreadUtils.runOnUiThreadBlocking(() -> getActivity().getActivityTab());
+        Tab tab = getActivityTab();
         return loadUrlInTab(url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, tab);
     }
 
@@ -431,7 +431,7 @@
                 new Callable<>() {
                     @Override
                     public List<InfoBar> call() {
-                        Tab currentTab = getActivity().getActivityTab();
+                        Tab currentTab = getActivityTab();
                         assertNotNull(currentTab);
                         assertNotNull(InfoBarContainer.get(currentTab));
                         return InfoBarContainer.get(currentTab).getInfoBarsForTesting();
@@ -444,8 +444,8 @@
      * its execution in JSON format.
      */
     public String runJavaScriptCodeInCurrentTab(String code) throws TimeoutException {
-        return JavaScriptUtils.executeJavaScriptAndWaitForResult(
-                getActivity().getCurrentWebContents(), code);
+        WebContents webContents = getWebContents();
+        return JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, code);
     }
 
     /**
@@ -454,8 +454,8 @@
      */
     public String runJavaScriptCodeWithUserGestureInCurrentTab(String code)
             throws TimeoutException {
-        return JavaScriptUtils.executeJavaScriptWithUserGestureAndWaitForResult(
-                getActivity().getCurrentWebContents(), code);
+        WebContents webContents = getWebContents();
+        return JavaScriptUtils.executeJavaScriptWithUserGestureAndWaitForResult(webContents, code);
     }
 
     /**
@@ -472,10 +472,7 @@
      */
     public InfoBarContainer getInfoBarContainer() {
         return ThreadUtils.runOnUiThreadBlocking(
-                () ->
-                        getActivity().getActivityTab() != null
-                                ? InfoBarContainer.get(getActivity().getActivityTab())
-                                : null);
+                () -> getActivityTab() != null ? InfoBarContainer.get(getActivityTab()) : null);
     }
 
     /** Gets the ChromeActivityTestRule's EmbeddedTestServer instance if it has one. */
@@ -488,6 +485,11 @@
         return mTestServerRule;
     }
 
+    /** Returns the active {@link Tab} of the activity. */
+    public Tab getActivityTab() {
+        return ThreadUtils.runOnUiThreadBlocking(() -> getActivity().getActivityTab());
+    }
+
     /** Returns the {@link WebContents} of the active tab of the activity. */
     public WebContents getWebContents() {
         return ThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
index 72701f75e..9efc46b8 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
@@ -171,7 +171,7 @@
         }
         ThreadUtils.runOnUiThreadBlocking(() -> incognitoTabModel.removeObserver(observer));
 
-        Tab tab = getActivity().getActivityTab();
+        Tab tab = getActivityTab();
 
         ChromeTabUtils.waitForTabPageLoaded(tab, (String) null);
         NewTabPageTestUtils.waitForNtpLoaded(tab);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
index bb84759..ea29982 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
@@ -11,11 +11,13 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -24,11 +26,12 @@
 import java.util.Collections;
 import java.util.List;
 
-/** Tests for BySelectorIndexUi2Locator. */
+/** Tests for {@link BySelectorIndexUi2Locator}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public final class BySelectorIndexUi2LocatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private BySelector mSelector;
 
     @Mock private UiDevice mDevice;
@@ -39,24 +42,20 @@
 
     @Mock private UiObject2 mResult1;
 
-    private List<UiObject2> mResults;
-
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         // Create a BySelectorLocator so tests can create BySelectorIndexUi2Locator off of it.
         mSelector = By.res("resource");
-        mResults = new ArrayList<>();
-        mResults.add(mResult0);
-        mResults.add(mResult1);
+        List<UiObject2> results = new ArrayList<>();
+        results.add(mResult0);
+        results.add(mResult1);
 
         // Only mResult0 is used here since mSelector should return it when locateOne
-        // is called.  This works because we've also correctly speicifed that it should
+        // is called.  This works because we've also correctly specified that it should
         // return mResults in response to locateAll, which will contain a list of mResult0
         // and mResult1.  BySelectorIndexUi2Locator uses locateAll to be able to locate
         // any child by it's position in the children list.
-        TestUtils.stubMocks(mDevice, mRoot, mSelector, mResult0, mResults);
+        TestUtils.stubMocks(mDevice, mRoot, mSelector, mResult0, results);
     }
 
     @Test
@@ -81,6 +80,6 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void locateNegativeIndex() {
-        BySelectorIndexUi2Locator locator = new BySelectorIndexUi2Locator(mSelector, -1);
+        new BySelectorIndexUi2Locator(mSelector, -1);
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
index a40cbae8..d710293 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
@@ -11,11 +11,13 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -28,6 +30,7 @@
 @Config(manifest = Config.NONE)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class BySelectorUi2LocatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     private BySelector mSelector;
 
     @Mock private UiDevice mDevice;
@@ -42,8 +45,6 @@
 
     @Before
     public void setup() {
-        MockitoAnnotations.initMocks(this);
-
         mSelector = By.res("resource");
 
         mResults = new ArrayList<>();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
index 777d73e..fefe6802 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
@@ -15,11 +15,13 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -33,6 +35,7 @@
 @Config(manifest = Config.NONE)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class ChildIndexUi2LocatorTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private UiDevice mDevice;
 
     @Mock private UiObject2 mNode0;
@@ -62,8 +65,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mNodeList = new ArrayList<>();
         mNodeList.add(mNode0);
         mNodeList.add(mNode1);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
index 748742c..c899c2fdb 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
@@ -13,11 +13,13 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -43,14 +45,13 @@
 
     @Mock private UiObject2 mRoot;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private UiDevice mDevice;
 
     private List<UiObject2> mLocatorResults;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mLocatorResults0 = Collections.singletonList(mResult0);
         mLocatorResults1 = Collections.singletonList(mResult1);
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
index 21e5564..81ce3d08 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
@@ -13,11 +13,13 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -57,6 +59,7 @@
 
     @Mock private UiObject2 mResult411;
 
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock private UiDevice mDevice;
 
     private List<UiObject2> mLocator0Results;
@@ -68,8 +71,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mLocator0Results = Collections.singletonList(mLocator0Result);
         mLocator1Results = Collections.singletonList(mLocator1Result);
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
index 73e3d6a..f2933fa 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
@@ -20,11 +20,13 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -39,6 +41,7 @@
 @Config(manifest = Config.NONE)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class Ui2LocatorsTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Mock UiDevice mDevice;
 
     @Mock Resources mResources;
@@ -57,8 +60,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
         mRootAsList = Collections.singletonList(mRoot);
 
         mChild0And1 = new ArrayList<>();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BaseCtaTransitTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BaseCtaTransitTestRule.java
index ab02befb..f5679913 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BaseCtaTransitTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BaseCtaTransitTestRule.java
@@ -54,6 +54,10 @@
         return mActivityTestRule.getTestServer();
     }
 
+    public Tab getActivityTab() {
+        return mActivityTestRule.getActivityTab();
+    }
+
     // TODO(crbug.com/406324209): Create WebPageStation#getWebContents() and replace these calls.
     public WebContents getWebContents() {
         return mActivityTestRule.getWebContents();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/Journeys.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/Journeys.java
index 0dc924b..36b7cd92 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/Journeys.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/Journeys.java
@@ -7,8 +7,10 @@
 import static org.junit.Assert.assertTrue;
 
 import static org.chromium.base.test.transit.Triggers.noopTo;
+import static org.chromium.chrome.test.util.ChromeTabUtils.getTabCountOnUiThread;
 
 import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.Token;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.transit.TravelException;
@@ -171,8 +173,10 @@
             boolean captureThumbnails) {
         assert urlsForRegularTabs.size() >= 1;
         TabModelSelector tabModelSelector = startingStation.getTabModelSelector();
-        int currentTabCount = tabModelSelector.getModel(/* incognito= */ false).getCount();
-        int currentIncognitoTabCount = tabModelSelector.getModel(/* incognito= */ true).getCount();
+        int currentTabCount =
+                getTabCountOnUiThread(tabModelSelector.getModel(/* incognito= */ false));
+        int currentIncognitoTabCount =
+                getTabCountOnUiThread(tabModelSelector.getModel(/* incognito= */ true));
         assert currentTabCount == 1;
         assert currentIncognitoTabCount == 0;
         T station =
@@ -337,7 +341,7 @@
         List<Token> tabGroupIdsOfGroupedTabs = new ArrayList<>();
         for (Tab tab : tabs) {
             int id = tab.getId();
-            Tab tabById = currentModel.getTabById(id);
+            Tab tabById = ThreadUtils.runOnUiThreadBlocking(() -> currentModel.getTabById(id));
             if (tabById != null) {
                 Token tabGroupId = tabById.getTabGroupId();
                 tabGroupIdsOfGroupedTabs.add(tabGroupId);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModeConditions.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModeConditions.java
index b532970c..8e88f09 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModeConditions.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/dom_distiller/ReaderModeConditions.java
@@ -1,3 +1,7 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 package org.chromium.chrome.test.transit.dom_distiller;
 
 import org.chromium.base.test.transit.Condition;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
index 4664ae4c..6623804 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabGroupDialogFacility.java
@@ -103,28 +103,17 @@
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING)
                 || ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING_JOIN_ONLY)) {
             // TODO(ckitagawa): Add handling for an already shared group.
-            if (mHostStation.getPhase() == Phase.ACTIVE) {
-                // TODO(crbug.com/384533121): When declareElementFactory works with Conditions from
-                // past transitions, remove this check and always use declareElementFactory().
-                if (isAllowedToShare()) {
-                    shareButtonElement =
-                            declareView(toolbarElement.descendant(withId(R.id.share_button)));
-                }
-            } else if (mHostStation.getPhase() != Phase.FINISHED) {
-                // Make this a delayed element check to ensure the tab model is available on check.
-                declareElementFactory(
-                        mHostStation.tabModelElement,
-                        delayedElements -> {
-                            if (isAllowedToShare()) {
-                                shareButtonElement =
-                                        delayedElements.declareView(
-                                                toolbarElement.descendant(
-                                                        withId(R.id.share_button)));
-                            }
-                        });
-            } else { // mHostStation.getPhase() == Phase.FINISHED
-                throw new IllegalStateException("Station is already FINISHED: " + mHostStation);
-            }
+
+            // Make this a delayed element check to ensure the tab model is available on check.
+            declareElementFactory(
+                    mHostStation.tabModelElement,
+                    delayedElements -> {
+                        if (isAllowedToShare()) {
+                            shareButtonElement =
+                                    delayedElements.declareView(
+                                            toolbarElement.descendant(withId(R.id.share_button)));
+                        }
+                    });
 
             // Data sharing layout causes the menu button to be hidden due to the rounded corner.
             listMenuButtonElement =
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabCountChangedCondition.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabCountChangedCondition.java
index 32c176d6..de5760e 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabCountChangedCondition.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabCountChangedCondition.java
@@ -4,12 +4,14 @@
 
 package org.chromium.chrome.test.transit.tabmodel;
 
+import static org.chromium.chrome.test.util.ChromeTabUtils.getTabCountOnUiThread;
+
 import org.chromium.base.test.transit.ConditionStatus;
-import org.chromium.base.test.transit.InstrumentationThreadCondition;
+import org.chromium.base.test.transit.UiThreadCondition;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 
 /** Condition fulfilled when N number of tabs are opened/closed. */
-public class TabCountChangedCondition extends InstrumentationThreadCondition {
+public class TabCountChangedCondition extends UiThreadCondition {
     private final TabModel mTabModel;
     private int mStartingTabs = -1;
     private final int mExpectedChange;
@@ -41,7 +43,7 @@
     @Override
     public void onStartMonitoring() {
         super.onStartMonitoring();
-        mStartingTabs = mTabModel.getCount();
+        mStartingTabs = getTabCountOnUiThread(mTabModel);
     }
 
     @Override
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabGroupCreatedCondition.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabGroupCreatedCondition.java
index 318c610..598b68c 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabGroupCreatedCondition.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabGroupCreatedCondition.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.Token;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.transit.ConditionStatusWithResult;
@@ -29,7 +30,8 @@
     public void onStartMonitoring() {
         super.onStartMonitoring();
         TabGroupModelFilter tabGroupModelFilter = mTabGroupModelFilterSupplier.get();
-        mOriginalTabGroupIds = tabGroupModelFilter.getAllTabGroupIds();
+        mOriginalTabGroupIds =
+                ThreadUtils.runOnUiThreadBlocking(() -> tabGroupModelFilter.getAllTabGroupIds());
     }
 
     @Override
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
index bbbd84c8..e157762 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -130,6 +130,14 @@
                 && !tab.getWebContents().shouldShowLoadingUI();
     }
 
+    public static Tab getActivityTab(ChromeActivity activity) {
+        return ThreadUtils.runOnUiThreadBlocking(() -> activity.getActivityTab());
+    }
+
+    public static int getIndexOnUiThread(TabModel tabModel) {
+        return ThreadUtils.runOnUiThreadBlocking(() -> tabModel.index());
+    }
+
     public static int getTabCountOnUiThread(TabModel tabModel) {
         return ThreadUtils.runOnUiThreadBlocking(() -> tabModel.getCount());
     }
@@ -536,7 +544,7 @@
         }
         ThreadUtils.runOnUiThreadBlocking(() -> tabModel.removeObserver(observer));
 
-        Tab tab = activity.getActivityTab();
+        Tab tab = getActivityTab(activity);
         waitForTabPageLoaded(tab, (String) null);
         if (waitForNtpLoad) NewTabPageTestUtils.waitForNtpLoaded(tab);
         instrumentation.waitForIdleSync();
@@ -569,7 +577,7 @@
             final boolean incognito) {
         newTabFromMenu(instrumentation, activity, incognito, false);
 
-        final Tab tab = activity.getActivityTab();
+        final Tab tab = getActivityTab(activity);
         waitForTabPageLoaded(
                 tab,
                 url,
diff --git a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/elhlgakmbkdkoajdlnfkhjbpgmbpjdig.pem b/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/elhlgakmbkdkoajdlnfkhjbpgmbpjdig.pem
deleted file mode 100644
index 0ea431e..0000000
--- a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/elhlgakmbkdkoajdlnfkhjbpgmbpjdig.pem
+++ /dev/null
@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvfkz/kZMLFvJ5
-4lHJykMujn/JgHjBDXgQg1Ya0D/PUwQWc66nnL9Z1k+fQTJBmzK7l0fMwocandrM
-9SMmAJ11OtEYO/G/nFBaHx7N5jl9WE+3Kna351qIlKT3GpkyGWJ7uBOeRWdD38o4
-dS3QvEaHdOC3v5xOAKDEOKH7iWS0mQa/Qy9NNU5Ck+QK2MBQ4QhrUgyJrIzins8Y
-Ls1b7vqKBarJuaPnBOrCie34ZlnG5SIuPI1DFg6LLDfF7CX7BYhi+OM8sWqsyx/4
-Swee1Yueileiuw66qpPRzgKrv3MGJIKZsAXmB8ytCHHRHU8yt2tCC6BH7kkU7x3t
-eqp8AE6vAgMBAAECggEASuOr+hfmVwIo4Wh6HJGqz7BRyeyAG2ojBXD2iqS5xkCX
-6vjc3HwgkDbLbZuF1cdkA/eP1UpiGzKnz3UA1dPHXeKGnj/ebzVGeN7050rK17ma
-8wA0/0/EK6q7JxP7sgxxIXixLoZRhf53LlabAYuG0YFH8EHdctADyxibz1qXVhWN
-SjhiPhB6pSiqtLb+l2hKLJLQYeHfApswTaBzHeoOzXpQNoVI+Tq9t1yNt7oSWCQt
-8+06vr/kW+SxmoiAfSrw7edeWnE5O6+ut8K3M9zBovt1+nsDf7D63XfDyPLxHWCE
-6k7a+DCWrzeo72AglJYD77GqOqtFM7wmLbqqgOlSqQKBgQDublm+IE2Yz6bISUOn
-09od/AxujApK3xZGykEFyXGkinI5DHnJ/FTIVAjvSKrHd6Z2O5FTaWSmv/d2CRMX
-mr+r1tvxodZxlwuxaXwipHlUt/uShm5d5WbNe3b5N1zWrKpSWKx2PCPlFJnRfxqj
-UFKBQTg25vZz/q9eXdz1wlOnnQKBgQC8bLlAyP7hGyF38GWajtmp+dcF8TzKasQt
-rQTnbseVb/aeIs33WaRYWH79T5NZiWSj35miu6dvpkn4a2N8jWfUbfCelUQwHhQQ
-EeJpDPX2swfrN7uty/grcb/YBw56n+P3IK0aOymjZw3hRjhP65jpQVqAeGpIFYgl
-L5YpRfuruwKBgQDdlE3wZALZFXlQvs2SJU6Z+QfwoFJcXFBOf13IK/phyIv4OoDg
-VpDQD1CyV1zmvGpFjHw1AUgZs2MdHbfRgu3Hm4iRWS56J74lJPvJEgLz2XuBI09k
-EXHlWm0pk+rCUnqCxoeX5bISDYAZcj7mMRpLprnARAobqD9/uklDV1H4/QKBgHsS
-MLYmEoSJqgSjGlonb/hb3ZxeAyzbK6QB3LAlZWswJE8JwKoM/RFPTDK8JSxYV0nK
-JJlsJGMCpFIEIokZ+3V/EakjKdSb8NLGO7IN6yHlsghq8MUF8uS9eWbqxQRHJykl
-SKtXdUzrZN99dA6PfeLs8uXywMiwd6qCOHxg3489AoGAA2xJn33YJamYR+DY3DSy
-HACFee8FoicBN0T+WWZGIo9yxSfqW5qr8oaBQ8xPbaz1k9FA+Dps7mfN1CkxMNNd
-FXqc+bCpNTchvCx05BuT2lYPm6ziVHXiOsRi6cfoP5QU4tTSnGE2apPkqxyRcNSi
-8P7FuZcC2F3CjtqQJvUNGBs=
------END PRIVATE KEY-----
diff --git a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-128.png b/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-128.png
deleted file mode 100644
index 5c226f3..0000000
--- a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-128.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-16.png b/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-16.png
deleted file mode 100644
index c7510d38..0000000
--- a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/icon-16.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/manifest.json b/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/manifest.json
deleted file mode 100644
index 6ba851e..0000000
--- a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/manifest.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "manifest_version": 3,
-  "name": "Kiosk Input API Test Extension",
-  "description": "Companion Extension for KioskEnterpriseInputApiBrowserTest",
-  "version": "1.0",
-  "icons": {
-    "128": "icon-128.png",
-    "16": "icon-16.png"
-  },
-  "permissions": [
-    "enterprise.kioskInput"
-  ],
-  "background": {
-    "service_worker": "service_worker.js"
-  },
-  "externally_connectable": {
-    "matches": [
-      "<all_urls>"
-    ]
-  }
-}
diff --git a/chrome/test/data/chromeos/app_mode/webstore/downloads/elhlgakmbkdkoajdlnfkhjbpgmbpjdig-1.0.0.crx b/chrome/test/data/chromeos/app_mode/webstore/downloads/elhlgakmbkdkoajdlnfkhjbpgmbpjdig-1.0.0.crx
deleted file mode 100644
index dfb9f34..0000000
--- a/chrome/test/data/chromeos/app_mode/webstore/downloads/elhlgakmbkdkoajdlnfkhjbpgmbpjdig-1.0.0.crx
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/enterprise_kiosk_input.pem b/chrome/test/data/extensions/api_test/enterprise_kiosk_input.pem
new file mode 100644
index 0000000..5905702
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/enterprise_kiosk_input.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC6gaLSBi7T3p7J
+wE73/FEavkOzLWDeom/eZhY/dDp+Bh4SdBYytFfwqPyA591GdG+nuYutot0/7Tug
+OQt4MiYo2Jxlx+UAdmQQoGR8BA0kWN2nbhx2I6b/dZXnCjJ1KxOIcQY1j+ESv5B0
+1n9mY95TtRBCsXV+X3NgEHO6Skn0pF52AI8A8/PAxN8H/4r+gPfn96G7iI6GK9Km
+/mP8uBz80R8SJuiHkY/I9b1VmHsjTv9naU+o4tybAsLw8hzw/S1hkHx6JEgFB0CQ
+UCCwPDC3FuUyVfDTM/K7PVZlpkg9bfnTrvcLUzZ6N66y8sl8skRXUDe3ItPGHG6U
+PDU0QM7TAgMBAAECggEAEle8mTZVda3v5Py+Z4JPwbcTtnQQkmTcZr2Yk44NUKau
+X3c+VadJ/NfJ2a20JAFAl/jWJXIem3JsClKB78TS3vKK0zHJMnXyWnZD27SUTE5X
+ImfgcbgI7Rf18b6dfsuJRMKE71CivLLNdMhByGKrE4V7v2tvmEmv8bM8hoZW5rH2
+rqFr1qKCXsVDdNy9jyCaP/9MnZU1L7ENHRFFMdzGrGG7DqXU99vkUTYGiLcHYe8C
+II1iHc37OQp5/eR20LZ5ZEtMYSeNeqUvPsZSYBHyxW+slYJH9yYwUOOprSgUVH3Y
+bhlY3joYGK1kYzubMinffwfvSJ8vJaDtsY3H+/V/+QKBgQDoUGW2Zd1LOkN33Eh0
+73KlxC9ceHyDG9ez+7FCX8Ja4jUTqVLPtYZudiVuRadsjb7I8lPaEnle8gyGhYDV
+MFsqZGA1surqBK+jYejknoG/AZDoS/bjeD0hSZnFu8FXhW2Z/Dkx/630I5pOZ5oy
+wJdwHUxO6jd+gAuKRLUb9le+ewKBgQDNhZ4+QshLkzW2SIXCjsgLnf3TRugb+0nc
+S9g2R+flNUOOXQRUVGwS6/iczMvlskiUXgb+0wmDGbZZUclitrY5Ss8j3khqNObr
+aCFTXjEWSJ6r7aAH/wgTq4Ij3UdcczQcFeeuYjYtCfXODI1+2pDDoOL9pmT6P5G0
+A8Rw45ztiQKBgQCY1ivUb/fCwjYY6QeSRuX6QLOX9nyUFQE4G+JmdHF9MU0R/lfI
+5vfmPDwr7A9Vz3sw4Jxh372RxVSQO8yidQnFPfw919PM2gBjUMrTfaSGcRVQfomS
+5UvyVmWgPQHZ/qI4qENIrZlYAQRHiMldkm8PB3dog5a21q7A7KrqFotreQKBgQC+
+QYytPGtpMvzNIzPYWQ8tWfPIq2JhzO2iJwAft88fq4A/gTJp0sE9fv7mQNwcZj+0
+QZseOUUb/SiGZSUV4eis/ujk3niRASooEHyRTagJZe6lYFP+MwRKGUJfaxANsIQz
+379a+oYGiaroNUyjezf6Ma0QfQILe9+pEre+facfaQKBgQDETrBre2t4M7oHfgHj
+apGgmr/RKZzc9ANDzjHL6dr8YehF2+dZDLkwJn1H91wdqwI3xOqH/DagwLUvrXiY
+7M8neBDbKh4uo6ukpC6ZnS2TLBgzwTf5L7vUOP7Pa2D5Au0Cht5uWAqHckajA+2a
+0g2dRiZbbwqiCygMiIU0AINRvA==
+-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/api_test/enterprise_kiosk_input/DIR_METADATA b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/DIR_METADATA
new file mode 100644
index 0000000..d4effef
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//chrome/browser/ash/app_mode/COMMON_METADATA"
diff --git a/chrome/test/data/extensions/api_test/enterprise_kiosk_input/OWNERS b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/OWNERS
new file mode 100644
index 0000000..f782149
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/OWNERS
@@ -0,0 +1 @@
+file://chromeos/components/kiosk/OWNERS
diff --git a/chrome/test/data/extensions/api_test/enterprise_kiosk_input/manifest.json b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/manifest.json
new file mode 100644
index 0000000..73a197c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/manifest.json
@@ -0,0 +1,17 @@
+{
+    "name": "Kiosk Input API Test Extension",
+    "description": "Companion Extension for KioskEnterpriseInputApiBrowserTest",
+    "version": "1.3",
+    "manifest_version": 3,
+    "permissions": [
+        "enterprise.kioskInput"
+    ],
+    "background": {
+        "service_worker": "service_worker.js"
+    },
+    "externally_connectable": {
+        "matches": [
+            "<all_urls>"
+        ]
+    }
+}
diff --git a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/service_worker.js b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/service_worker.js
similarity index 85%
rename from chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/service_worker.js
rename to chrome/test/data/extensions/api_test/enterprise_kiosk_input/service_worker.js
index 8f9184b05..55d7220 100644
--- a/chrome/test/data/chromeos/app_mode/apps_and_extensions/input_extension/src/service_worker.js
+++ b/chrome/test/data/extensions/api_test/enterprise_kiosk_input/service_worker.js
@@ -11,6 +11,9 @@
       case "set_input_method":
         runSetInputMethod(data, sendResponse);
         return true;
+      case "version":
+        sendResponse("1.3");
+        return false;
     }
     sendResponse('unknown message "' + message + '"');
     return false;
@@ -28,5 +31,5 @@
   );
 }
 
-// Report back to the browsertest that the extension is ready.
+// Trigger `kReadyMessageReceived` in `extension_force_install_mixin.cc`.
 chrome.test?.sendMessage && chrome.test.sendMessage('ready')
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn
index 42b1706..bedc78e7 100644
--- a/chrome/test/data/webui/new_tab_page/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -40,7 +40,6 @@
 
   ts_deps = [
     "//chrome/browser/resources/new_tab_page:build_ts",
-    "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/cr_components/help_bubble:build_ts",
     "//ui/webui/resources/cr_components/history_clusters:build_ts",
     "//ui/webui/resources/cr_components/most_visited:build_ts",
diff --git a/chrome/test/data/webui/new_tab_page/modules/v2/calendar/calendar_test.ts b/chrome/test/data/webui/new_tab_page/modules/v2/calendar/calendar_test.ts
index d841b92..e37b465 100644
--- a/chrome/test/data/webui/new_tab_page/modules/v2/calendar/calendar_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/v2/calendar/calendar_test.ts
@@ -115,8 +115,9 @@
           element.shadowRoot.querySelectorAll('ntp-calendar-event');
       assertEquals(eventElements.length, 2);
       const expandedEvent = eventElements[0];
-      assertTrue(expandedEvent!.hasAttribute('expanded'));
-      assertEquals(expandedEvent!.event.title, 'Test Event 1');
+      assertTrue(!!expandedEvent);
+      assertTrue(expandedEvent.hasAttribute('expanded'));
+      assertEquals(expandedEvent.event.title, 'Test Event 1');
     });
 
     test('prioritize event with other attendee', async () => {
@@ -140,8 +141,9 @@
           element.shadowRoot.querySelectorAll('ntp-calendar-event');
       assertEquals(eventElements.length, 2);
       const expandedEvent = eventElements[0];
-      assertTrue(expandedEvent!.hasAttribute('expanded'));
-      assertEquals(expandedEvent!.event.title, 'Test Event 1');
+      assertTrue(!!expandedEvent);
+      assertTrue(expandedEvent.hasAttribute('expanded'));
+      assertEquals(expandedEvent.event.title, 'Test Event 1');
     });
 
     test('do not expand any meetings if they are all over', async () => {
diff --git a/chrome/test/data/webui/new_tab_page/modules/v2/modules_test.ts b/chrome/test/data/webui/new_tab_page/modules/v2/modules_test.ts
index 0b545821..cc00f103d 100644
--- a/chrome/test/data/webui/new_tab_page/modules/v2/modules_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/v2/modules_test.ts
@@ -751,9 +751,9 @@
         moduleWrappers =
             modulesElement.shadowRoot.querySelectorAll('ntp-module-wrapper');
         assertEquals(1, moduleWrappers.length);
-        assertEquals(
-            fooDescriptor.id,
-            (moduleWrappers[0] as ModuleWrapperElement).module.descriptor.id);
+        const fooModule = (moduleWrappers[0] as ModuleWrapperElement).module;
+        assert(fooModule);
+        assertEquals(fooDescriptor.id, fooModule.descriptor.id);
         assertEquals(
             1, metrics.count('NewTabPage.Modules.ReloadedModulesCount'));
         assertEquals(
@@ -813,9 +813,9 @@
         let moduleWrappers =
             modulesElement.shadowRoot.querySelectorAll('ntp-module-wrapper');
         assertEquals(1, moduleWrappers.length);
-        assertEquals(
-            fooDescriptor.id,
-            (moduleWrappers[0] as ModuleWrapperElement).module.descriptor.id);
+        const fooModule = (moduleWrappers[0] as ModuleWrapperElement).module;
+        assert(fooModule);
+        assertEquals(fooDescriptor.id, fooModule.descriptor.id);
         assertEquals(1, metrics.count('NewTabPage.Modules.LoadedModulesCount'));
         assertEquals(
             1, metrics.count('NewTabPage.Modules.LoadedModulesCount', 1));
@@ -843,12 +843,12 @@
         assertEquals(2, moduleWrappers.length);
         // Ensure the 'foo' module loads last, as it was not included in the
         // module order returned by |getModulesOrder()|.
-        assertEquals(
-            barDescriptor.id,
-            (moduleWrappers[0] as ModuleWrapperElement).module.descriptor.id);
-        assertEquals(
-            fooDescriptor.id,
-            (moduleWrappers[1] as ModuleWrapperElement).module.descriptor.id);
+        let wrapperModule = (moduleWrappers[0] as ModuleWrapperElement).module;
+        assert(wrapperModule);
+        assertEquals(barDescriptor.id, wrapperModule.descriptor.id);
+        wrapperModule = (moduleWrappers[1] as ModuleWrapperElement).module;
+        assert(wrapperModule);
+        assertEquals(fooDescriptor.id, wrapperModule.descriptor.id);
         assertEquals(1, metrics.count('NewTabPage.Modules.LoadedModulesCount'));
         assertEquals(
             1, metrics.count('NewTabPage.Modules.ReloadedModulesCount'));
@@ -880,7 +880,7 @@
             assertEquals(1, moduleWrappers.length);
 
             let fooModule = moduleWrappers[0] as ModuleWrapperElement;
-            assertEquals(fooDescriptor.id, fooModule.module.descriptor.id);
+            assertEquals(fooDescriptor.id, fooModule.module!.descriptor.id);
             assertNotStyle(fooModule, 'display', 'none');
             // Disable foo module.
             callbackRouterRemote.setDisabledModules(
@@ -902,7 +902,7 @@
                 'ntp-module-wrapper');
             assertEquals(1, moduleWrappers.length);
             fooModule = moduleWrappers[0] as ModuleWrapperElement;
-            assertEquals(fooDescriptor.id, fooModule.module.descriptor.id);
+            assertEquals(fooDescriptor.id, fooModule.module!.descriptor.id);
             assertNotStyle(fooModule, 'display', 'none');
           });
 
@@ -918,9 +918,9 @@
         let moduleWrappers =
             modulesElement.shadowRoot.querySelectorAll('ntp-module-wrapper');
         assertEquals(1, moduleWrappers.length);
-        assertEquals(
-            fooDescriptor.id,
-            (moduleWrappers[0] as ModuleWrapperElement).module.descriptor.id);
+        let fooModule = (moduleWrappers[0] as ModuleWrapperElement).module;
+        assert(fooModule);
+        assertEquals(fooDescriptor.id, fooModule.descriptor.id);
         // Prepare to load bar module.
         const barModulePromise = getModulePromise(barDescriptor);
         moduleRegistry.setResultFor('initializeModuleById', barModulePromise);
@@ -941,12 +941,12 @@
         moduleWrappers =
             modulesElement.shadowRoot.querySelectorAll('ntp-module-wrapper');
         assertEquals(2, moduleWrappers.length);
-        assertEquals(
-            fooDescriptor.id,
-            (moduleWrappers[0] as ModuleWrapperElement).module.descriptor.id);
-        assertEquals(
-            barDescriptor.id,
-            (moduleWrappers[1] as ModuleWrapperElement).module.descriptor.id);
+        fooModule = (moduleWrappers[0] as ModuleWrapperElement).module;
+        assert(fooModule);
+        assertEquals(fooDescriptor.id, fooModule.descriptor.id);
+        const barModule = (moduleWrappers[1] as ModuleWrapperElement).module;
+        assert(barModule);
+        assertEquals(barDescriptor.id, barModule.descriptor.id);
       });
 
       test(
@@ -983,7 +983,7 @@
                 'ntp-module-wrapper');
             assertEquals(1, moduleWrappers.length);
             const fooModule = moduleWrappers[0] as ModuleWrapperElement;
-            assertEquals(fooDescriptor.id, fooModule.module.descriptor.id);
+            assertEquals(fooDescriptor.id, fooModule.module!.descriptor.id);
           });
     });
 
@@ -1010,7 +1010,7 @@
           } else {
             assertEquals(1, moduleWrappers.length);
             const fooModule = moduleWrappers[0] as ModuleWrapperElement;
-            assertEquals(fooDescriptor.id, fooModule.module.descriptor.id);
+            assertEquals(fooDescriptor.id, fooModule.module!.descriptor.id);
             assertNotStyle(fooModule, 'display', 'none');
           }
         });
@@ -1040,7 +1040,7 @@
             modulesElement.shadowRoot.querySelectorAll('ntp-module-wrapper');
         assertEquals(1, moduleWrappers.length);
         const fooModule = moduleWrappers[0] as ModuleWrapperElement;
-        assertEquals(fooDescriptor.id, fooModule.module.descriptor.id);
+        assertEquals(fooDescriptor.id, fooModule.module!.descriptor.id);
         assertNotStyle(fooModule, 'display', 'none');
       });
     });
diff --git a/chrome/test/user_education/interactive_feature_promo_test.cc b/chrome/test/user_education/interactive_feature_promo_test.cc
index fb28ca51..2f1d899 100644
--- a/chrome/test/user_education/interactive_feature_promo_test.cc
+++ b/chrome/test/user_education/interactive_feature_promo_test.cc
@@ -246,6 +246,13 @@
 }
 
 InteractiveFeaturePromoTestApi::StepBuilder
+InteractiveFeaturePromoTestApi::CheckPromoActive(
+    const base::Feature& iph_feature,
+    bool active) {
+  return CheckPromoImpl(iph_feature, active, false);
+}
+
+InteractiveFeaturePromoTestApi::StepBuilder
 InteractiveFeaturePromoTestApi::CheckPromoImpl(const base::Feature& iph_feature,
                                                bool requested,
                                                bool include_queued) {
diff --git a/chrome/test/user_education/interactive_feature_promo_test.h b/chrome/test/user_education/interactive_feature_promo_test.h
index 67b05fa7..6f95248 100644
--- a/chrome/test/user_education/interactive_feature_promo_test.h
+++ b/chrome/test/user_education/interactive_feature_promo_test.h
@@ -145,6 +145,12 @@
       const base::Feature& iph_feature,
       bool requested = true);
 
+  // Same as `CheckPromoRequested()` but ignores queued promos. Usually prefer
+  // to use `CheckPromoRequested()`. Note that "active" includes both "bubble
+  // visible" and "bubble closed but promo continued".
+  [[nodiscard]] StepBuilder CheckPromoActive(const base::Feature& iph_feature,
+                                             bool requested = true);
+
   // Ends the specified promo via the API, with reason `kAborted`.
   [[nodiscard]] MultiStep AbortPromo(const base::Feature& iph_feature,
                                      bool expected_result = true);
diff --git a/chromeos/ash/components/dbus/BUILD.gn b/chromeos/ash/components/dbus/BUILD.gn
index c01f894e5..3cde444 100644
--- a/chromeos/ash/components/dbus/BUILD.gn
+++ b/chromeos/ash/components/dbus/BUILD.gn
@@ -59,7 +59,6 @@
     "//chromeos/ash/components/dbus/device_management:unit_tests",
     "//chromeos/ash/components/dbus/dlcservice:unit_tests",
     "//chromeos/ash/components/dbus/easy_unlock:unit_tests",
-    "//chromeos/ash/components/dbus/featured:unit_tests",
     "//chromeos/ash/components/dbus/fwupd:test_support",
     "//chromeos/ash/components/dbus/gnubby:unit_tests",
     "//chromeos/ash/components/dbus/hermes:test_support",
diff --git a/chromeos/ash/components/dbus/featured/BUILD.gn b/chromeos/ash/components/dbus/featured/BUILD.gn
deleted file mode 100644
index b4b4e9b..0000000
--- a/chromeos/ash/components/dbus/featured/BUILD.gn
+++ /dev/null
@@ -1,47 +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.
-
-import("//third_party/protobuf/proto_library.gni")
-
-assert(is_chromeos)
-
-component("featured") {
-  defines = [ "IS_CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_IMPL" ]
-
-  deps = [
-    ":proto",
-    "//base",
-    "//dbus",
-  ]
-
-  sources = [
-    "fake_featured_client.cc",
-    "fake_featured_client.h",
-    "featured_client.cc",
-    "featured_client.h",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-
-  deps = [
-    ":featured",
-    ":proto",
-    "//base",
-    "//base/test:test_support",
-    "//dbus",
-    "//dbus:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-  ]
-
-  sources = [ "featured_client_unittest.cc" ]
-}
-
-proto_library("proto") {
-  sources = [ "//third_party/cros_system_api/dbus/featured/featured.proto" ]
-
-  proto_out_dir = "chromeos/ash/components/dbus/featured"
-}
diff --git a/chromeos/ash/components/dbus/featured/fake_featured_client.cc b/chromeos/ash/components/dbus/featured/fake_featured_client.cc
deleted file mode 100644
index 6fe93cb..0000000
--- a/chromeos/ash/components/dbus/featured/fake_featured_client.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/ash/components/dbus/featured/fake_featured_client.h"
-
-#include "base/check_op.h"
-#include "base/containers/queue.h"
-#include "base/functional/callback.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#include "dbus/object_proxy.h"
-
-namespace ash::featured {
-
-namespace {
-
-// Used to track the fake instance, mirrors the instance in the base class.
-FakeFeaturedClient* g_instance = nullptr;
-
-}  // namespace
-
-FakeFeaturedClient::FakeFeaturedClient() {
-  DCHECK(!g_instance);
-  g_instance = this;
-}
-
-FakeFeaturedClient::~FakeFeaturedClient() {
-  DCHECK_EQ(this, g_instance);
-  g_instance = nullptr;
-}
-
-// static
-FakeFeaturedClient* FakeFeaturedClient::Get() {
-  return g_instance;
-}
-
-void FakeFeaturedClient::HandleSeedFetched(
-    const ::featured::SeedDetails& safe_seed,
-    base::OnceCallback<void(bool success)> callback) {
-  handle_seed_fetched_attempts_++;
-
-  if (responses_.empty()) {
-    std::move(callback).Run(false);
-    return;
-  }
-
-  bool success = responses_.front();
-  if (success) {
-    // We only want to save the safe seed if the response (success) is valid.
-    latest_safe_seed_ = safe_seed;
-  }
-  responses_.pop();
-  std::move(callback).Run(success);
-}
-
-void FakeFeaturedClient::AddResponse(bool success) {
-  responses_.push(success);
-}
-
-}  // namespace ash::featured
diff --git a/chromeos/ash/components/dbus/featured/fake_featured_client.h b/chromeos/ash/components/dbus/featured/fake_featured_client.h
deleted file mode 100644
index 40db5ef..0000000
--- a/chromeos/ash/components/dbus/featured/fake_featured_client.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FAKE_FEATURED_CLIENT_H_
-#define CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FAKE_FEATURED_CLIENT_H_
-
-#include "base/component_export.h"
-#include "base/containers/queue.h"
-#include "base/functional/callback.h"
-#include "base/logging.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#include "chromeos/ash/components/dbus/featured/featured_client.h"
-
-namespace ash::featured {
-
-// Fake implementation of FeaturedClient.
-class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED) FakeFeaturedClient
-    : public FeaturedClient {
- public:
-  FakeFeaturedClient();
-
-  FakeFeaturedClient(const FakeFeaturedClient&) = delete;
-  FakeFeaturedClient& operator=(const FakeFeaturedClient&) = delete;
-
-  ~FakeFeaturedClient() override;
-
-  // Returns the global FakeFeaturedClient instance. Returns `nullptr` if
-  // it is not initialized.
-  static FakeFeaturedClient* Get();
-
-  // |callback| is run with the first response in `responses_`. Call
-  // `AddResponse` to add a response. |callback| is invoked with false if not
-  // enough responses are provided.
-  void HandleSeedFetched(
-      const ::featured::SeedDetails& safe_seed,
-      base::OnceCallback<void(bool success)> callback) override;
-
-  // Adds a response to call `HandleSeedFetched` with.
-  void AddResponse(bool success);
-
-  // Returns the number of times `HandleSeedFetched` was called. Used for
-  // testing.
-  int handle_seed_fetched_attempts() const {
-    return handle_seed_fetched_attempts_;
-  }
-
-  // Returns the safe seed received from HandleSeedFetched. Used for testing.
-  const ::featured::SeedDetails& latest_safe_seed() const {
-    return latest_safe_seed_;
-  }
-
- private:
-  base::queue<bool> responses_;
-  size_t handle_seed_fetched_attempts_ = 0;
-  ::featured::SeedDetails latest_safe_seed_;
-};
-
-}  // namespace ash::featured
-
-#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FAKE_FEATURED_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/featured/featured_client.cc b/chromeos/ash/components/dbus/featured/featured_client.cc
deleted file mode 100644
index ea1c966e..0000000
--- a/chromeos/ash/components/dbus/featured/featured_client.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/ash/components/dbus/featured/featured_client.h"
-
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "base/check_is_test.h"
-#include "base/files/dir_reader_posix.h"
-#include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
-#include "base/files/file_util.h"
-#include "base/functional/callback.h"
-#include "base/logging.h"
-#include "base/memory/raw_ptr.h"
-#include "base/metrics/field_trial.h"
-#include "base/strings/escape.h"
-#include "base/strings/string_split.h"
-#include "base/task/thread_pool.h"
-#include "chromeos/ash/components/dbus/featured/fake_featured_client.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_proxy.h"
-#include "third_party/cros_system_api/constants/featured.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-
-namespace ash::featured {
-
-namespace {
-
-FeaturedClient* g_instance = nullptr;
-
-struct FileWatchOptions {
-  FeaturedClient::ListenForTrialCallback listen_callback;
-  const base::FilePath expected_dir;
-};
-
-void RecordEarlyBootTrialInUMA(const std::string& trial_name,
-                               const std::string& group_name) {
-  base::FieldTrial* trial =
-      base::FieldTrialList::CreateFieldTrial(trial_name, group_name);
-  // This records the trial in UMA.
-  trial->Activate();
-}
-
-// Assumes |filename| is valid (that its directory name is correct).
-bool RecordEarlyBootTrialInChrome(
-    FeaturedClient::ListenForTrialCallback listen_callback,
-    const base::FilePath& filename) {
-  base::FieldTrial::ActiveGroup active_group;
-  if (!FeaturedClient::ParseTrialFilename(filename, active_group)) {
-    return false;
-  }
-  listen_callback.Run(active_group.trial_name, active_group.group_name);
-  return true;
-}
-
-void RecordEarlyBootTrialAfterChromeStartup(
-    const FileWatchOptions& opts,
-    const base::FilePathWatcher::ChangeInfo& change_info,
-    const base::FilePath& path,
-    bool error) {
-  if (error || path.DirName() != opts.expected_dir) {
-    // TODO(b/296394808): Add UMA metric if we enter this code path since it
-    // is not expected.
-    return;
-  }
-
-  if (change_info.file_path_type !=
-          base::FilePathWatcher::FilePathType::kFile ||
-      change_info.change_type != base::FilePathWatcher::ChangeType::kCreated) {
-    // Only record field trial files that were just created. We do not want to
-    // record a field trial on any of the other change options like
-    // base::FilePathWatcher::ChangeType::kModified or
-    // base::FilePathWatcher::ChangeType::kDeleted.
-    return;
-  }
-
-  // TODO(b/296394808): Add UMA metric if unable to record trial due to parse
-  // error.
-  RecordEarlyBootTrialInChrome(opts.listen_callback, path);
-}
-
-void ListenForActiveEarlyBootTrials(base::FilePathWatcher* watcher,
-                                    const FileWatchOptions& opts) {
-  base::FilePathWatcher::WatchOptions options = {
-      // Watches for changes in a directory.
-      .type = base::FilePathWatcher::Type::kRecursive,
-      // Reports the path of modified files in the directory.
-      .report_modified_path = true};
-
-  watcher->WatchWithChangeInfo(
-      opts.expected_dir, options,
-      base::BindRepeating(&RecordEarlyBootTrialAfterChromeStartup, opts));
-}
-
-void ReadTrialsActivatedBeforeChromeStartup(const FileWatchOptions& opts) {
-  base::DirReaderPosix reader(opts.expected_dir.value().c_str());
-  if (!reader.IsValid()) {
-    // TODO(b/296394808): Add UMA metric if we are unable to enumerate trials
-    // activated before Chrome startup.
-    return;
-  }
-
-  while (reader.Next()) {
-    if (std::string(reader.name()) == "." ||
-        std::string(reader.name()) == "..") {
-      continue;
-    }
-    // TODO(b/296394808): Add UMA metric if unable to record trial due to
-    // parse error.
-    RecordEarlyBootTrialInChrome(opts.listen_callback,
-                                 base::FilePath(reader.name()));
-  }
-}
-
-// We need to delete the FilePathWatcher instance via a posted task since we
-// call FilePathWatche::Watch() on a posted task. The documentation states the
-// instance must be destroyed on the same sequence it watches from.
-void DeleteWatcher(std::unique_ptr<base::FilePathWatcher> watcher) {
-  watcher.reset();
-}
-
-// Production implementation of FeaturedClient.
-class FeaturedClientImpl : public FeaturedClient {
- public:
-  FeaturedClientImpl() : watcher_(std::make_unique<base::FilePathWatcher>()) {}
-
-  FeaturedClientImpl(const FeaturedClient&) = delete;
-  FeaturedClientImpl operator=(const FeaturedClient&) = delete;
-
-  ~FeaturedClientImpl() override {
-    file_listener_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&DeleteWatcher, std::move(watcher_)));
-  }
-
-  void Init(dbus::Bus* const bus) {
-    InitWithCallback(bus, base::FilePath(feature::kActiveTrialFileDirectory),
-                     base::BindRepeating(&RecordEarlyBootTrialInUMA));
-  }
-
-  void InitForTesting(dbus::Bus* const bus,  // IN-TEST
-                      const base::FilePath& expected_dir,
-                      ListenForTrialCallback callback) {
-    CHECK_IS_TEST();
-    InitWithCallback(bus, expected_dir, callback);
-  }
-
-  void HandleSeedFetchedResponse(
-      base::OnceCallback<void(bool success)> callback,
-      dbus::Response* response) {
-    if (!response ||
-        response->GetMessageType() != dbus::Message::MESSAGE_METHOD_RETURN) {
-      LOG(WARNING) << "Received invalid response for HandleSeedFetched";
-      std::move(callback).Run(false);
-      return;
-    }
-    std::move(callback).Run(true);
-  }
-
-  void HandleSeedFetched(
-      const ::featured::SeedDetails& safe_seed,
-      base::OnceCallback<void(bool success)> callback) override {
-    dbus::MethodCall method_call(::featured::kFeaturedInterface,
-                                 "HandleSeedFetched");
-
-    dbus::MessageWriter writer(&method_call);
-    writer.AppendProtoAsArrayOfBytes(safe_seed);
-
-    featured_service_proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::BindOnce(&FeaturedClientImpl::HandleSeedFetchedResponse,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-  }
-
- private:
-  void InitWithCallback(dbus::Bus* const bus,
-                        const base::FilePath& expected_dir,
-                        ListenForTrialCallback callback) {
-    featured_service_proxy_ =
-        bus->GetObjectProxy(::featured::kFeaturedServiceName,
-                            dbus::ObjectPath(::featured::kFeaturedServicePath));
-    expected_dir_ = expected_dir;
-    listen_callback_ = callback;
-    FileWatchOptions opts = {.listen_callback = callback,
-                             .expected_dir = expected_dir};
-    file_listener_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ListenForActiveEarlyBootTrials, watcher_.get(), opts));
-    file_listener_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ReadTrialsActivatedBeforeChromeStartup, opts));
-  }
-
-  // Callback used when early-boot trial files are written to `expected_dir_`.
-  FeaturedClient::ListenForTrialCallback listen_callback_;
-
-  // Directory where active trial files on platform are written to.
-  base::FilePath expected_dir_;
-
-  // Watches for early-boot trial files written to `expected_dir_`.
-  std::unique_ptr<base::FilePathWatcher> watcher_;
-
-  raw_ptr<dbus::ObjectProxy> featured_service_proxy_ = nullptr;
-
-  // Sequence runner that an post tasks that may block.
-  scoped_refptr<base::SequencedTaskRunner> file_listener_task_runner_ =
-      base::ThreadPool::CreateSequencedTaskRunner(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
-
-  // Note: This should remain the last member so it'll be destroyed and
-  // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<FeaturedClientImpl> weak_ptr_factory_{this};
-};
-
-}  // namespace
-
-FeaturedClient::FeaturedClient() {
-  DCHECK(!g_instance);
-  g_instance = this;
-}
-
-FeaturedClient::~FeaturedClient() {
-  DCHECK_EQ(this, g_instance);
-  g_instance = nullptr;
-}
-
-// static
-void FeaturedClient::Initialize(dbus::Bus* bus) {
-  DCHECK(bus);
-  (new FeaturedClientImpl())->Init(bus);
-}
-
-// static
-void FeaturedClient::InitializeFake() {
-  new FakeFeaturedClient();
-}
-
-// static
-void FeaturedClient::InitializeForTesting(dbus::Bus* bus,
-                                          const base::FilePath& expected_dir,
-                                          ListenForTrialCallback callback) {
-  DCHECK(bus);
-  (new FeaturedClientImpl())
-      ->InitForTesting(bus, expected_dir, callback);  // IN-TEST
-}
-
-// static
-void FeaturedClient::Shutdown() {
-  DCHECK(g_instance);
-  delete g_instance;
-}
-
-// static
-FeaturedClient* FeaturedClient::Get() {
-  return g_instance;
-}
-
-// static
-bool FeaturedClient::ParseTrialFilename(
-    const base::FilePath& path,
-    base::FieldTrial::ActiveGroup& active_group) {
-  std::string filename = path.BaseName().value();
-  std::vector<std::string_view> components =
-      base::SplitStringPiece(filename, feature::kTrialGroupSeparator,
-                             base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-  if (components.size() != 2) {
-    LOG(ERROR) << "Active trial filename not of the form TrialName,GroupName: "
-               << filename;
-    return false;
-  }
-
-  std::string trial_name = base::UnescapeURLComponent(
-      components[0],
-      base::UnescapeRule::SPACES | base::UnescapeRule::PATH_SEPARATORS |
-          base::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
-  std::string group_name = base::UnescapeURLComponent(
-      components[1],
-      base::UnescapeRule::SPACES | base::UnescapeRule::PATH_SEPARATORS |
-          base::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
-  active_group.trial_name = trial_name;
-  active_group.group_name = group_name;
-
-  return true;
-}
-
-}  // namespace ash::featured
diff --git a/chromeos/ash/components/dbus/featured/featured_client.h b/chromeos/ash/components/dbus/featured/featured_client.h
deleted file mode 100644
index 033aa160..0000000
--- a/chromeos/ash/components/dbus/featured/featured_client.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FEATURED_CLIENT_H_
-#define CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FEATURED_CLIENT_H_
-
-#include "base/component_export.h"
-#include "base/files/file_path.h"
-#include "base/functional/callback.h"
-#include "base/gtest_prod_util.h"
-#include "base/metrics/field_trial.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-
-namespace dbus {
-class Bus;
-}
-
-namespace ash::featured {
-
-// FeaturedClient is used to:
-//  * communicate seed state with featured, which is used for enabling and
-//  managing platform specific features.
-//  * record early-boot trials to UMA by listening for early-boot trial files
-//  written by featured.
-//
-// Its main user is Chrome field trials.
-class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED) FeaturedClient {
- public:
-  // Callback type for ListenForActiveEarlyBootTrials(), which takes in the
-  // trial name and group name of a field trial.
-  using ListenForTrialCallback =
-      base::RepeatingCallback<void(const std::string& trial_name,
-                                   const std::string& group_name)>;
-
-  // Creates and initializes the global instance. |bus| must not be null.
-  static void Initialize(dbus::Bus* bus);
-
-  // Creates and initializes the global instance for testing. |bus| must not be
-  // null.
-  static void InitializeForTesting(dbus::Bus* bus,
-                                   const base::FilePath& expected_dir,
-                                   ListenForTrialCallback callback);
-
-  // Creates and initializes a fake global instance.
-  static void InitializeFake();
-
-  // Destroys the global instance.
-  static void Shutdown();
-
-  // Returns the global instance which may be null if not initialized.
-  static FeaturedClient* Get();
-
-  FeaturedClient(const FeaturedClient&) = delete;
-  FeaturedClient& operator=(const FeaturedClient&) = delete;
-
-  // Asynchronously calls featured's `HandleSeedFetched`.
-  virtual void HandleSeedFetched(
-      const ::featured::SeedDetails& safe_seed,
-      base::OnceCallback<void(bool success)> callback) = 0;
-
-  // Returns true if the base component of |path| is of the format
-  // `TrialName,GroupName`. |active_group| will contain the trial name and group
-  // name specified by the filename. If the return value is false,
-  // |active_group| will not be modified.
-  //
-  // The platform-side logic that writes these files can be found in
-  // feature::PlatformFeatures::RecordActiveTrial() in chromiumos.
-  static bool ParseTrialFilename(const base::FilePath& path,
-                                 base::FieldTrial::ActiveGroup& active_group);
-
- protected:
-  // Initialize/Shutdown should be used instead.
-  FeaturedClient();
-  virtual ~FeaturedClient();
-
- private:
-  friend class FeaturedClientTest;
-};
-}  // namespace ash::featured
-
-#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_FEATURED_FEATURED_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/featured/featured_client_unittest.cc b/chromeos/ash/components/dbus/featured/featured_client_unittest.cc
deleted file mode 100644
index 6e8fe57..0000000
--- a/chromeos/ash/components/dbus/featured/featured_client_unittest.cc
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/ash/components/dbus/featured/featured_client.h"
-
-#include <map>
-#include <string>
-
-#include "base/barrier_closure.h"
-#include "base/check_op.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "base/strings/escape.h"
-#include "base/test/bind.h"
-#include "base/test/task_environment.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "chromeos/ash/components/dbus/featured/fake_featured_client.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#include "dbus/message.h"
-#include "dbus/mock_bus.h"
-#include "dbus/mock_object_proxy.h"
-#include "dbus/object_path.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/cros_system_api/constants/featured.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-
-namespace ash::featured {
-
-namespace {
-
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::IsEmpty;
-using ::testing::Return;
-
-std::string CreateEscapedFilename(const std::string& trial_name,
-                                  const std::string& group_name) {
-  std::string escaped_trial_name = base::EscapeAllExceptUnreserved(trial_name);
-  std::string escaped_group_name = base::EscapeAllExceptUnreserved(group_name);
-
-  return base::StrCat(
-      {escaped_trial_name, feature::kTrialGroupSeparator, escaped_group_name});
-}
-
-}  // namespace
-
-class FeaturedClientTest : public testing::Test {
- public:
-  FeaturedClientTest()
-      : bus_(base::MakeRefCounted<dbus::MockBus>(dbus::Bus::Options{})),
-        path_(dbus::ObjectPath(::featured::kFeaturedServicePath)),
-        proxy_(base::MakeRefCounted<dbus::MockObjectProxy>(
-            bus_.get(),
-            ::featured::kFeaturedServiceName,
-            path_)) {
-    // Makes sure `GetObjectProxy()` is called with the correct service name and
-    // path.
-    EXPECT_CALL(*bus_.get(),
-                GetObjectProxy(::featured::kFeaturedServiceName, path_))
-        .WillRepeatedly(Return(proxy_.get()));
-
-    EXPECT_TRUE(dir_.CreateUniqueTempDir());
-    active_trials_dir_ = dir_.GetPath().Append("active_trials");
-    EXPECT_TRUE(base::CreateDirectory(active_trials_dir_));
-  }
-
-  FeaturedClientTest(const FeaturedClientTest&) = delete;
-  FeaturedClientTest& operator=(const FeaturedClientTest&) = delete;
-
-  ~FeaturedClientTest() override = default;
-
- protected:
-  // Helper method to test FeaturedClient::ParseTrialFilename. Wrapping this
-  // logic simplifies the testing logic by allowing us to use a friend class
-  // instead of several FRIEND_TEST_ALL_PREFIXES.
-  //
-  // Callers must initialize FeaturedClient before calling this method.
-  bool ParseTrialFilename(const base::FilePath& path,
-                          base::FieldTrial::ActiveGroup& active_group) {
-    return FeaturedClient::ParseTrialFilename(path, active_group);
-  }
-
-  // Mock bus and proxy for simulating calls.
-  scoped_refptr<dbus::MockBus> bus_;
-  dbus::ObjectPath path_;
-  scoped_refptr<dbus::MockObjectProxy> proxy_;
-  base::ScopedTempDir dir_;
-  base::FilePath active_trials_dir_;
-  base::test::TaskEnvironment task_environment_;
-};
-
-TEST_F(FeaturedClientTest, InitializeSuccess) {
-  FeaturedClient::Initialize(bus_.get());
-
-  ASSERT_NE(FeaturedClient::Get(), nullptr);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, NotInitializedGet) {
-  ASSERT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, InitializeFakeSuccess) {
-  FeaturedClient::InitializeFake();
-
-  ASSERT_NE(FakeFeaturedClient::Get(), nullptr);
-
-  FakeFeaturedClient::Shutdown();
-
-  EXPECT_EQ(FakeFeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, NotInitializedFakeGet) {
-  ASSERT_EQ(FakeFeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, HandleSeedFetched_Success) {
-  EXPECT_CALL(*proxy_,
-              DoCallMethod(_, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, _))
-      .WillOnce(Invoke([](dbus::MethodCall* call, int timeout_ms,
-                          dbus::MockObjectProxy::ResponseCallback* callback) {
-        std::unique_ptr<dbus::Response> response =
-            dbus::Response::CreateEmpty();
-        std::move(*callback).Run(response.get());
-      }));
-
-  FeaturedClient::Initialize(bus_.get());
-  FeaturedClient* client = FeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  ::featured::SeedDetails safe_seed;
-
-  bool ran_callback = false;
-  client->HandleSeedFetched(
-      safe_seed, base::BindLambdaForTesting([&ran_callback](bool success) {
-        EXPECT_TRUE(success);
-        ran_callback = true;
-      }));
-  // Ensures the callback was executed.
-  EXPECT_TRUE(ran_callback);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-// Check that `HandleSeedFetched` runs the callback with a false success value
-// if the server (platform) returns an error responses.
-TEST_F(FeaturedClientTest, HandleSeedFetched_Failure_ErrorResponse) {
-  EXPECT_CALL(*proxy_,
-              DoCallMethod(_, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, _))
-      .WillOnce(Invoke([](dbus::MethodCall* call, int timeout_ms,
-                          dbus::MockObjectProxy::ResponseCallback* callback) {
-        // Not setting the serial causes a crash.
-        call->SetSerial(123);
-        std::unique_ptr<dbus::Response> response =
-            dbus::ErrorResponse::FromMethodCall(call, DBUS_ERROR_FAILED,
-                                                "test");
-        std::move(*callback).Run(response.get());
-      }));
-
-  FeaturedClient::Initialize(bus_.get());
-  FeaturedClient* client = FeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  ::featured::SeedDetails safe_seed;
-
-  bool ran_callback = false;
-  client->HandleSeedFetched(
-      safe_seed, base::BindLambdaForTesting([&ran_callback](bool success) {
-        EXPECT_FALSE(success);
-        ran_callback = true;
-      }));
-  // Ensures the callback was executed.
-  EXPECT_TRUE(ran_callback);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-// Check that `HandleSeedFetched` runs the callback with a false success value
-// if the method call is unsuccessful (response is a nullptr).
-TEST_F(FeaturedClientTest, HandleSeedFetched_Failure_NullResponse) {
-  EXPECT_CALL(*proxy_,
-              DoCallMethod(_, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, _))
-      .WillOnce(Invoke([](dbus::MethodCall* call, int timeout_ms,
-                          dbus::MockObjectProxy::ResponseCallback* callback) {
-        std::move(*callback).Run(nullptr);
-      }));
-
-  FeaturedClient::Initialize(bus_.get());
-  FeaturedClient* client = FeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  ::featured::SeedDetails safe_seed;
-
-  bool ran_callback = false;
-  client->HandleSeedFetched(
-      safe_seed, base::BindLambdaForTesting([&ran_callback](bool success) {
-        EXPECT_FALSE(success);
-        ran_callback = true;
-      }));
-  // Ensures the callback was executed.
-  EXPECT_TRUE(ran_callback);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-// Check that Fake runs `HandleSeedFetched` callback with a false success value
-// by default (no expected responses added).
-TEST_F(FeaturedClientTest, FakeHandleSeedFetched_InvokeFalseByDefault) {
-  FeaturedClient::InitializeFake();
-  FakeFeaturedClient* client = FakeFeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  ::featured::SeedDetails safe_seed;
-
-  bool ran_callback = false;
-  client->HandleSeedFetched(
-      safe_seed, base::BindLambdaForTesting([&ran_callback](bool success) {
-        EXPECT_FALSE(success);
-        ran_callback = true;
-      }));
-  // Ensures the callback was executed.
-  EXPECT_TRUE(ran_callback);
-  EXPECT_EQ(client->handle_seed_fetched_attempts(), 1);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FakeFeaturedClient::Get(), nullptr);
-}
-
-// Check that Fake runs `HandleSeedFetched` callback with value added by
-// `AddResponse`.
-TEST_F(FeaturedClientTest, FakeHandleSeedFetched_InvokeSuccessWhenSet) {
-  FeaturedClient::InitializeFake();
-  FakeFeaturedClient* client = FakeFeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  ::featured::SeedDetails safe_seed;
-  client->AddResponse(true);
-
-  bool ran_callback = false;
-  client->HandleSeedFetched(
-      safe_seed, base::BindLambdaForTesting([&ran_callback](bool success) {
-        EXPECT_TRUE(success);
-        ran_callback = true;
-      }));
-  // Ensures the callback was executed.
-  EXPECT_TRUE(ran_callback);
-  EXPECT_EQ(client->handle_seed_fetched_attempts(), 1);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FakeFeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, ReadTrialsActivatedBeforeChromeStartup_FilesExist) {
-  // Create active trial files before FeaturedClient is initialized.
-  EXPECT_TRUE(base::WriteFile(
-      active_trials_dir_.Append("test_trial_1,test_group_1"), ""));
-  EXPECT_TRUE(base::WriteFile(
-      active_trials_dir_.Append("test_trial_2,test_group_2"), ""));
-
-  std::map<std::string, std::string> expected;
-  expected.insert({"test_trial_1", "test_group_1"});
-  expected.insert({"test_trial_2", "test_group_2"});
-
-  base::RunLoop run_loop;
-  base::RepeatingClosure barrier_callback =
-      base::BarrierClosure(2, run_loop.QuitClosure());
-  std::map<std::string, std::string> actual;
-  FeaturedClient::InitializeForTesting(
-      bus_.get(), active_trials_dir_,
-      base::BindLambdaForTesting(
-          [&actual, &barrier_callback](const std::string& trial_name,
-                                       const std::string& group_name) {
-            actual.insert({trial_name, group_name});
-            barrier_callback.Run();
-          }));
-  run_loop.Run();
-  EXPECT_EQ(actual, expected);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest,
-       ReadTrialsActivatedBeforeChromeStartup_NoFilesExist) {
-  std::map<std::string, std::string> actual_trials;
-  FeaturedClient::InitializeForTesting(
-      bus_.get(), active_trials_dir_,
-      base::BindLambdaForTesting(
-          [&actual_trials](const std::string& trial_name,
-                           const std::string& group_name) {
-            actual_trials.insert({trial_name, group_name});
-          }));
-  EXPECT_THAT(actual_trials, IsEmpty());
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest, ParseTrialFileName_ImproperFilename_MissingGroup) {
-  FeaturedClient::InitializeForTesting(bus_.get(), active_trials_dir_,
-                                       base::DoNothing());
-  FeaturedClient* client = FeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  base::FieldTrial::ActiveGroup active_group;
-  base::FilePath trial_file = active_trials_dir_.Append("test_trial");
-
-  EXPECT_TRUE(base::WriteFile(trial_file, ""));
-  EXPECT_FALSE(ParseTrialFilename(trial_file, active_group));
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientTest,
-       ParseTrialFileName_ImproperFilename_MissingSeparator) {
-  FeaturedClient::InitializeForTesting(bus_.get(), active_trials_dir_,
-                                       base::DoNothing());
-  FeaturedClient* client = FeaturedClient::Get();
-
-  ASSERT_NE(client, nullptr);
-
-  base::FieldTrial::ActiveGroup active_group;
-  base::FilePath trial_file = active_trials_dir_.Append("test_trialtest_group");
-
-  EXPECT_TRUE(base::WriteFile(trial_file, ""));
-  EXPECT_FALSE(ParseTrialFilename(trial_file, active_group));
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-struct ParseProperFilenameTestParams {
-  std::string expected_trial_name;
-  std::string expected_group_name;
-};
-
-// Parameterized tests to check that properly formatted filenames with special
-// characters (eg. whitespace, /, *, etc) are parsed correctly.
-class FeaturedClientTrialFileTest
-    : public FeaturedClientTest,
-      public ::testing::WithParamInterface<ParseProperFilenameTestParams> {};
-
-TEST_P(FeaturedClientTrialFileTest, ParseProperFilename) {
-  FeaturedClient::InitializeForTesting(bus_.get(), active_trials_dir_,
-                                       base::DoNothing());
-  FeaturedClient* client = FeaturedClient::Get();
-  ASSERT_NE(client, nullptr);
-
-  const ParseProperFilenameTestParams test_case = GetParam();
-  base::FilePath trial_file = active_trials_dir_.Append(CreateEscapedFilename(
-      test_case.expected_trial_name, test_case.expected_group_name));
-  EXPECT_TRUE(base::WriteFile(trial_file, ""));
-
-  base::FieldTrial::ActiveGroup active_group;
-  EXPECT_TRUE(ParseTrialFilename(trial_file, active_group));
-  EXPECT_EQ(active_group.trial_name, test_case.expected_trial_name);
-  EXPECT_EQ(active_group.group_name, test_case.expected_group_name);
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    FeaturedClientTrialFileTestSuite,
-    FeaturedClientTrialFileTest,
-    testing::ValuesIn<ParseProperFilenameTestParams>({
-        {"test_trial", "test_group"}, {",", "test_group"}, {"/", "test_group"},
-        {"&", "test_group"},          {"!", "test_group"}, {"@", "test_group"},
-        {"#", "test_group"},          {"$", "test_group"}, {"%", "test_group"},
-        {"^", "test_group"},          {".", "test_group"}, {"~", "test_group"},
-        {"-", "test_group"},          {"`", "test_group"}, {"(", "test_group"},
-        {")", "test_group"},          {"`", "test_group"}, {"?", "test_group"},
-        {"+", "test_group"},          {"=", "test_group"}, {" ", "test_group"},
-    }));
-
-#if DCHECK_IS_ON()
-using FeaturedClientDeathTest = FeaturedClientTest;
-TEST_F(FeaturedClientDeathTest, InitializeFailure_NullBus) {
-  EXPECT_DEATH(FeaturedClient::Initialize(nullptr), "");
-}
-
-TEST_F(FeaturedClientDeathTest, DoubleInitialize) {
-  FeaturedClient::Initialize(bus_.get());
-
-  EXPECT_DEATH(FeaturedClient::Initialize(bus_.get()), "");
-
-  FeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-
-TEST_F(FeaturedClientDeathTest, DoubleInitializeFake) {
-  FeaturedClient::InitializeFake();
-
-  EXPECT_DEATH(FeaturedClient::InitializeFake(), "");
-
-  FakeFeaturedClient::Shutdown();
-
-  EXPECT_EQ(FeaturedClient::Get(), nullptr);
-}
-#endif  // DCHECK_IS_ON()
-}  // namespace ash::featured
diff --git a/clank b/clank
index e2d2617..dc223ca 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit e2d261757af9a7a32cecbc192644aad81a29f51f
+Subproject commit dc223ca45f40208adbfa36bb82127259ef6775bd
diff --git a/components/android_autofill/browser/BUILD.gn b/components/android_autofill/browser/BUILD.gn
index 65338cac..fca1c9a 100644
--- a/components/android_autofill/browser/BUILD.gn
+++ b/components/android_autofill/browser/BUILD.gn
@@ -138,6 +138,8 @@
     "android_form_event_logger.h",
     "autofill_provider.cc",
     "autofill_provider.h",
+    "autofill_type_util.cc",
+    "autofill_type_util.h",
   ]
   public_deps = [ "//components/autofill/core/browser" ]
   deps = [
diff --git a/components/android_autofill/browser/android_autofill_manager.cc b/components/android_autofill/browser/android_autofill_manager.cc
index cc4c83d..11313f0 100644
--- a/components/android_autofill/browser/android_autofill_manager.cc
+++ b/components/android_autofill/browser/android_autofill_manager.cc
@@ -14,7 +14,9 @@
 #include "base/notreached.h"
 #include "components/android_autofill/browser/android_form_event_logger.h"
 #include "components/android_autofill/browser/autofill_provider.h"
+#include "components/android_autofill/browser/autofill_type_util.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
 #include "components/autofill/core/common/unique_ids.h"
 #include "content/public/browser/render_frame_host.h"
@@ -215,10 +217,11 @@
     const FieldGlobalId& field_id) {
   FormStructure* form_structure = nullptr;
   AutofillField* autofill_field = nullptr;
-  return GetCachedFormAndField(form_id, field_id, &form_structure,
-                               &autofill_field)
-             ? autofill_field->Type().group()
-             : FieldTypeGroup::kNoGroup;
+  if (!GetCachedFormAndField(form_id, field_id, &form_structure,
+                             &autofill_field)) {
+    return FieldTypeGroup::kNoGroup;
+  }
+  return GroupTypeOfFieldType(GetMostRelevantFieldType(autofill_field->Type()));
 }
 
 void AndroidAutofillManager::FillOrPreviewForm(
diff --git a/components/android_autofill/browser/autofill_type_util.cc b/components/android_autofill/browser/autofill_type_util.cc
new file mode 100644
index 0000000..d48f424
--- /dev/null
+++ b/components/android_autofill/browser/autofill_type_util.cc
@@ -0,0 +1,31 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/android_autofill/browser/autofill_type_util.h"
+
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+
+FieldType GetMostRelevantFieldType(const AutofillType& type) {
+  if (FieldType field_type = type.GetPasswordManagerType();
+      field_type != UNKNOWN_TYPE) {
+    return field_type;
+  }
+  if (FieldType field_type = type.GetCreditCardType();
+      field_type != UNKNOWN_TYPE) {
+    return field_type;
+  }
+  if (FieldType field_type = type.GetAddressType();
+      field_type != UNKNOWN_TYPE) {
+    return field_type;
+  }
+  if (FieldTypeSet types = type.GetTypes(); !types.empty()) {
+    return *types.begin();
+  }
+  return UNKNOWN_TYPE;
+}
+
+}  // namespace autofill
diff --git a/components/android_autofill/browser/autofill_type_util.h b/components/android_autofill/browser/autofill_type_util.h
new file mode 100644
index 0000000..4a42611
--- /dev/null
+++ b/components/android_autofill/browser/autofill_type_util.h
@@ -0,0 +1,19 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_TYPE_UTIL_H_
+#define COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_TYPE_UTIL_H_
+
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+
+// Picks the most relevant of the FieldTypes encapsulated by the given
+// AutofillType to a single one: Password Manager > Credit > Addresses.
+FieldType GetMostRelevantFieldType(const AutofillType& type);
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_TYPE_UTIL_H_
diff --git a/components/android_autofill/browser/form_data_android.cc b/components/android_autofill/browser/form_data_android.cc
index 4bd0008b..2218f90e 100644
--- a/components/android_autofill/browser/form_data_android.cc
+++ b/components/android_autofill/browser/form_data_android.cc
@@ -11,6 +11,7 @@
 #include "base/containers/flat_map.h"
 #include "base/feature_list.h"
 #include "components/android_autofill/browser/android_autofill_bridge_factory.h"
+#include "components/android_autofill/browser/autofill_type_util.h"
 #include "components/android_autofill/browser/form_data_android_bridge.h"
 #include "components/android_autofill/browser/form_field_data_android.h"
 #include "components/autofill/core/browser/autofill_field.h"
@@ -113,11 +114,18 @@
         server_predictions.emplace_back(
             ToSafeFieldType(prediction.type(), NO_SERVER_DATA));
       }
+      std::string_view computed_type = [&] {
+        AutofillType autofill_type = autofill_field->ComputedType();
+        HtmlFieldType html_field_type = autofill_type.html_type();
+        if (html_field_type != HtmlFieldType::kUnspecified) {
+          return FieldTypeToStringView(html_field_type);
+        }
+        return FieldTypeToStringView(GetMostRelevantFieldType(autofill_type));
+      }();
       form_field_data_android->UpdateFieldTypes(
           FormFieldDataAndroid::FieldTypes(
               autofill_field->heuristic_type(), autofill_field->server_type(),
-              autofill_field->ComputedType().ToString(),
-              std::move(server_predictions)));
+              computed_type, std::move(server_predictions)));
     }
   }
 }
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
index cf22230c..e7d517bb 100644
--- a/components/autofill/core/browser/autofill_field.cc
+++ b/components/autofill/core/browser/autofill_field.cc
@@ -531,7 +531,7 @@
 
 void AutofillField::SetTypeTo(const AutofillType& type,
                               std::optional<AutofillPredictionSource> source) {
-  DCHECK(type.GetStorableType() != NO_SERVER_DATA);
+  DCHECK(!type.GetTypes().empty());
   overall_type_ = {type, source};
 }
 
@@ -716,16 +716,15 @@
 }
 
 bool AutofillField::IsFieldFillable() const {
-  FieldType field_type = Type().GetStorableType();
-  return IsFillableFieldType(field_type);
+  return std::ranges::any_of(Type().GetTypes(), IsFillableFieldType);
 }
 
 bool AutofillField::HasExpirationDateType() const {
-  static constexpr DenseSet kExpirationDateTypes = {
+  static constexpr FieldTypeSet kExpirationDateTypes = {
       CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR,
       CREDIT_CARD_EXP_4_DIGIT_YEAR, CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
       CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR};
-  return kExpirationDateTypes.contains(Type().GetStorableType());
+  return Type().GetTypes().contains_any(kExpirationDateTypes);
 }
 
 bool AutofillField::ShouldSuppressSuggestionsAndFillingByDefault() const {
@@ -778,7 +777,7 @@
 bool AutofillField::WasAutofilledWithFallback() const {
   return autofilled_type_ &&
          (!overall_type_ ||
-          autofilled_type_ != overall_type_->type.GetStorableType());
+          !overall_type_->type.GetTypes().contains(*autofilled_type_));
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h
index 5311711..d810170 100644
--- a/components/autofill/core/browser/autofill_field.h
+++ b/components/autofill/core/browser/autofill_field.h
@@ -216,13 +216,13 @@
     only_fill_when_focused_ = fill_when_focused;
   }
 
-  // Set the type of the field. This sets the value returned by |Type|.
+  // Set the type of the field. This sets the value returned by Type().
   // This function can be used to override the value that would be returned by
-  // |ComputedType|.
-  // As the |type| is expected to depend on |ComputedType|, the value will be
-  // reset to |ComputedType| if some internal value change (e.g. on call to
-  // (|set_heuristic_type|).
-  // |SetTypeTo| cannot be called with type.GetStorableType() == NO_SERVER_DATA.
+  // ComputedType().
+  // As the `type` is expected to depend on ComputedType(), the value will be
+  // reset to ComputedType() if some internal value change (e.g. on call to
+  // (set_heuristic_type()).
+  // SetTypeTo() must not be called with `type.GetTypes().empty()`.
   void SetTypeTo(const AutofillType& type,
                  std::optional<AutofillPredictionSource> source);
 
diff --git a/components/autofill/core/browser/autofill_field_unittest.cc b/components/autofill/core/browser/autofill_field_unittest.cc
index 8f77842..775c399 100644
--- a/components/autofill/core/browser/autofill_field_unittest.cc
+++ b/components/autofill/core/browser/autofill_field_unittest.cc
@@ -51,13 +51,13 @@
 
   field.set_server_predictions(
       {CreateFieldPrediction(PHONE_HOME_CITY_AND_NUMBER)});
-  EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(PHONE_HOME_CITY_AND_NUMBER));
   EXPECT_EQ(field.PredictionSource(),
             AutofillPredictionSource::kServerCrowdsourcing);
 
   // Overrides to another number format.
   field.set_server_predictions({CreateFieldPrediction(PHONE_HOME_NUMBER)});
-  EXPECT_EQ(PHONE_HOME_NUMBER, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(PHONE_HOME_NUMBER));
   EXPECT_EQ(field.PredictionSource(),
             AutofillPredictionSource::kServerCrowdsourcing);
 
@@ -65,7 +65,7 @@
   field.SetHtmlType(HtmlFieldType::kTelNational, HtmlFieldMode::kNone);
   field.set_server_predictions(
       {CreateFieldPrediction(PHONE_HOME_WHOLE_NUMBER)});
-  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(PHONE_HOME_WHOLE_NUMBER));
   EXPECT_EQ(field.PredictionSource(),
             AutofillPredictionSource::kServerCrowdsourcing);
 
@@ -74,21 +74,21 @@
   field.SetHtmlType(HtmlFieldType::kTelNational, HtmlFieldMode::kNone);
   field.set_server_predictions(
       {CreateFieldPrediction(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR)});
-  EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(PHONE_HOME_CITY_AND_NUMBER));
   EXPECT_EQ(field.PredictionSource(), AutofillPredictionSource::kAutocomplete);
 
   // If html type not specified, we still use server prediction.
   field.SetHtmlType(HtmlFieldType::kUnspecified, HtmlFieldMode::kNone);
   field.set_server_predictions(
       {CreateFieldPrediction(PHONE_HOME_CITY_AND_NUMBER)});
-  EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(PHONE_HOME_CITY_AND_NUMBER));
   EXPECT_EQ(field.PredictionSource(),
             AutofillPredictionSource::kServerCrowdsourcing);
 }
 
 TEST_F(AutofillFieldTest, IsFieldFillable) {
   AutofillField field;
-  ASSERT_EQ(UNKNOWN_TYPE, field.Type().GetStorableType());
+  ASSERT_THAT(field.Type().GetTypes(), ElementsAre(UNKNOWN_TYPE));
 
   // Type is unknown.
   EXPECT_FALSE(field.IsFieldFillable());
@@ -119,18 +119,18 @@
       features::kAutofillEnableEmailOrLoyaltyCardsFilling);
 
   AutofillField field;
-  EXPECT_EQ(UNKNOWN_TYPE, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(UNKNOWN_TYPE));
 
   // Both types set.
   field.set_heuristic_type(GetActiveHeuristicSource(), NAME_FIRST);
   field.set_server_predictions({CreateFieldPrediction(LOYALTY_MEMBERSHIP_ID)});
 
-  EXPECT_EQ(NAME_FIRST, field.Type().GetStorableType());
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(NAME_FIRST));
 }
 
 TEST_F(AutofillFieldTest, NoPredictions) {
   AutofillField field;
-  EXPECT_EQ(field.Type().GetStorableType(), UNKNOWN_TYPE);
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(UNKNOWN_TYPE));
   EXPECT_EQ(field.PredictionSource(), std::nullopt);
 }
 
@@ -257,7 +257,8 @@
   field.set_server_predictions({CreateFieldPrediction(test_case.server_type)});
   field.set_heuristic_type(GetActiveHeuristicSource(),
                            test_case.heuristic_type);
-  EXPECT_EQ(field.ComputedType().GetStorableType(), test_case.expected_result);
+  EXPECT_THAT(field.ComputedType().GetTypes(),
+              ElementsAre(test_case.expected_result));
   EXPECT_EQ(field.PredictionSource(), test_case.expected_source);
 }
 
@@ -314,7 +315,7 @@
   field.SetHtmlType(HtmlFieldType::kUnrecognized, HtmlFieldMode::kNone);
 
   // Expect that the predicted type wins over ac=unrecognized.
-  EXPECT_EQ(field.Type().GetStorableType(), test.predicted_type);
+  EXPECT_THAT(field.Type().GetTypes(), ElementsAre(test.predicted_type));
   EXPECT_EQ(field.ShouldSuppressSuggestionsAndFillingByDefault(),
             test.expect_should_suppress_suggestions_and_filling);
   EXPECT_EQ(field.PredictionSource(), test.expected_source);
@@ -375,7 +376,8 @@
   field.set_server_predictions({CreateFieldPrediction(test_case.server_type)});
   field.set_heuristic_type(GetActiveHeuristicSource(),
                            test_case.heuristic_type);
-  EXPECT_EQ(field.ComputedType().GetStorableType(), test_case.expected_result)
+  EXPECT_THAT(field.ComputedType().GetTypes(),
+              ElementsAre(test_case.expected_result))
       << "html_field_type: " << test_case.html_field_type
       << ", server_type: " << test_case.server_type
       << ", heuristic_type: " << test_case.heuristic_type
@@ -711,7 +713,8 @@
                            test_case.autofill_heuristic_type);
   field.set_heuristic_type(HeuristicSource::kPasswordManagerMachineLearning,
                            test_case.password_manager_predicted_type);
-  EXPECT_EQ(field.ComputedType().GetStorableType(), test_case.expected_result);
+  EXPECT_THAT(field.ComputedType().GetTypes(),
+              ElementsAre(test_case.expected_result));
   EXPECT_EQ(field.PredictionSource(), test_case.expected_source);
 }
 
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
index 3610547..9a7fc45 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -460,8 +460,8 @@
     // TODO(crbug.com/40286837): Understand and document why the type is
     // relevant.
     if (!field->initial_value().empty() &&
-        ((field->Type().GetStorableType() != NO_SERVER_DATA &&
-          field->Type().GetStorableType() != UNKNOWN_TYPE) ||
+        (!field->Type().GetTypes().contains_any(
+             {NO_SERVER_DATA, UNKNOWN_TYPE}) ||
          !field->possible_types().empty())) {
       added_field->set_initial_value_changed(field->initial_value() !=
                                              field->value());
@@ -776,7 +776,7 @@
 void MaybeMergeServerPredictions(
     std::vector<FieldPrediction>& server_predictions) {
   const auto server_types =
-      DenseSet<FieldType>(server_predictions, [](const FieldPrediction& pred) {
+      FieldTypeSet(server_predictions, [](const FieldPrediction& pred) {
         return ToSafeFieldType(pred.type(), UNKNOWN_TYPE);
       });
 
@@ -1027,7 +1027,7 @@
           field_suggestion->predictions().end()};
       MaybeMergeServerPredictions(server_predictions);
       field->set_server_predictions(std::move(server_predictions));
-      if (heuristic_type != field->Type().GetStorableType()) {
+      if (!field->Type().GetTypes().contains(heuristic_type)) {
         query_response_overrode_heuristics = true;
       }
       if (field_suggestion->has_password_requirements()) {
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
index 1905a403..70f64c2 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
@@ -2383,18 +2383,18 @@
   EXPECT_FALSE(form.field(1)->server_type_prediction_is_override());
 
   // Validate that the server prediction won for the first field.
-  EXPECT_EQ(form.field(0)->Type().GetStorableType(), NAME_FIRST);
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), NAME_FULL);
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST));
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(NAME_FULL));
 
   // Validate that the server override cannot be altered.
   form.field(0)->SetTypeTo(AutofillType(NAME_FULL),
                            AutofillPredictionSource::kHeuristics);
-  EXPECT_EQ(form.field(0)->Type().GetStorableType(), NAME_FIRST);
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST));
 
   // Validate that that the non-override can be altered.
   form.field(1)->SetTypeTo(AutofillType(NAME_FIRST),
                            AutofillPredictionSource::kHeuristics);
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), NAME_FIRST);
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(NAME_FIRST));
 }
 
 // Test the heuristic prediction for NAME_LAST_SECOND overrides server
@@ -2439,9 +2439,9 @@
   EXPECT_EQ(NAME_LAST, form.field(2)->server_type());
 
   // Validate that the heuristic prediction wins for the two last name fields.
-  EXPECT_EQ(form.field(0)->Type().GetStorableType(), NAME_FIRST);
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), NAME_LAST_FIRST);
-  EXPECT_EQ(form.field(2)->Type().GetStorableType(), NAME_LAST_SECOND);
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST));
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(NAME_LAST_FIRST));
+  EXPECT_THAT(form.field(2)->Type().GetTypes(), ElementsAre(NAME_LAST_SECOND));
 }
 
 // Test the heuristic prediction for ADDRESS_HOME_STREET_NAME and
@@ -2489,8 +2489,10 @@
 
   // Validate that the heuristic prediction wins for the street name and house
   // number.
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), ADDRESS_HOME_STREET_NAME);
-  EXPECT_EQ(form.field(2)->Type().GetStorableType(), ADDRESS_HOME_HOUSE_NUMBER);
+  EXPECT_THAT(form.field(1)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_STREET_NAME));
+  EXPECT_THAT(form.field(2)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_HOUSE_NUMBER));
 }
 
 // Tests that a joined prediction for email or loyalty card fields is generated
@@ -2531,9 +2533,9 @@
   EXPECT_EQ(form.field(0)->server_type(), EMAIL_OR_LOYALTY_MEMBERSHIP_ID);
 
   // Validate that the server prediction wins for email or loyalty cards.
-  EXPECT_EQ(EMAIL_OR_LOYALTY_MEMBERSHIP_ID,
-            form.field(0)->Type().GetStorableType());
-  EXPECT_EQ(PASSWORD, form.field(1)->Type().GetStorableType());
+  EXPECT_THAT(form.field(0)->Type().GetTypes(),
+              ElementsAre(EMAIL_OR_LOYALTY_MEMBERSHIP_ID));
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(PASSWORD));
 }
 
 // Tests that a server joined prediction is not generated for email or loyalty
@@ -2574,8 +2576,8 @@
   EXPECT_EQ(form.field(0)->server_type(), EMAIL_ADDRESS);
 
   // Validate that the server prediction wins for email or loyalty cards.
-  EXPECT_EQ(form.field(0)->Type().GetStorableType(), EMAIL_ADDRESS);
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), PASSWORD);
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(EMAIL_ADDRESS));
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(PASSWORD));
 }
 
 // Tests proper resolution heuristic, server and html field types when the
@@ -2617,19 +2619,19 @@
   EXPECT_EQ(NAME_FIRST, form.field(0)->heuristic_type());
   EXPECT_EQ(NAME_FIRST, form.field(0)->server_type());
   EXPECT_EQ(HtmlFieldType::kUnspecified, form.field(0)->html_type());
-  EXPECT_EQ(NAME_FIRST, form.field(0)->Type().GetStorableType());
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST));
 
   // Validate field 1.
   EXPECT_EQ(NAME_LAST, form.field(1)->heuristic_type());
   EXPECT_EQ(NAME_LAST, form.field(1)->server_type());
   EXPECT_EQ(HtmlFieldType::kUnspecified, form.field(1)->html_type());
-  EXPECT_EQ(NAME_LAST, form.field(1)->Type().GetStorableType());
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(NAME_LAST));
 
   // Validate field 2. Note: HtmlFieldType::kAddressLevel2 -> City
   EXPECT_EQ(EMAIL_ADDRESS, form.field(2)->heuristic_type());
   EXPECT_EQ(ADDRESS_HOME_LINE1, form.field(2)->server_type());
   EXPECT_EQ(HtmlFieldType::kAddressLevel2, form.field(2)->html_type());
-  EXPECT_EQ(ADDRESS_HOME_CITY, form.field(2)->Type().GetStorableType());
+  EXPECT_THAT(form.field(2)->Type().GetTypes(), ElementsAre(ADDRESS_HOME_CITY));
 
   // Also check the extreme case of an empty form.
   FormStructure empty_form{FormData()};
@@ -2678,19 +2680,19 @@
   EXPECT_EQ(form.field(0)->heuristic_type(), NAME_FIRST);
   EXPECT_EQ(form.field(0)->server_type(), UNKNOWN_TYPE);
   EXPECT_EQ(form.field(0)->html_type(), HtmlFieldType::kUnspecified);
-  EXPECT_EQ(form.field(0)->Type().GetStorableType(), UNKNOWN_TYPE);
+  EXPECT_THAT(form.field(0)->Type().GetTypes(), ElementsAre(UNKNOWN_TYPE));
 
   // Validate field 1.
   EXPECT_EQ(form.field(1)->heuristic_type(), NAME_LAST);
   EXPECT_EQ(form.field(1)->server_type(), NO_SERVER_DATA);
   EXPECT_EQ(form.field(1)->html_type(), HtmlFieldType::kUnspecified);
-  EXPECT_EQ(form.field(1)->Type().GetStorableType(), NAME_LAST);
+  EXPECT_THAT(form.field(1)->Type().GetTypes(), ElementsAre(NAME_LAST));
 
   // Validate field 2. Note: HtmlFieldType::kAddressLevel2 -> City
   EXPECT_EQ(form.field(2)->heuristic_type(), EMAIL_ADDRESS);
   EXPECT_EQ(form.field(2)->server_type(), ADDRESS_HOME_LINE1);
   EXPECT_EQ(form.field(2)->html_type(), HtmlFieldType::kAddressLevel2);
-  EXPECT_EQ(form.field(2)->Type().GetStorableType(), ADDRESS_HOME_CITY);
+  EXPECT_THAT(form.field(2)->Type().GetTypes(), ElementsAre(ADDRESS_HOME_CITY));
 }
 
 struct PredictionPrecedenceTestCase {
@@ -2985,7 +2987,7 @@
   auto* form_suggestion = api_response.add_form_suggestions();
   AddFieldPredictionsToForm(form.fields()[0],
                             {CreateFieldPrediction(NAME_FULL),
-                             CreateFieldPrediction(PHONE_HOME_COUNTRY_CODE)},
+                             CreateFieldPrediction(CREDIT_CARD_NAME_FULL)},
                             form_suggestion);
   AddFieldPredictionToForm(form.fields()[1], ADDRESS_HOME_LINE1,
                            form_suggestion);
@@ -3009,7 +3011,7 @@
   EXPECT_EQ(forms[0]->field(0)->server_type(), NAME_FULL);
   EXPECT_THAT(forms[0]->field(0)->server_predictions(),
               ElementsAre(EqualsPrediction(NAME_FULL),
-                          EqualsPrediction(PHONE_HOME_COUNTRY_CODE)));
+                          EqualsPrediction(CREDIT_CARD_NAME_FULL)));
 
   EXPECT_EQ(forms[0]->field(1)->server_type(), ADDRESS_HOME_LINE1);
   EXPECT_THAT(forms[0]->field(1)->server_predictions(),
@@ -3568,10 +3570,11 @@
   ASSERT_GE(forms[0]->field_count(), 2U);
   // Server type is parsed from the response and is the end result type.
   EXPECT_EQ(forms[0]->field(0)->server_type(), EMAIL_ADDRESS);
-  EXPECT_EQ(forms[0]->field(0)->Type().GetStorableType(), EMAIL_ADDRESS);
+  EXPECT_THAT(forms[0]->field(0)->Type().GetTypes(),
+              ElementsAre(EMAIL_ADDRESS));
   EXPECT_EQ(forms[0]->field(1)->server_type(), ACCOUNT_CREATION_PASSWORD);
-  EXPECT_EQ(forms[0]->field(1)->Type().GetStorableType(),
-            ACCOUNT_CREATION_PASSWORD);
+  EXPECT_THAT(forms[0]->field(1)->Type().GetTypes(),
+              ElementsAre(ACCOUNT_CREATION_PASSWORD));
 }
 
 // Tests that, when the flag is off, we will not set the predicted type to
@@ -3617,11 +3620,13 @@
   ASSERT_EQ(4U, forms[0]->field_count());
 
   // Only NAME_LAST should be affected by the flag.
-  EXPECT_EQ(forms[0]->field(1)->Type().GetStorableType(), NAME_LAST);
+  EXPECT_THAT(forms[0]->field(1)->Type().GetTypes(), ElementsAre(NAME_LAST));
 
-  EXPECT_EQ(forms[0]->field(0)->Type().GetStorableType(), NAME_FIRST);
-  EXPECT_EQ(forms[0]->field(2)->Type().GetStorableType(), ADDRESS_HOME_LINE1);
-  EXPECT_EQ(forms[0]->field(3)->Type().GetStorableType(), ADDRESS_HOME_COUNTRY);
+  EXPECT_THAT(forms[0]->field(0)->Type().GetTypes(), ElementsAre(NAME_FIRST));
+  EXPECT_THAT(forms[0]->field(2)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_LINE1));
+  EXPECT_THAT(forms[0]->field(3)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_COUNTRY));
 }
 
 // Tests that we never overwrite the CVC heuristic-predicted type, even if there
@@ -3664,15 +3669,16 @@
 
   ASSERT_EQ(1U, forms.size());
   ASSERT_EQ(4U, forms[0]->field_count());
-  EXPECT_EQ(forms[0]->field(0)->Type().GetStorableType(),
-            CREDIT_CARD_NAME_FULL);
-  EXPECT_EQ(forms[0]->field(1)->Type().GetStorableType(), CREDIT_CARD_NUMBER);
-  EXPECT_EQ(forms[0]->field(2)->Type().GetStorableType(),
-            CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
+  EXPECT_THAT(forms[0]->field(0)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NAME_FULL));
+  EXPECT_THAT(forms[0]->field(1)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NUMBER));
+  EXPECT_THAT(forms[0]->field(2)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR));
 
   // Regardless of the flag, the CVC field should not have been overwritten.
-  EXPECT_EQ(forms[0]->field(3)->Type().GetStorableType(),
-            CREDIT_CARD_VERIFICATION_CODE);
+  EXPECT_THAT(forms[0]->field(3)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_VERIFICATION_CODE));
 }
 
 // Tests that we never overwrite the CVC heuristic-predicted type, even if there
@@ -3721,13 +3727,14 @@
 
   // Regardless of the flag, the fields should not have been overwritten,
   // including the CVC field.
-  EXPECT_EQ(forms[0]->field(0)->Type().GetStorableType(),
-            CREDIT_CARD_NAME_FULL);
-  EXPECT_EQ(forms[0]->field(1)->Type().GetStorableType(), CREDIT_CARD_NUMBER);
-  EXPECT_EQ(forms[0]->field(2)->Type().GetStorableType(),
-            CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
-  EXPECT_EQ(forms[0]->field(3)->Type().GetStorableType(),
-            CREDIT_CARD_VERIFICATION_CODE);
+  EXPECT_THAT(forms[0]->field(0)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NAME_FULL));
+  EXPECT_THAT(forms[0]->field(1)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NUMBER));
+  EXPECT_THAT(forms[0]->field(2)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR));
+  EXPECT_THAT(forms[0]->field(3)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_VERIFICATION_CODE));
 }
 
 // When two fields have the same signature and the server response has multiple
diff --git a/components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.cc b/components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.cc
index 22fdc14..e187747 100644
--- a/components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.cc
+++ b/components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.cc
@@ -16,10 +16,10 @@
 
 // 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().GetStorableType() == CREDIT_CARD_NAME_FULL ||
-         field.Type().GetStorableType() == CREDIT_CARD_NAME_FIRST ||
-         field.Type().GetStorableType() == CREDIT_CARD_NAME_LAST;
+  return field.Type().GetGroups().contains(FieldTypeGroup::kName) ||
+         field.Type().GetTypes().contains_any({CREDIT_CARD_NAME_FULL,
+                                               CREDIT_CARD_NAME_FIRST,
+                                               CREDIT_CARD_NAME_LAST});
 }
 
 // Selects the probable name types for the possible field types of the `field`.
@@ -99,7 +99,7 @@
     if (!IsNameType(prev_field)) {
       has_found_previous_type = true;
       is_previous_credit_card =
-          prev_field.Type().group() == FieldTypeGroup::kCreditCard;
+          prev_field.Type().GetGroups().contains(FieldTypeGroup::kCreditCard);
     }
   }
 
@@ -112,7 +112,7 @@
     if (!IsNameType(next_field)) {
       has_found_next_type = true;
       is_next_credit_card =
-          next_field.Type().group() == FieldTypeGroup::kCreditCard;
+          next_field.Type().GetGroups().contains(FieldTypeGroup::kCreditCard);
     }
   }
 
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
index c1e2505..f947ecc 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
@@ -361,7 +361,7 @@
     return std::ranges::count_if(
         submitted_form->fields(),
         [=](const std::unique_ptr<AutofillField>& field) {
-          return FieldTypeGroupToFormType(field->Type().group()) == type;
+          return field->Type().GetFormTypes().contains(type);
         });
   };
 
diff --git a/components/autofill/core/browser/data_quality/autofill_data_util.cc b/components/autofill/core/browser/data_quality/autofill_data_util.cc
index 12163f0..83b42fb 100644
--- a/components/autofill/core/browser/data_quality/autofill_data_util.cc
+++ b/components/autofill/core/browser/data_quality/autofill_data_util.cc
@@ -287,8 +287,9 @@
 uint32_t DetermineGroups(const FormStructure& form) {
   uint32_t group_bitmask = 0;
   for (const auto& field : form) {
-    FieldType type = field->Type().GetStorableType();
-    AddGroupToBitmask(&group_bitmask, type);
+    for (FieldType type : field->Type().GetTypes()) {
+      AddGroupToBitmask(&group_bitmask, type);
+    }
   }
   return group_bitmask;
 }
diff --git a/components/autofill/core/browser/field_type_utils.cc b/components/autofill/core/browser/field_type_utils.cc
index 40ad78c..c264fe9 100644
--- a/components/autofill/core/browser/field_type_utils.cc
+++ b/components/autofill/core/browser/field_type_utils.cc
@@ -27,7 +27,7 @@
 }
 
 bool TypeOfFieldIsPossibleType(const AutofillField& field) {
-  return field.possible_types().contains(field.Type().GetStorableType());
+  return field.possible_types().contains_any(field.Type().GetTypes());
 }
 
 size_t AddressLineIndex(FieldType type) {
diff --git a/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util.cc b/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util.cc
index 4803d5d..f467ab7 100644
--- a/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util.cc
+++ b/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util.cc
@@ -84,7 +84,8 @@
     const AttributeInstance& attribute,
     const AutofillField& field,
     const std::string& app_locale) {
-  FieldType type = field.Type().GetStorableType();
+  FieldType type =
+      field.Type().GetAutofillAiType(attribute.type().entity_type());
   if (!IsDateFieldType(type)) {
     return std::nullopt;
   }
@@ -92,8 +93,7 @@
   auto get_part = [&](const std::u16string& format_string, uint32_t min = 0,
                       uint32_t max =
                           std::numeric_limits<uint32_t>::max()) -> uint32_t {
-    std::u16string s = attribute.GetInfo(field.Type().GetStorableType(),
-                                         app_locale, format_string);
+    std::u16string s = attribute.GetInfo(type, app_locale, format_string);
     unsigned int i = 0;
     return base::StringToUint(s, &i) && min <= i && i <= max
                ? i
@@ -118,7 +118,8 @@
 std::u16string GetValueForInput(const AttributeInstance& attribute,
                                 const AutofillField& field,
                                 const std::string& app_locale) {
-  FieldType type = field.Type().GetStorableType();
+  FieldType type =
+      field.Type().GetAutofillAiType(attribute.type().entity_type());
   // TODO(crbug.com/389625753): Investigate whether only passing the
   // field type is the right choice here. This would for example
   // fail the fill a PASSPORT_NUMBER field that gets a
@@ -126,7 +127,7 @@
   // prediction logic.
   std::u16string value =
       attribute.GetInfo(type, app_locale, field.format_string());
-  switch (field.Type().GetStorableType()) {
+  switch (type) {
     case DRIVERS_LICENSE_REGION:
     case VEHICLE_PLATE_STATE:
       // TODO(crbug.com/389625753): Support countries other than the US.
@@ -149,7 +150,8 @@
                                  const AutofillField& field,
                                  const std::string& app_locale,
                                  AddressNormalizer* address_normalizer) {
-  FieldType type = field.Type().GetStorableType();
+  FieldType type =
+      field.Type().GetAutofillAiType(attribute.type().entity_type());
   if (IsDateFieldType(type)) {
     return GetValueForDateSelect(attribute, field, app_locale).value_or(u"");
   }
diff --git a/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util_unittest.cc b/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util_unittest.cc
index 8d790a4..a48fa64 100644
--- a/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util_unittest.cc
+++ b/components/autofill/core/browser/filling/autofill_ai/field_filling_entity_util_unittest.cc
@@ -78,8 +78,8 @@
   // For a name field fake that there are other fields that dynamically
   // propagate to the name field.
   for (AutofillFieldWithAttributeType& field_and_type : fields_and_types) {
-    if (GroupTypeOfFieldType(field_and_type.field->Type().GetStorableType()) ==
-            FieldTypeGroup::kName &&
+    if (field_and_type.field->Type().GetGroups().contains(
+            FieldTypeGroup::kName) &&
         base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) {
       auto attribute_type = [&entity]() -> std::optional<AttributeType> {
         switch (entity.type().name()) {
diff --git a/components/autofill/core/browser/filling/form_filler.cc b/components/autofill/core/browser/filling/form_filler.cc
index 5e1da635..7fda1fe 100644
--- a/components/autofill/core/browser/filling/form_filler.cc
+++ b/components/autofill/core/browser/filling/form_filler.cc
@@ -456,9 +456,11 @@
   return originally_filled_.has_value();
 }
 
-bool FormFiller::RefillOptions::may_refill(FieldType field_type) const {
+bool FormFiller::RefillOptions::may_refill(
+    const FieldTypeSet& field_types) const {
   CHECK(is_refill());
-  return originally_filled_->contains(GroupTypeOfFieldType(field_type));
+  return originally_filled_->contains_all(
+      DenseSet<FieldTypeGroup>(field_types, &GroupTypeOfFieldType));
 }
 
 DenseSet<FieldFillingSkipReason> FormFiller::GetFillingSkipReasonsForField(
@@ -526,26 +528,29 @@
                                    refill_options.is_refill()),
          FieldFillingSkipReason::kAlreadyAutofilled);
 
-  FieldType field_type = autofill_field.Type().GetStorableType();
+  AutofillType autofill_type = autofill_field.Type();
+  FieldTypeSet field_types = autofill_type.GetTypes();
   std::optional<FieldType> autofill_ai_type =
       autofill_field.GetAutofillAiServerTypePredictions();
 
   // On a refill, only fill fields from type groups that were present during
   // the initial fill.
-  add_if(refill_options.is_refill() && !refill_options.may_refill(field_type),
+  add_if(refill_options.is_refill() && !refill_options.may_refill(field_types),
          FieldFillingSkipReason::kRefillNotInInitialFill);
 
   // A field with a specific type is only allowed to be filled a limited
   // number of times given by |TypeValueFormFillingLimit(field_type)|.
-  add_if(++type_count[field_type] > TypeValueFormFillingLimit(field_type),
-         FieldFillingSkipReason::kFillingLimitReachedType);
+  for (FieldType field_type : field_types) {
+    add_if(++type_count[field_type] > TypeValueFormFillingLimit(field_type),
+           FieldFillingSkipReason::kFillingLimitReachedType);
+  }
 
   std::optional<FieldTypeSet> supported_types =
       GetFieldTypesToFillFromFillingProduct(filling_product);
   // This ensures that a filling product only operates on fields of supported
   // types.
   add_if(
-      supported_types && !supported_types->contains(field_type) &&
+      supported_types && !supported_types->contains_any(field_types) &&
           (!autofill_ai_type || !supported_types->contains(*autofill_ai_type)),
       FieldFillingSkipReason::kFieldTypeUnrelated);
 
@@ -849,8 +854,8 @@
     }
 
     if (could_attempt_refill) {
-      refill_context->type_groups_originally_filled.insert(
-          autofill_field.Type().group());
+      refill_context->type_groups_originally_filled.insert_all(
+          autofill_field.Type().GetGroups());
     }
     std::string failure_to_fill;  // Reason for failing to fill.
     const std::map<FieldGlobalId, std::u16string>& forced_fill_values =
@@ -1156,11 +1161,30 @@
                 CHECK_DEREF(entity_and_fields_and_types.first);
             const std::vector<AutofillFieldWithAttributeType>& fields =
                 entity_and_fields_and_types.second;
+            AutofillType autofill_type = autofill_field.Type();
+            FieldType field_type =
+                autofill_type.GetAutofillAiType(entity.type());
+            if (field_type == UNKNOWN_TYPE &&
+                !autofill_type.GetTypes().empty()) {
+              // This is currently reachable if a classical prediction is
+              // followed by an Autofill AI prediction, e.g.,
+              // ADDRESS_HOME_COUNTRY followed by PASSPORT_ISSUING_COUNTRY.
+              //
+              // Then AutofillField::Type() only contains the classical
+              // prediction but Autofill AI nonetheless may fill the field
+              // because it obtains the Autofill AI type in
+              // AutofillField::GetAutofillAiServerTypePredictions()
+              //
+              // TODO(crbug.com/432645177): Remove once we've removed
+              // AutofillField::GetAutofillAiServerTypePredictions() (and
+              // instead populate AutofillType with Autofill AI types).
+              field_type = *autofill_type.GetTypes().begin();
+            }
             return {GetFillValueForEntity(
                         entity, fields, autofill_field, action_persistence,
                         manager_->client().GetAppLocale(),
                         manager_->client().GetAddressNormalizer()),
-                    autofill_field.Type().GetStorableType()};
+                    field_type};
           },
           [&](const VerifiedProfile* profile)
               -> std::pair<std::u16string, FieldType> {
diff --git a/components/autofill/core/browser/filling/form_filler.h b/components/autofill/core/browser/filling/form_filler.h
index 867b27f..d96f6a8 100644
--- a/components/autofill/core/browser/filling/form_filler.h
+++ b/components/autofill/core/browser/filling/form_filler.h
@@ -85,7 +85,7 @@
     static RefillOptions Refill(DenseSet<FieldTypeGroup> originally_filled);
 
     bool is_refill() const;
-    bool may_refill(FieldType field_type) const;
+    bool may_refill(const FieldTypeSet& field_type) const;
 
    private:
     RefillOptions();
@@ -218,9 +218,10 @@
 
   // Fills `field_data` and modifies `autofill_field` given all other states.
   // Returns the FieldType of the value that was filled, or std::nullopt if no
-  // value was filled. The return value is independent of whether the field was
-  // filled or autofilled before. When `allow_suggestion_swapping` is true, the
-  // method still returns the FieldType if the `autofill_field` is emptied.
+  // value was filled. If the FieldType is not known, returns UNKNOWN_TYPE. The
+  // return value is independent of whether the field was filled or autofilled
+  // before. When `allow_suggestion_swapping` is true, the method still returns
+  // the FieldType if the `autofill_field` is emptied.
   // TODO(crbug.com/40227071): Cleanup API and logic.
   std::optional<FieldType> FillField(
       AutofillField& autofill_field,
diff --git a/components/autofill/core/browser/filling/form_filler_unittest.cc b/components/autofill/core/browser/filling/form_filler_unittest.cc
index e699ece2..f5e2d2d 100644
--- a/components/autofill/core/browser/filling/form_filler_unittest.cc
+++ b/components/autofill/core/browser/filling/form_filler_unittest.cc
@@ -12,6 +12,7 @@
 
 #include "base/containers/flat_map.h"
 #include "base/containers/span.h"
+#include "base/containers/to_vector.h"
 #include "base/feature_list.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
@@ -54,13 +55,14 @@
 namespace {
 
 using ::testing::AtLeast;
+using ::testing::Contains;
 using ::testing::DoAll;
 using ::testing::Each;
 using ::testing::Eq;
-using ::testing::Field;
 using ::testing::NiceMock;
 using ::testing::Not;
 using ::testing::Optional;
+using ::testing::Property;
 using ::testing::Return;
 using ::testing::SaveArg;
 
@@ -113,13 +115,17 @@
               (override));
 };
 
-MATCHER_P(HasValue, value, "") {
-  return arg.value() == value;
+auto HasValue(std::u16string value) {
+  return Property("FormFieldData::value", &FormFieldData::value,
+                  std::move(value));
 }
 
 // Takes a FormFieldData argument.
-MATCHER_P(AutofilledWith, value, "") {
-  return arg.is_autofilled() && arg.value() == value;
+auto AutofilledWith(std::u16string value) {
+  return AllOf(Property("FormFieldData::is_autofilled",
+                        &FormFieldData::is_autofilled, true),
+               Property("FormFieldData::value", &FormFieldData::value,
+                        std::move(value)));
 }
 
 // Takes an AutofillField argument.
@@ -815,7 +821,8 @@
   FormStructure* form_structure = GetFormStructure(form);
   form_structure->field(1)->set_heuristic_type(GetActiveHeuristicSource(),
                                                NAME_MIDDLE);
-  ASSERT_EQ(form_structure->field(1)->Type().GetStorableType(), NAME_MIDDLE);
+  ASSERT_THAT(form_structure->field(1)->Type().GetTypes(),
+              Contains(NAME_MIDDLE));
 
   AutofillProfile profile = test::GetFullProfile();
   std::vector<FormFieldData> filled_fields =
@@ -1542,6 +1549,8 @@
 }
 
 TEST_F(FormFillerTest, FillPassportEntity) {
+  base::test::ScopedFeatureList feature_list(
+      features::kAutofillAiWithDataSchema);
   FormData form = test::GetFormData({.fields = {
                                          // Passport number:
                                          {.role = UNKNOWN_TYPE},
@@ -1563,6 +1572,13 @@
   auto set_server_type = [&](size_t field_index, auto... types) {
     form_structure->fields()[field_index]->set_server_predictions(
         {test::CreateFieldPrediction(types)...});
+    std::vector<FieldType> expected_types = {types...};
+    std::vector<FieldType> actual_types = base::ToVector(
+        form_structure->fields()[field_index]->server_predictions(),
+        [](const auto& p) {
+          return ToSafeFieldType(p.type(), NO_SERVER_DATA);
+        });
+    CHECK(expected_types == actual_types);
   };
   auto set_format_string = [&](size_t field_index,
                                std::string_view format_string) {
@@ -1573,7 +1589,7 @@
   set_server_type(0, PASSPORT_NUMBER);
   set_server_type(1, NAME_FIRST, PASSPORT_NAME_TAG);
   set_server_type(2, NAME_LAST, PASSPORT_NAME_TAG);
-  set_server_type(3, ADDRESS_HOME_COUNTRY, PASSPORT_ISSUING_COUNTRY);
+  set_server_type(3, PASSPORT_ISSUING_COUNTRY);
   set_server_type(4, PASSPORT_ISSUE_DATE);
   set_format_string(4, "M/YY");
   set_server_type(5, PASSPORT_EXPIRATION_DATE);
diff --git a/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc b/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
index e2c19a2f..ff1a0ea 100644
--- a/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
+++ b/components/autofill/core/browser/filling/payments/field_filling_payments_util.cc
@@ -483,9 +483,8 @@
     mojom::ActionPersistence action_persistence,
     const AutofillField& field,
     std::string* failure_to_fill) {
-  CHECK(FieldTypeGroupSet(
-            {FieldTypeGroup::kCreditCard, FieldTypeGroup::kStandaloneCvcField})
-            .contains(field.Type().group()));
+  CHECK(field.Type().GetGroups().contains_any(
+      {FieldTypeGroup::kCreditCard, FieldTypeGroup::kStandaloneCvcField}));
   std::u16string value =
       credit_card.record_type() == CreditCard::RecordType::kVirtualCard &&
               action_persistence == mojom::ActionPersistence::kPreview
diff --git a/components/autofill/core/browser/form_import/form_data_importer.cc b/components/autofill/core/browser/form_import/form_data_importer.cc
index 11c0ec2..1037bedf 100644
--- a/components/autofill/core/browser/form_import/form_data_importer.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer.cc
@@ -1050,7 +1050,8 @@
 
     // If we don't know the type of the field, or the user hasn't entered any
     // information into the field, then skip it.
-    if (value.empty() || field.Type().group() != FieldTypeGroup::kCreditCard) {
+    if (value.empty() ||
+        !field.Type().GetGroups().contains(FieldTypeGroup::kCreditCard)) {
       return;
     }
     std::u16string old_value = result.card.GetInfo(field.Type(), app_locale);
@@ -1145,8 +1146,7 @@
     if (!field->IsFieldFillable() || value.empty()) {
       continue;
     }
-    FieldType field_type = field->Type().GetStorableType();
-    if (field_type == IBAN_VALUE && Iban::IsValid(value)) {
+    if (field->Type().GetTypes().contains(IBAN_VALUE) && Iban::IsValid(value)) {
       candidate_iban.set_value(value);
       break;
     }
diff --git a/components/autofill/core/browser/form_import/form_data_importer_unittest.cc b/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
index 4c3b7b05e..710d8ea 100644
--- a/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
@@ -85,8 +85,15 @@
 using test::CreateTestFormField;
 using test::CreateTestIbanFormData;
 using ::testing::_;
+using ::testing::Contains;
+using ::testing::ElementsAre;
+using ::testing::Eq;
 using ::testing::NiceMock;
+using ::testing::Pair;
+using ::testing::Pointee;
 using ::testing::Return;
+using ::testing::Truly;
+using ::testing::UnorderedElementsAre;
 
 constexpr char kLocale[] = "en_US";
 
@@ -468,7 +475,7 @@
 // Takes `expected` by value to avoid a dangling reference.
 template <typename T>
 auto ComparesEqual(T expected) {
-  return ::testing::Truly([expected = std::move(expected)](const T& actual) {
+  return Truly([expected = std::move(expected)](const T& actual) {
     return actual.Compare(expected) == 0;
   });
 }
@@ -479,17 +486,16 @@
 
 template <typename T>
 auto UnorderedElementsCompareEqualArray(const std::vector<T>& expected_values) {
-  std::vector<::testing::Matcher<const T*>> matchers;
+  std::vector<testing::Matcher<const T*>> matchers;
   for (const T& expected : expected_values) {
-    matchers.push_back(::testing::Pointee(ComparesEqual(expected)));
+    matchers.push_back(Pointee(ComparesEqual(expected)));
   }
-  return ::testing::UnorderedElementsAreArray(matchers);
+  return UnorderedElementsAreArray(matchers);
 }
 
 template <typename... Matchers>
 auto UnorderedElementsCompareEqual(Matchers... matchers) {
-  return ::testing::UnorderedElementsAre(
-      ::testing::Pointee(ComparesEqual(std::move(matchers)))...);
+  return UnorderedElementsAre(Pointee(ComparesEqual(std::move(matchers)))...);
 }
 
 // TODO(crbug.com/40270301): Move MockCreditCardSaveManager to new header and cc
@@ -1337,7 +1343,8 @@
       ConstructDefaultProfileFormStructure();
 
   // Change the value of the email field.
-  ASSERT_EQ(form_structure->field(2)->Type().GetStorableType(), EMAIL_ADDRESS);
+  ASSERT_THAT(form_structure->field(2)->Type().GetTypes(),
+              Contains(EMAIL_ADDRESS));
   form_structure->field(2)->set_value(u"bogus");
 
   // Verify that there was no import.
@@ -3938,7 +3945,7 @@
 
 INSTANTIATE_TEST_SUITE_P(All,
                          SkipSaveCardInFormDataImporterTest,
-                         ::testing::Bool());
+                         testing::Bool());
 
 // Test that save card functionality is skipped for tab modal popup only when
 // kAutofillSkipSaveCardForTabModalPopup is enabled; otherwise, the card saving
@@ -4271,9 +4278,7 @@
       test_api(form_data_importer()).HasInvalidFieldTypes(section_fields));
   EXPECT_THAT(
       test_api(form_data_importer()).GetObservedFieldValues(section_fields),
-      ::testing::ElementsAre(
-          ::testing::Pair(::testing::Eq(ADDRESS_HOME_COUNTRY),
-                          ::testing::Eq(u"United States"))));
+      ElementsAre(Pair(Eq(ADDRESS_HOME_COUNTRY), Eq(u"United States"))));
 }
 
 // Tests that duplicate fields with identical field values are valid for the
@@ -4298,9 +4303,7 @@
       test_api(form_data_importer()).HasInvalidFieldTypes(section_fields));
   EXPECT_THAT(
       test_api(form_data_importer()).GetObservedFieldValues(section_fields),
-      ::testing::ElementsAre(
-          ::testing::Pair(::testing::Eq(ADDRESS_HOME_COUNTRY),
-                          ::testing::Eq(u"United States"))));
+      ElementsAre(Pair(Eq(ADDRESS_HOME_COUNTRY), Eq(u"United States"))));
 }
 
 }  // namespace
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 480bc68..7c4a151c 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -274,12 +274,14 @@
       size_t next_section_id = section_id_map.size() + 1;
       section_id_map[field->section()] = next_section_id;
     }
-    field->AppendLogEventIfNotRepeated(RationalizationFieldLogEvent{
-        .field_type = field->Type().GetStorableType(),
-        .section_id = section_id_map[field->section()],
-        .type_changed = field->Type().GetStorableType() !=
-                        field->ComputedType().GetStorableType(),
-    });
+    for (FieldType field_type : field->Type().GetTypes()) {
+      field->AppendLogEventIfNotRepeated(RationalizationFieldLogEvent{
+          .field_type = field_type,
+          .section_id = section_id_map[field->section()],
+          .type_changed = field->Type().GetTypes().contains(field_type) !=
+                          field->ComputedType().GetTypes().contains(field_type),
+      });
+    }
   }
 }
 
@@ -886,7 +888,13 @@
       // the form types.
       form_types.insert(FormType::kUnknownFormType);
     } else {
-      form_types.insert(FieldTypeGroupToFormType(field->Type().group()));
+      form_types.insert_all([&field] {
+        DenseSet<FormType> ts = field->Type().GetFormTypes();
+        if (ts.empty()) {
+          ts = {FormType::kUnknownFormType};
+        }
+        return ts;
+      }());
     }
   }
   return form_types;
diff --git a/components/autofill/core/browser/form_structure_rationalization_engine.cc b/components/autofill/core/browser/form_structure_rationalization_engine.cc
index 060a3ab..62af1e8d 100644
--- a/components/autofill/core/browser/form_structure_rationalization_engine.cc
+++ b/components/autofill/core/browser/form_structure_rationalization_engine.cc
@@ -161,8 +161,8 @@
                                                const FieldCondition& condition,
                                                const AutofillField& field) {
   if (condition.possible_overall_types.has_value() &&
-      !condition.possible_overall_types->contains(
-          field.Type().GetStorableType())) {
+      !condition.possible_overall_types->contains_any(
+          field.Type().GetTypes())) {
     return false;
   }
 
@@ -192,7 +192,7 @@
                                                     candidate_field)) {
         return static_cast<size_t>(i);
       }
-      if (candidate_field.Type().GetStorableType() != UNKNOWN_TYPE &&
+      if (!candidate_field.Type().GetTypes().contains(UNKNOWN_TYPE) &&
           ((direction > 0 &&
             condition.location == FieldLocation::kNextClassifiedSuccessor) ||
            (direction < 0 &&
@@ -286,7 +286,7 @@
       CHECK(found_fields.find(action.target) != found_fields.end());
       AutofillField& field = *fields[found_fields[action.target]];
       buffer << ", changing field " << found_fields[action.target] << " from "
-             << FieldTypeToStringView(field.Type().GetStorableType()) << " to "
+             << FieldTypeSetToString(field.Type().GetTypes()) << " to "
              << FieldTypeToStringView(action.set_overall_type);
       field.SetTypeTo(AutofillType(action.set_overall_type),
                       AutofillPredictionSource::kRationalization);
diff --git a/components/autofill/core/browser/form_structure_rationalizer.cc b/components/autofill/core/browser/form_structure_rationalizer.cc
index 82fe158..cdd4df3 100644
--- a/components/autofill/core/browser/form_structure_rationalizer.cc
+++ b/components/autofill/core/browser/form_structure_rationalizer.cc
@@ -713,11 +713,21 @@
         AutofillField::FormatStringSource::kHeuristics);
   };
 
+  auto get_autofill_ai_date_types = [](const AutofillField& field) {
+    FieldTypeSet field_types = field.Type().GetAutofillAiTypes();
+    for (const FieldType field_type : field_types) {
+      if (!IsDateFieldType(field_type)) {
+        field_types.erase(field_type);
+      }
+    }
+    return field_types;
+  };
+
   for (auto it = fields_->begin(); it != fields_->end(); ++it) {
     AutofillField& field = **it;
-    if (std::optional<FieldType> type =
-            field.GetAutofillAiServerTypePredictions();
-        !type || !IsDateFieldType(*type)) {
+    const FieldTypeSet autofill_ai_date_types =
+        get_autofill_ai_date_types(field);
+    if (autofill_ai_date_types.empty()) {
       continue;
     }
     switch (field.format_string_source()) {
@@ -780,8 +790,7 @@
           return nullptr;
         }
         AutofillField& successor = **std::next(it, n);
-        if (successor.GetAutofillAiServerTypePredictions() !=
-            field.GetAutofillAiServerTypePredictions()) {
+        if (get_autofill_ai_date_types(successor) != autofill_ai_date_types) {
           return nullptr;
         }
         if (successor.label() != field.label() && !successor.label().empty()) {
diff --git a/components/autofill/core/browser/form_structure_rationalizer_unittest.cc b/components/autofill/core/browser/form_structure_rationalizer_unittest.cc
index abda6162..229c1ad 100644
--- a/components/autofill/core/browser/form_structure_rationalizer_unittest.cc
+++ b/components/autofill/core/browser/form_structure_rationalizer_unittest.cc
@@ -146,15 +146,19 @@
   return form_structure;
 }
 
-std::vector<FieldType> GetTypes(const FormStructure& form_structure) {
-  std::vector<FieldType> types;
+std::vector<FieldTypeSet> GetTypes(const FormStructure& form_structure) {
+  std::vector<FieldTypeSet> types;
   types.reserve(form_structure.field_count());
   for (size_t i = 0; i < form_structure.field_count(); ++i) {
-    types.push_back(form_structure.field(i)->Type().GetStorableType());
+    types.push_back(form_structure.field(i)->Type().GetTypes());
   }
   return types;
 }
 
+auto FieldTypesAre(auto... types) {
+  return ElementsAre(FieldTypeSet{types}...);
+}
+
 std::vector<std::optional<std::string>> GetFormatStrings(
     const FormStructure& form_structure) {
   std::vector<std::optional<std::string>> format_strings;
@@ -172,8 +176,8 @@
 
 Matcher<AutofillField> HasType(FieldType type) {
   return Property("AutofillField::Type", &AutofillField::Type,
-                  Property("AutofillType::GetStorableType",
-                           &AutofillType::GetStorableType, type));
+                  Property("AutofillType::GetTypes", &AutofillType::GetTypes,
+                           ElementsAre(type)));
 }
 
 Matcher<AutofillField> HasOffset(size_t offset) {
@@ -212,9 +216,9 @@
        {"height", "height", CREDIT_CARD_EXP_MONTH},  // Uh-oh!
        {"email", "email", EMAIL_ADDRESS}},
       /*run_heuristics=*/false);
-  EXPECT_THAT(
-      GetTypes(*form_structure),
-      ElementsAre(NAME_FULL, ADDRESS_HOME_LINE1, UNKNOWN_TYPE, EMAIL_ADDRESS));
+  EXPECT_THAT(GetTypes(*form_structure),
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_LINE1, UNKNOWN_TYPE,
+                            EMAIL_ADDRESS));
 }
 
 TEST_F(FormStructureRationalizerTest, ParseQueryResponse_RationalizeCCName) {
@@ -224,7 +228,7 @@
                           {"email", "email", EMAIL_ADDRESS}},
                          /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FIRST, NAME_LAST, EMAIL_ADDRESS));
+              FieldTypesAre(NAME_FIRST, NAME_LAST, EMAIL_ADDRESS));
 }
 TEST_F(FormStructureRationalizerTest,
        ParseQueryResponse_RationalizeMultiMonth_1) {
@@ -238,9 +242,9 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
-                          CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR,
-                          UNKNOWN_TYPE));
+              FieldTypesAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
+                            CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR,
+                            UNKNOWN_TYPE));
 }
 
 TEST_F(FormStructureRationalizerTest,
@@ -254,8 +258,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
-                          CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, UNKNOWN_TYPE));
+              FieldTypesAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
+                            CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, UNKNOWN_TYPE));
 }
 
 TEST_F(FormStructureRationalizerTest, RationalizeStreetAddressAndAddressLine) {
@@ -267,7 +271,7 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2));
 }
 
 // Tests that phone number trunk types are rationalized correctly.
@@ -314,9 +318,13 @@
       BuildFormStructure(fields, /*run_heuristics=*/false);
 
   // Expect `kCorrectTypes` twice.
-  std::vector<FieldType> expected_types = kCorrectTypes;
-  expected_types.insert(expected_types.end(), kCorrectTypes.begin(),
-                        kCorrectTypes.end());
+  std::vector<FieldTypeSet> expected_types;
+  for (const FieldType field_type : kCorrectTypes) {
+    expected_types.push_back(FieldTypeSet{field_type});
+  }
+  for (const FieldType field_type : kCorrectTypes) {
+    expected_types.push_back(FieldTypeSet{field_type});
+  }
   EXPECT_THAT(GetTypes(*form_structure), ElementsAreArray(expected_types));
 }
 
@@ -333,7 +341,7 @@
       /*run_heuristics=*/false);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY));
+      FieldTypesAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY));
 }
 
 // Tests that a form that has two address predicted as
@@ -350,8 +358,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2,
-                          ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2,
+                            ADDRESS_HOME_CITY));
 }
 
 // Tests that a form that has three address lines predicted as
@@ -369,8 +377,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2,
-                          ADDRESS_HOME_LINE3, ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2,
+                            ADDRESS_HOME_LINE3, ADDRESS_HOME_CITY));
 }
 
 // Tests that a form that has four address lines predicted as
@@ -391,9 +399,9 @@
       /*run_heuristics=*/false);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
-                  ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_ADDRESS,
-                  ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY));
+      FieldTypesAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
+                    ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_ADDRESS,
+                    ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY));
 }
 
 // Tests that a form that has only one address in each section predicted as
@@ -413,7 +421,7 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(
+              FieldTypesAre(
                   // Billing:
                   NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY,
                   // Shipping:
@@ -451,7 +459,7 @@
       /*run_heuristics=*/false);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(
+      FieldTypesAre(
           // Shipping.
           NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2, ADDRESS_HOME_CITY,
           // Billing.
@@ -482,7 +490,7 @@
       },
       /*run_heuristics=*/true);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(
+              FieldTypesAre(
                   // Billing.
                   NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY,
                   // Shipping.
@@ -512,7 +520,7 @@
       /*run_heuristics=*/true);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(
+      FieldTypesAre(
           // Shipping.
           NAME_FULL, ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2, ADDRESS_HOME_CITY,
           // Billing.
@@ -528,8 +536,9 @@
 
   // As there are no other credit card fields or an email address field, we
   // rationalize the CVC field to a standalone CVC field.
-  EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, CREDIT_CARD_STANDALONE_VERIFICATION_CODE));
+  EXPECT_THAT(
+      GetTypes(*form_structure),
+      FieldTypesAre(NAME_FULL, CREDIT_CARD_STANDALONE_VERIFICATION_CODE));
 }
 
 TEST_F(FormStructureRationalizerTest,
@@ -545,9 +554,9 @@
   // As there are other credit card fields, we won't map the CVC field to a
   // standalone CVC field.
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
-                          CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR,
-                          CREDIT_CARD_VERIFICATION_CODE));
+              FieldTypesAre(CREDIT_CARD_NAME_FULL, CREDIT_CARD_NUMBER,
+                            CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR,
+                            CREDIT_CARD_VERIFICATION_CODE));
 }
 
 TEST_F(FormStructureRationalizerTest,
@@ -560,7 +569,7 @@
   // As there is an email address field we won't map the CVC field to a
   // standalone CVC field.
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(EMAIL_ADDRESS, UNKNOWN_TYPE));
+              FieldTypesAre(EMAIL_ADDRESS, UNKNOWN_TYPE));
 }
 
 // Tests that contenteditables types are overridden with UNKNOWN_TYPE.
@@ -572,7 +581,7 @@
         .form_control_type = FormControlType::kInputText}},
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(UNKNOWN_TYPE, CREDIT_CARD_NUMBER));
+              FieldTypesAre(UNKNOWN_TYPE, CREDIT_CARD_NUMBER));
 }
 
 // Tests the rationalization that ignores certain types on the main origin. The
@@ -895,7 +904,7 @@
 
 struct RationalizeAutocompleteTestParam {
   std::vector<FieldTemplate> fields;
-  std::vector<FieldType> final_types;
+  std::vector<FieldTypeSet> final_types;
 };
 
 class RationalizeAutocompleteTest
@@ -917,21 +926,21 @@
                             AutocompleteParsingResult{
                                 .field_type = HtmlFieldType::kAdditionalName},
                         .max_length = 1}},
-            .final_types = {NAME_MIDDLE_INITIAL}},
+            .final_types = {{NAME_MIDDLE_INITIAL}}},
         // <input autocomplete="cc-exp" max-length=5> becomes a MM/YY field.
         RationalizeAutocompleteTestParam{
             .fields = {{.parsed_autocomplete =
                             AutocompleteParsingResult{
                                 .field_type = HtmlFieldType::kCreditCardExp},
                         .max_length = 5}},
-            .final_types = {CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}}},
         // <input autocomplete="cc-exp" max-length=7> becomes a MM/YYYY field.
         RationalizeAutocompleteTestParam{
             .fields = {{.parsed_autocomplete =
                             AutocompleteParsingResult{
                                 .field_type = HtmlFieldType::kCreditCardExp},
                         .max_length = 7}},
-            .final_types = {CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}}},
         // <input autocomplete="cc-exp" max-length=7> becomes a MM/YY field
         // if there is a MM / YY label.
         RationalizeAutocompleteTestParam{
@@ -940,7 +949,7 @@
                             AutocompleteParsingResult{
                                 .field_type = HtmlFieldType::kCreditCardExp},
                         .max_length = 7}},
-            .final_types = {CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}}},
         // <input autocomplete="cc-exp" max-length=20> becomes a MM/YYYY field
         // by default (see test above), but if later a server classification is
         // available, the type is re-rationalized to a 2 digit expiration field.
@@ -956,14 +965,14 @@
                           .field_type =
                               HtmlFieldType::kCreditCardExpDate4DigitYear},
                   .max_length = 7}},
-            .final_types = {CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}}},
         // The pattern "MM / YY" trumps a server verdict.
         RationalizeAutocompleteTestParam{
             .fields = {{.label = "MM / YY",
                         .field_type = CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
                         .max_length = 7,
                         .heuristic_type = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
-            .final_types = {CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}}},
         // The pattern "MM / YY" does NOT trump a server override.
         RationalizeAutocompleteTestParam{
             .fields = {{.label = "MM / YY",
@@ -971,7 +980,7 @@
                         .max_length = 7,
                         .field_type_is_override = true,
                         .heuristic_type = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR}},
-            .final_types = {CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}}},
         // <input autocomplete="cc-exp-year" max-length=4> becomes a YYYY field.
         RationalizeAutocompleteTestParam{
             .fields =
@@ -982,8 +991,8 @@
                       AutocompleteParsingResult{
                           .field_type = HtmlFieldType::kCreditCardExpYear},
                   .max_length = 4}},
-            .final_types = {CREDIT_CARD_EXP_MONTH,
-                            CREDIT_CARD_EXP_4_DIGIT_YEAR}},
+            .final_types = {{CREDIT_CARD_EXP_MONTH},
+                            {CREDIT_CARD_EXP_4_DIGIT_YEAR}}},
         // <input autocomplete="cc-exp-year" max-length=2> becomes a YY field.
         RationalizeAutocompleteTestParam{
             .fields =
@@ -994,8 +1003,8 @@
                       AutocompleteParsingResult{
                           .field_type = HtmlFieldType::kCreditCardExpYear},
                   .max_length = 2}},
-            .final_types = {CREDIT_CARD_EXP_MONTH,
-                            CREDIT_CARD_EXP_2_DIGIT_YEAR}}));
+            .final_types = {{CREDIT_CARD_EXP_MONTH},
+                            {CREDIT_CARD_EXP_2_DIGIT_YEAR}}}));
 
 TEST_P(RationalizeAutocompleteTest, RationalizeAutocompleteAttribute) {
   std::unique_ptr<FormStructure> form_structure =
@@ -1016,7 +1025,7 @@
       /*run_heuristics=*/true);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(NAME_FIRST, NAME_LAST, ADDRESS_HOME_LINE1, UNKNOWN_TYPE));
+      FieldTypesAre(NAME_FIRST, NAME_LAST, ADDRESS_HOME_LINE1, UNKNOWN_TYPE));
 }
 
 // Tests that PHONE_HOME_COUNTRY_CODE fields are not rationalized to
@@ -1030,8 +1039,8 @@
                            PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}},
                          /*run_heuristics=*/true);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FIRST, NAME_LAST, PHONE_HOME_COUNTRY_CODE,
-                          PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX));
+              FieldTypesAre(NAME_FIRST, NAME_LAST, PHONE_HOME_COUNTRY_CODE,
+                            PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX));
 }
 
 class RationalizePhoneNumbersForFillingTest
@@ -1392,8 +1401,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
-                          ADDRESS_HOME_ZIP_PREFIX, ADDRESS_HOME_ZIP_SUFFIX));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
+                            ADDRESS_HOME_ZIP_PREFIX, ADDRESS_HOME_ZIP_SUFFIX));
 }
 
 // Tests that two consecutive ADDRESS_HOME_ZIP fields are not rationalized
@@ -1415,8 +1424,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
-                          ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
+                            ADDRESS_HOME_CITY));
 }
 
 // Tests that two consecutive ADDRESS_HOME_ZIP fields are not rationalized
@@ -1432,8 +1441,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
-                          ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
+                            ADDRESS_HOME_CITY));
 }
 
 // Tests that 3 consecutive ADDRESS_HOME_ZIP fields are not affected
@@ -1461,8 +1470,8 @@
       /*run_heuristics=*/false);
   EXPECT_THAT(
       GetTypes(*form_structure),
-      ElementsAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_ZIP,
-                  ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP));
+      FieldTypesAre(NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_ZIP,
+                    ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP));
 }
 
 // Tests that a form that has two non-consecutive ADDRESS_HOME_ZIP fields
@@ -1485,8 +1494,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY,
-                          NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY,
+                            NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY));
 }
 
 // Tests that ADDRESS_HOME_ZIP_SUFFIX without previous ADDRESS_HOME_ZIP is
@@ -1502,7 +1511,7 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_CITY));
 }
 
 // Tests that (ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP_SUFFIX) is rationalized to
@@ -1519,8 +1528,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP_PREFIX,
-                          ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP_PREFIX,
+                            ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_CITY));
 }
 
 // Tests that (ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_ZIP_SUFFIX) is rationalized
@@ -1539,8 +1548,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP_PREFIX,
-                          ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP_PREFIX,
+                            ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_CITY));
 }
 
 // Tests that (ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_ZIP) is rationalized
@@ -1557,8 +1566,8 @@
       },
       /*run_heuristics=*/false);
   EXPECT_THAT(GetTypes(*form_structure),
-              ElementsAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
-                          ADDRESS_HOME_CITY));
+              FieldTypesAre(NAME_FULL, ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP,
+                            ADDRESS_HOME_CITY));
 }
 
 }  // namespace
diff --git a/components/autofill/core/browser/form_structure_sectioning_util.cc b/components/autofill/core/browser/form_structure_sectioning_util.cc
index 595f1c9b..d2dcbb38 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util.cc
+++ b/components/autofill/core/browser/form_structure_sectioning_util.cc
@@ -16,16 +16,17 @@
 
 namespace {
 
-bool HaveSeenSimilarType(FieldType type, const FieldTypeSet& seen_types) {
+bool HaveSeenSimilarType(const FieldTypeSet& types,
+                         const FieldTypeSet& seen_types) {
   // Forms sometimes have a different format of inputting names in
   // different sections. If we believe a new name is being entered, assume
   // it is a new section.
-  FieldTypeSet first_last_name = {NAME_FIRST, NAME_LAST};
-  if ((type == NAME_FULL && seen_types.contains_any(first_last_name)) ||
-      (first_last_name.contains(type) && seen_types.contains(NAME_FULL))) {
+  static constexpr FieldTypeSet kFirstLastName = {NAME_FIRST, NAME_LAST};
+  if ((types.contains(NAME_FULL) && seen_types.contains_any(kFirstLastName)) ||
+      (types.contains_any(kFirstLastName) && seen_types.contains(NAME_FULL))) {
     return true;
   }
-  return seen_types.count(type) > 0;
+  return seen_types.contains_any(types);
 }
 
 // Some forms have adjacent fields of the same or very similar type. These
@@ -38,19 +39,24 @@
 //  * In Japan, forms commonly have separate inputs for phonetic names. In
 //    practice this means consecutive name field types (e.g. first name and last
 //    name).
-bool ConsecutiveSimilarFieldType(FieldType current_type,
-                                 FieldType previous_type) {
-  if (previous_type == current_type)
-    return true;
-  if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kName &&
-      GroupTypeOfFieldType(previous_type) == FieldTypeGroup::kName) {
+bool ConsecutiveSimilarFieldType(const AutofillType& current_type,
+                                 const AutofillType& previous_type) {
+  const FieldTypeSet common_types =
+      Intersection(current_type.GetTypes(), previous_type.GetTypes());
+  if (!common_types.empty()) {
     return true;
   }
-  if (FieldTypeSet({ADDRESS_HOME_ZIP, ADDRESS_HOME_ZIP_PREFIX,
-                    ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_DEPENDENT_LOCALITY,
-                    ADDRESS_HOME_CITY, ADDRESS_HOME_ADMIN_LEVEL2,
-                    ADDRESS_HOME_STATE, ADDRESS_HOME_COUNTRY})
-          .contains_all({previous_type, current_type})) {
+  if (current_type.GetGroups().contains(FieldTypeGroup::kName) &&
+      previous_type.GetGroups().contains(FieldTypeGroup::kName)) {
+    return true;
+  }
+  static constexpr FieldTypeSet kSimilar = {
+      ADDRESS_HOME_ZIP,        ADDRESS_HOME_ZIP_PREFIX,
+      ADDRESS_HOME_ZIP_SUFFIX, ADDRESS_HOME_DEPENDENT_LOCALITY,
+      ADDRESS_HOME_CITY,       ADDRESS_HOME_ADMIN_LEVEL2,
+      ADDRESS_HOME_STATE,      ADDRESS_HOME_COUNTRY};
+  if (kSimilar.contains_any(previous_type.GetTypes()) &&
+      kSimilar.contains_any(current_type.GetTypes())) {
     return true;
   }
   return false;
@@ -73,7 +79,8 @@
     base::flat_map<LocalFrameToken, size_t>& frame_token_ids) {
   auto first_cc_field = std::ranges::find_if(
       fields, [](const std::unique_ptr<AutofillField>& field) {
-        return field->Type().group() == FieldTypeGroup::kCreditCard &&
+        return field->Type().GetGroups().contains(
+                   FieldTypeGroup::kCreditCard) &&
                !field->section();
       });
   if (first_cc_field == fields.end())
@@ -81,7 +88,7 @@
   Section cc_section =
       Section::FromFieldIdentifier(**first_cc_field, frame_token_ids);
   for (const auto& field : fields) {
-    if (field->Type().group() == FieldTypeGroup::kCreditCard &&
+    if (field->Type().GetGroups().contains(FieldTypeGroup::kCreditCard) &&
         !field->section()) {
       field->set_section(cc_section);
     }
@@ -121,25 +128,25 @@
     return true;
   }
 
-  const FieldType current_type = current_field.Type().GetStorableType();
-  if (current_type == UNKNOWN_TYPE)
+  const AutofillType current_type = current_field.Type();
+  if (current_type.GetTypes().contains(UNKNOWN_TYPE)) {
     return true;
+  }
 
   // Generally, adjacent fields of the same or very similar type belong in the
   // same logical section.
-  if (ConsecutiveSimilarFieldType(current_type,
-                                  previous_field.Type().GetStorableType())) {
+  if (ConsecutiveSimilarFieldType(current_type, previous_field.Type())) {
     return true;
   }
 
   // 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 (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kPhone) {
+  if (current_type.GetGroups().contains(FieldTypeGroup::kPhone)) {
     return true;
   }
 
-  return !HaveSeenSimilarType(current_type, seen_types);
+  return !HaveSeenSimilarType(current_type.GetTypes(), seen_types);
 }
 
 // Finds the first focusable field that doesn't have a section assigned.
@@ -178,7 +185,7 @@
       return it;
     }
     if (!field.section()) {
-      seen_types.insert(field.Type().GetStorableType());
+      seen_types.insert_all(field.Type().GetTypes());
       prev_field = &field;
     }
   }
diff --git a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
index 6e6a130..1ed6763 100644
--- a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
+++ b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
@@ -47,7 +47,7 @@
     f->set_form_control_type(t.form_control_type);
     f->SetTypeTo(AutofillType(t.field_type),
                  AutofillPredictionSource::kHeuristics);
-    DCHECK_EQ(f->Type().GetStorableType(), t.field_type);
+    DCHECK_EQ(f->Type().GetTypes(), FieldTypeSet{t.field_type});
     if (!t.autocomplete_section.empty() ||
         t.autocomplete_mode != HtmlFieldMode::kNone) {
       f->set_parsed_autocomplete(AutocompleteParsingResult{
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 0492ce1..106b637 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -912,7 +912,7 @@
   EXPECT_FALSE(FormShouldRunHeuristics(form));
   EXPECT_TRUE(FormShouldBeQueried(form));
 
-  // As a side effect of parsing small forms (if any of the heuristics, query,
+  // As a side effect of parsing small forms, if any of the heuristics, query,
   // or upload minimums are disabled, we'll autofill fields with an
   // autocomplete attribute, even if its the only field in the form.
   {
@@ -924,7 +924,8 @@
     ASSERT_EQ(1U, AutofillCount(form_structure));
     EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type());
     EXPECT_EQ(NO_SERVER_DATA, form_structure.field(0)->server_type());
-    EXPECT_EQ(NAME_FIRST, form_structure.field(0)->Type().GetStorableType());
+    EXPECT_THAT(form_structure.field(0)->Type().GetTypes(),
+                ElementsAre(NAME_FIRST));
     EXPECT_TRUE(form_structure.IsAutofillable());
   }
 }
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager.cc b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
index 23bcad2..5038647 100644
--- a/components/autofill/core/browser/foundations/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
@@ -567,15 +567,16 @@
   return plus_addresses[0];
 }
 
-base::flat_map<FieldGlobalId, FieldTypeGroup>
+base::flat_map<FieldGlobalId, FieldTypeGroupSet>
 GetFieldTypeGroupsFromFormStructure(const FormStructure* form_structure) {
-  return form_structure ? base::MakeFlatMap<FieldGlobalId, FieldTypeGroup>(
-                              form_structure->fields(), /*comp=*/{},
-                              [](const std::unique_ptr<AutofillField>& field) {
-                                return std::make_pair(field->global_id(),
-                                                      field->Type().group());
-                              })
-                        : base::flat_map<FieldGlobalId, FieldTypeGroup>();
+  return form_structure
+             ? base::MakeFlatMap<FieldGlobalId, FieldTypeGroupSet>(
+                   form_structure->fields(), /*comp=*/{},
+                   [](const std::unique_ptr<AutofillField>& field) {
+                     return std::make_pair(field->global_id(),
+                                           field->Type().GetGroups());
+                   })
+             : base::flat_map<FieldGlobalId, FieldTypeGroupSet>();
 }
 
 // Returns if the email address was modified on any of the suggested addresses
@@ -1061,7 +1062,7 @@
     // achieves that.
     if (!std::ranges::all_of(*form_structure, [](const auto& field) {
           return field->ShouldSuppressSuggestionsAndFillingByDefault() ||
-                 field->Type().GetStorableType() == UNKNOWN_TYPE;
+                 field->Type().GetTypes().contains(UNKNOWN_TYPE);
         })) {
       context.suppress_reason = SuppressReason::kAutocompleteUnrecognized;
     }
@@ -1409,7 +1410,7 @@
   // at least one address suggestion.
   const bool should_offer_plus_addresses_with_profiles =
       context.field_is_relevant_for_plus_addresses && autofill_field &&
-      autofill_field->Type().group() == FieldTypeGroup::kEmail &&
+      autofill_field->Type().GetGroups().contains(FieldTypeGroup::kEmail) &&
       !suggestions.empty() &&
       !WasEmailOverrideAppliedOnSuggestions(suggestions);
   // Try to show plus address suggestions. If the user specifically requested
@@ -1503,9 +1504,9 @@
   // Whether or not to show plus address suggestions.
   const bool should_offer_plus_addresses =
       context.field_is_relevant_for_plus_addresses && autofill_field &&
-      (autofill_field->Type().group() == FieldTypeGroup::kEmail ||
-       autofill_field->Type().GetStorableType() == FieldType::USERNAME ||
-       autofill_field->Type().GetStorableType() == FieldType::SINGLE_USERNAME);
+      (autofill_field->Type().GetGroups().contains(FieldTypeGroup::kEmail) ||
+       autofill_field->Type().GetTypes().contains(FieldType::USERNAME) ||
+       autofill_field->Type().GetTypes().contains(FieldType::SINGLE_USERNAME));
 
   // Early return to avoid running password form classifications.
   if (!should_offer_plus_addresses && !should_offer_single_field_form_fill) {
@@ -2744,10 +2745,11 @@
   }
 
   const AutofillField* email_autofill_field = nullptr;
-  if (auto it = std::ranges::find(safe_filled_fields, EMAIL_ADDRESS,
-                                  [](const AutofillField* field) {
-                                    return field->Type().GetStorableType();
-                                  });
+  if (auto it = std::ranges::find_if(safe_filled_fields,
+                                     [](const AutofillField* field) {
+                                       return field->Type().GetTypes().contains(
+                                           EMAIL_ADDRESS);
+                                     });
       it != safe_filled_fields.end()) {
     email_autofill_field = *it;
   } else {
@@ -2792,7 +2794,7 @@
     return;
   }
 
-  if (autofill_field->Type().GetStorableType() != EMAIL_ADDRESS) {
+  if (!autofill_field->Type().GetTypes().contains(EMAIL_ADDRESS)) {
     return;
   }
 
@@ -3279,7 +3281,11 @@
     // Ignore ac=unrecognized fields in key metrics.
     return nullptr;
   }
-  switch (FieldTypeGroupToFormType(field.Type().group())) {
+  // TODO(crbug.com/432645177): When migrating Loyalty Cards to AutofillType, we
+  // need to pick the right logger(s) here.
+  const DenseSet<FormType> form_types = field.Type().GetFormTypes();
+  switch (!form_types.empty() ? *form_types.begin()
+                              : FormType::kUnknownFormType) {
     case FormType::kAddressForm:
       return &metrics_->address_form_event_logger;
     case FormType::kCreditCardForm:
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
index e0c7399..3c37cbc6 100644
--- a/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
@@ -4471,7 +4471,8 @@
                                ADDRESS_HOME_CITY, ADDRESS_HOME_STATE,
                                ADDRESS_HOME_ZIP};
   for (size_t i = 0; i < types.size(); ++i) {
-    EXPECT_EQ(types[i], form_structure->field(i)->Type().GetStorableType());
+    EXPECT_THAT(form_structure->field(i)->Type().GetTypes(),
+                ElementsAre(types[i]));
   }
 
   // Simulate form submission.
@@ -4948,18 +4949,20 @@
 
   // We expect the server suggestions to have been applied to the first field of
   // the first form.
-  EXPECT_EQ(ADDRESS_HOME_CITY,
-            form_structure->field(0)->Type().GetStorableType());
-  EXPECT_EQ(ADDRESS_HOME_STATE,
-            form_structure->field(1)->Type().GetStorableType());
-  EXPECT_EQ(ADDRESS_HOME_ZIP,
-            form_structure->field(2)->Type().GetStorableType());
+  EXPECT_THAT(form_structure->field(0)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_CITY));
+  EXPECT_THAT(form_structure->field(1)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_STATE));
+  EXPECT_THAT(form_structure->field(2)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_ZIP));
   // We expect the server suggestions to have been applied to the second form as
   // well.
-  EXPECT_EQ(NAME_LAST, form_structure2->field(0)->Type().GetStorableType());
-  EXPECT_EQ(NAME_MIDDLE, form_structure2->field(1)->Type().GetStorableType());
-  EXPECT_EQ(ADDRESS_HOME_ZIP,
-            form_structure2->field(2)->Type().GetStorableType());
+  EXPECT_THAT(form_structure2->field(0)->Type().GetTypes(),
+              ElementsAre(NAME_LAST));
+  EXPECT_THAT(form_structure2->field(1)->Type().GetTypes(),
+              ElementsAre(NAME_MIDDLE));
+  EXPECT_THAT(form_structure2->field(2)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_ZIP));
 }
 
 // Test that OnLoadedServerPredictions does not call ParseQueryResponse if the
@@ -5064,10 +5067,10 @@
             form_structure->field(4)->heuristic_type());
 
   // We expect to see the server type as the overall type.
-  EXPECT_EQ(CREDIT_CARD_NAME_FIRST,
-            form_structure->field(0)->Type().GetStorableType());
-  EXPECT_EQ(CREDIT_CARD_NAME_LAST,
-            form_structure->field(1)->Type().GetStorableType());
+  EXPECT_THAT(form_structure->field(0)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NAME_FIRST));
+  EXPECT_THAT(form_structure->field(1)->Type().GetTypes(),
+              ElementsAre(CREDIT_CARD_NAME_LAST));
   EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(2)->heuristic_type());
   EXPECT_EQ(CREDIT_CARD_EXP_MONTH, form_structure->field(3)->heuristic_type());
   EXPECT_EQ(CREDIT_CARD_EXP_4_DIGIT_YEAR,
@@ -7489,12 +7492,14 @@
   // Check that we set predictions on the form.
   const FormStructure* const fs = manager().FindCachedFormById(form_id);
   ASSERT_TRUE(fs);
-  EXPECT_EQ(fs->field(0)->GetAutofillAiServerTypePredictions(), std::nullopt);
-  EXPECT_EQ(fs->field(1)->GetAutofillAiServerTypePredictions(), std::nullopt);
-  EXPECT_EQ(fs->field(2)->GetAutofillAiServerTypePredictions(),
-            PASSPORT_NUMBER);
-  EXPECT_EQ(fs->field(3)->GetAutofillAiServerTypePredictions(),
-            PASSPORT_ISSUE_DATE);
+  EXPECT_THAT(fs->field(0)->Type().GetAutofillAiTypes(),
+              ElementsAre(NAME_FIRST));
+  EXPECT_THAT(fs->field(1)->Type().GetAutofillAiTypes(),
+              ElementsAre(NAME_LAST));
+  EXPECT_THAT(fs->field(2)->Type().GetAutofillAiTypes(),
+              ElementsAre(PASSPORT_NUMBER));
+  EXPECT_THAT(fs->field(3)->Type().GetAutofillAiTypes(),
+              ElementsAre(PASSPORT_ISSUE_DATE));
   ASSERT_TRUE(fs->field(3)->format_string().has_value());
   EXPECT_EQ(fs->field(3)->format_string().value(), u"D.M.YYYY");
   EXPECT_EQ(fs->field(3)->format_string_source(),
@@ -8350,8 +8355,9 @@
   const std::vector<std::string> plus_addresses = {kPlusAddress};
   EXPECT_CALL(plus_address_delegate(), IsFieldEligibleForPlusAddress)
       .WillRepeatedly([&](const AutofillField& f) {
-        return autofill::GetFillingProductFromFieldTypeGroup(
-                   f.Type().group()) == FillingProduct::kAddress;
+        return DenseSet<FillingProduct>(f.Type().GetGroups(),
+                                        &GetFillingProductFromFieldTypeGroup)
+            .contains(FillingProduct::kAddress);
       });
   EXPECT_CALL(plus_address_delegate(), GetAffiliatedPlusAddresses)
       .WillOnce(RunOnceCallback<1>(plus_addresses));
diff --git a/components/autofill/core/browser/heuristic_classification_unittests.cc b/components/autofill/core/browser/heuristic_classification_unittests.cc
index b7957ab..e2a1f805 100644
--- a/components/autofill/core/browser/heuristic_classification_unittests.cc
+++ b/components/autofill/core/browser/heuristic_classification_unittests.cc
@@ -248,28 +248,29 @@
     }
 
     // Determine the type assigned to the field by the heuristic classification.
-    std::string heuristic_type =
-        FieldTypeToString(form_structure.field(i)->Type().GetStorableType());
+    for (FieldType field_type : form_structure.field(i)->Type().GetTypes()) {
+      std::string heuristic_type = FieldTypeToString(field_type);
 
-    // Record metrics on the divergence between tester and heuristics.
-    if (fields_in_scope_.contains(tester_type)) {
-      if (TesterAndHeuristicTypeMatch(tester_type, heuristic_type)) {
-        ++matches_;
-        ++match_by_type_count_[tester_type];
-        json_fields[i].GetDict().Set("last_correctness", "correct");
+      // Record metrics on the divergence between tester and heuristics.
+      if (fields_in_scope_.contains(tester_type)) {
+        if (TesterAndHeuristicTypeMatch(tester_type, heuristic_type)) {
+          ++matches_;
+          ++match_by_type_count_[tester_type];
+          json_fields[i].GetDict().Set("last_correctness", "correct");
+        } else {
+          ++mismatches_;
+          ++mismatch_by_type_count_[tester_type];
+          json_fields[i].GetDict().Set(
+              "last_correctness", "not_recognized: " + tester_type +
+                                      ", chosen_instead: " + heuristic_type);
+        }
       } else {
-        ++mismatches_;
-        ++mismatch_by_type_count_[tester_type];
+        ++ignored_by_type_count_[tester_type];
         json_fields[i].GetDict().Set("last_correctness",
-                                     "not_recognized: " + tester_type +
-                                         ", chosen_instead: " + heuristic_type);
+                                     "ignored: " + tester_type);
       }
-    } else {
-      ++ignored_by_type_count_[tester_type];
-      json_fields[i].GetDict().Set("last_correctness",
-                                   "ignored: " + tester_type);
+      json_fields[i].GetDict().Set("last_classification", heuristic_type);
     }
-    json_fields[i].GetDict().Set("last_classification", heuristic_type);
   }
 }
 
diff --git a/components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.cc b/components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.cc
index d55a6791c..013fb6b 100644
--- a/components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.cc
+++ b/components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.cc
@@ -216,14 +216,14 @@
 
   const bool has_iban_field =
       std::ranges::any_of(form_structure, [](const auto& field) {
-        return field->Type().GetStorableType() == IBAN_VALUE;
+        return field->Type().GetTypes().contains(IBAN_VALUE);
       });
   if (has_iban_field) {
     optimization_types.insert(optimization_guide::proto::IBAN_AUTOFILL_BLOCKED);
   }
   const bool has_credit_card_field =
       std::ranges::any_of(form_structure, [](const auto& field) {
-        return field->Type().group() == FieldTypeGroup::kCreditCard;
+        return field->Type().GetGroups().contains(FieldTypeGroup::kCreditCard);
       });
 
   if (has_credit_card_field) {
@@ -331,7 +331,7 @@
     const AutofillField* field) const {
   // If the field's storable type is `IBAN_VALUE`, check whether IBAN
   // suggestions should be blocked based on `url`.
-  if (field->Type().GetStorableType() == IBAN_VALUE) {
+  if (field->Type().GetTypes().contains(IBAN_VALUE)) {
     optimization_guide::OptimizationGuideDecision decision =
         decider_->CanApplyOptimization(
             url, optimization_guide::proto::IBAN_AUTOFILL_BLOCKED,
diff --git a/components/autofill/core/browser/integrators/plus_addresses/autofill_plus_address_delegate.h b/components/autofill/core/browser/integrators/plus_addresses/autofill_plus_address_delegate.h
index e75dbf2..78d1c981 100644
--- a/components/autofill/core/browser/integrators/plus_addresses/autofill_plus_address_delegate.h
+++ b/components/autofill/core/browser/integrators/plus_addresses/autofill_plus_address_delegate.h
@@ -102,7 +102,7 @@
       bool is_off_the_record,
       const FormData& focused_form,
       const FormFieldData& focused_field,
-      const base::flat_map<FieldGlobalId, FieldTypeGroup>& form_field_types,
+      const base::flat_map<FieldGlobalId, FieldTypeGroupSet>& form_field_types,
       const PasswordFormClassification& focused_form_classification,
       AutofillSuggestionTriggerSource trigger_source) = 0;
 
diff --git a/components/autofill/core/browser/integrators/plus_addresses/mock_autofill_plus_address_delegate.h b/components/autofill/core/browser/integrators/plus_addresses/mock_autofill_plus_address_delegate.h
index ea4abbd..64b9d10 100644
--- a/components/autofill/core/browser/integrators/plus_addresses/mock_autofill_plus_address_delegate.h
+++ b/components/autofill/core/browser/integrators/plus_addresses/mock_autofill_plus_address_delegate.h
@@ -43,7 +43,7 @@
                bool,
                const FormData&,
                const FormFieldData&,
-               (const base::flat_map<FieldGlobalId, FieldTypeGroup>&),
+               (const base::flat_map<FieldGlobalId, FieldTypeGroupSet>&),
                const PasswordFormClassification&,
                AutofillSuggestionTriggerSource),
               (override));
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index 5c882634..f61e64b 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -1109,7 +1109,8 @@
     const url::Origin& triggered_origin = p.field.origin();
     return field.origin() != triggered_origin &&
            (field.origin() != main_origin ||
-            IsSensitiveFieldType(field.Type().GetStorableType())) &&
+            std::ranges::any_of(field.Type().GetTypes(),
+                                IsSensitiveFieldType)) &&
            triggered_origin == main_origin;
   };
 
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_utils.cc b/components/autofill/core/browser/metrics/autofill_metrics_utils.cc
index cf5057a..74c5c87d 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_utils.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_utils.cc
@@ -40,11 +40,12 @@
 bool IsEmailOnlyForm(const FormStructure& form) {
   bool has_email_field = false;
   for (const auto& field : form.fields()) {
-    FieldType field_type = field->Type().GetStorableType();
-    if (field_type == EMAIL_ADDRESS) {
+    const FieldTypeSet field_types = field->Type().GetTypes();
+    if (field_types.contains(EMAIL_ADDRESS)) {
       has_email_field = true;
     }
-    if (field_type != EMAIL_ADDRESS && field_type != UNKNOWN_TYPE &&
+    if (!field_types.contains(EMAIL_ADDRESS) &&
+        !field_types.contains(UNKNOWN_TYPE) &&
         FieldTypeGroupToFormType(field->Type().group()) !=
             FormType::kPasswordForm) {
       return false;
@@ -54,9 +55,9 @@
 }
 
 bool IsPostalAddressForm(const FormStructure& form) {
-  DenseSet<FieldType> postal_address_field_types;
+  FieldTypeSet postal_address_field_types;
   for (const auto& field : form.fields()) {
-    if (field->Type().group() == FieldTypeGroup::kAddress &&
+    if (field->Type().GetGroups().contains(FieldTypeGroup::kAddress) &&
         field->Type().GetAddressType() != ADDRESS_HOME_COUNTRY) {
       postal_address_field_types.insert(field->Type().GetAddressType());
     }
diff --git a/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.cc b/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.cc
index d86c6d5..f7e011e 100644
--- a/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.cc
+++ b/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.cc
@@ -199,10 +199,11 @@
 FormGroupFillingStats GetFormFillingStatsForFormType(
     FormType form_type,
     const FormStructure& form_structure) {
+  DCHECK_NE(form_type, FormType::kUnknownFormType);
   FormGroupFillingStats filling_stats_for_form_type;
 
   for (auto& field : form_structure) {
-    if (FieldTypeGroupToFormType(field->Type().group()) != form_type) {
+    if (!field->Type().GetFormTypes().contains(form_type)) {
       continue;
     }
     filling_stats_for_form_type.AddFieldFillingStatus(
@@ -224,12 +225,11 @@
     // collect the type-unspecific field filling statistics.
     // Those are only emitted when autofill was used on at least one field of
     // the form.
-    const FormType form_type_of_field =
-        FieldTypeGroupToFormType(field->Type().group());
+    const DenseSet<FormType> form_type_of_field = field->Type().GetFormTypes();
     const bool is_address_form_field =
-        form_type_of_field == FormType::kAddressForm;
+        form_type_of_field.contains(FormType::kAddressForm);
     const bool is_credit_card_form_field =
-        form_type_of_field == FormType::kCreditCardForm;
+        form_type_of_field.contains(FormType::kCreditCardForm);
     if (!is_address_form_field && !is_credit_card_form_field) {
       FieldFillingStatus field_stats = GetFieldFillingStatus(*field);
       unclassified_fields_field_stats.AddFieldFillingStatus(field_stats);
diff --git a/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.h b/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.h
index ed49da6..e212c55 100644
--- a/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.h
+++ b/components/autofill/core/browser/metrics/field_filling_stats_and_score_metrics.h
@@ -78,7 +78,8 @@
 FieldFillingStatus GetFieldFillingStatus(const AutofillField& field);
 
 // Returns the `FormGroupFillingStats` corresponding to the fields in
-// `form_structure` that match `form_type`. This method does not log to UMA but
+// `form_structure` that match `form_type`. `form_type` must not be
+// `kUnknownFormType`. This function does not log to UMA but
 // only returns the statistics of a submitted form. `FormGroupFillingStats` is
 // UMA logged in `LogQualityMetrics()`.
 FormGroupFillingStats GetFormFillingStatsForFormType(
diff --git a/components/autofill/core/browser/metrics/prediction_quality_metrics.cc b/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
index 64848e7..a08c9e3f 100644
--- a/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
+++ b/components/autofill/core/browser/metrics/prediction_quality_metrics.cc
@@ -839,7 +839,7 @@
   }
 
   bool is_valid_email = IsValidEmailAddress(value);
-  bool is_email_prediction = field.Type().GetStorableType() == EMAIL_ADDRESS;
+  bool is_email_prediction = field.Type().GetTypes().contains(EMAIL_ADDRESS);
 
   if (is_email_prediction) {
     EmailPredictionConfusionMatrix prediction_precision =
diff --git a/components/autofill/core/browser/metrics/quality_metrics.cc b/components/autofill/core/browser/metrics/quality_metrics.cc
index 04fb8e6..7f0725f 100644
--- a/components/autofill/core/browser/metrics/quality_metrics.cc
+++ b/components/autofill/core/browser/metrics/quality_metrics.cc
@@ -224,7 +224,7 @@
     }
     if (FieldHasMeaningfulPossibleFieldTypes(*field) &&
         field->is_autofilled()) {
-      autofilled_field_types.insert(field->Type().GetStorableType());
+      autofilled_field_types.insert_all(field->Type().GetTypes());
     }
   }
   if (base::Contains(form.GetFormTypes(), FormType::kCreditCardForm)) {
diff --git a/components/autofill/core/browser/metrics/quality_metrics_filling.cc b/components/autofill/core/browser/metrics/quality_metrics_filling.cc
index 6e4d1c06..80ed07d 100644
--- a/components/autofill/core/browser/metrics/quality_metrics_filling.cc
+++ b/components/autofill/core/browser/metrics/quality_metrics_filling.cc
@@ -127,7 +127,7 @@
         AutofillMetrics::AutocompleteStateForSubmittedField(*field) ==
         AutofillMetrics::AutocompleteState::kGarbage;
 
-    FieldTypeSet field_types = {field->Type().GetStorableType()};
+    FieldTypeSet field_types = field->Type().GetTypes();
     field_types.erase_all({NO_SERVER_DATA, UNKNOWN_TYPE, EMPTY_TYPE});
 
     for (std::string_view histogram_base :
diff --git a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
index 5d513a8..44bc49da 100644
--- a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
@@ -34,6 +34,7 @@
 using ::base::Bucket;
 using ::base::BucketsAre;
 using ::base::BucketsInclude;
+using ::testing::ElementsAre;
 
 using ExpectedUkmMetricsRecord = std::vector<ExpectedUkmMetricsPair>;
 using ExpectedUkmMetrics = std::vector<ExpectedUkmMetricsRecord>;
@@ -871,11 +872,12 @@
                      Bucket(AutofillMetrics::QUERY_RESPONSE_PARSED, 1)));
 
   // Autocomplete-derived types are eventually what's inferred.
-  EXPECT_EQ(NAME_LAST, form_structure_ptr->field(0)->Type().GetStorableType());
-  EXPECT_EQ(NAME_MIDDLE,
-            form_structure_ptr->field(1)->Type().GetStorableType());
-  EXPECT_EQ(ADDRESS_HOME_ZIP,
-            form_structure_ptr->field(2)->Type().GetStorableType());
+  EXPECT_THAT(form_structure_ptr->field(0)->Type().GetTypes(),
+              ElementsAre(NAME_LAST));
+  EXPECT_THAT(form_structure_ptr->field(1)->Type().GetTypes(),
+              ElementsAre(NAME_MIDDLE));
+  EXPECT_THAT(form_structure_ptr->field(2)->Type().GetTypes(),
+              ElementsAre(ADDRESS_HOME_ZIP));
 
   for (const std::string source : {"Heuristic", "Server"}) {
     std::string aggregate_histogram =
diff --git a/components/autofill/core/browser/metrics/suggestions_list_metrics.cc b/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
index 2f421cc..a53b6a4 100644
--- a/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
+++ b/components/autofill/core/browser/metrics/suggestions_list_metrics.cc
@@ -126,11 +126,12 @@
   base::UmaHistogramEnumeration(
       "Autofill.AddressSuggestionOnTyping.AddressFieldTypeUsed",
       field_type_used, FieldType::MAX_VALID_FIELD_TYPE);
+  FieldTypeSet field_types = autofill_trigger_field->Type().GetTypes();
   base::UmaHistogramBoolean(
       "Autofill.AddressSuggestionOnTypingAcceptance.FieldClassication",
       autofill_trigger_field &&
-          autofill_trigger_field->Type().GetStorableType() >
-              FieldType::EMPTY_TYPE);
+          !FieldTypeSet{NO_SERVER_DATA, UNKNOWN_TYPE, EMPTY_TYPE}.contains_all(
+              field_types));
   if (autofill_trigger_field) {
     base::UmaHistogramCounts100(
         "Autofill.AddressSuggestionOnTypingAcceptance.NumberOfCharactersTyped",
diff --git a/components/autofill/core/browser/payments/autofill_save_card_delegate_unittest.cc b/components/autofill/core/browser/payments/autofill_save_card_delegate_unittest.cc
index 625d6566..d0d7e96 100644
--- a/components/autofill/core/browser/payments/autofill_save_card_delegate_unittest.cc
+++ b/components/autofill/core/browser/payments/autofill_save_card_delegate_unittest.cc
@@ -221,13 +221,14 @@
     return;
   }
 
-  CreateDelegate().OnUiUpdatedAndAccepted(
-      /*user_provided_details=*/{.cardholder_name = u"Test"});
+  payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+  details.cardholder_name = u"Test";
+  CreateDelegate().OnUiUpdatedAndAccepted(details);
 
-  EXPECT_THAT(
-      upload_offer_decisions_,
-      testing::Contains(EqualToUploadCallbackArgs(
-          SaveCardOfferUserDecision::kAccepted, {.cardholder_name = u"Test"})));
+  ASSERT_EQ(upload_offer_decisions_.size(), 1u);
+  const auto& [decision, received_details] = upload_offer_decisions_[0];
+  EXPECT_EQ(decision, SaveCardOfferUserDecision::kAccepted);
+  EXPECT_EQ(received_details.cardholder_name, u"Test");
 }
 
 TEST_P(AutofillSaveCardDelegateTest, OnUiUpdatedAndAcceptedLogsUserAction) {
@@ -238,7 +239,8 @@
 
   base::HistogramTester histogram_tester;
 
-  CreateDelegate().OnUiUpdatedAndAccepted(/*user_provided_details=*/{});
+  payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+  CreateDelegate().OnUiUpdatedAndAccepted(details);
 
   histogram_tester.ExpectUniqueSample(kUserActionMetricNameServer,
                                       InfoBarMetric::INFOBAR_ACCEPTED, 1);
diff --git a/components/autofill/core/browser/payments/bnpl_manager.cc b/components/autofill/core/browser/payments/bnpl_manager.cc
index 81960bf2..ada0771b 100644
--- a/components/autofill/core/browser/payments/bnpl_manager.cc
+++ b/components/autofill/core/browser/payments/bnpl_manager.cc
@@ -237,12 +237,21 @@
 void BnplManager::OnIssuerSelected(BnplIssuer selected_issuer) {
   ongoing_flow_state_->issuer = std::move(selected_issuer);
 
-  if (ongoing_flow_state_->issuer.payment_instrument().has_value()) {
+  if (ongoing_flow_state_->issuer.payment_instrument().has_value() &&
+      !AcceptTosActionRequired()) {
     ongoing_flow_state_->instrument_id = base::NumberToString(
         ongoing_flow_state_->issuer.payment_instrument()->instrument_id());
 
     LoadRiskDataForFetchingRedirectUrl();
   } else {
+    GetLegalMessageFromServer();
+  }
+}
+
+void BnplManager::GetLegalMessageFromServer() {
+  if (AcceptTosActionRequired()) {
+    GetDetailsForUpdateBnplPaymentInstrument();
+  } else {
     GetDetailsForCreateBnplPaymentInstrument();
   }
 }
@@ -355,13 +364,14 @@
 void BnplManager::OnRedirectUrlFetched(
     PaymentsAutofillClient::PaymentsRpcResult result,
     const BnplFetchUrlResponseDetails& response) {
-  if (ongoing_flow_state_->issuer.payment_instrument().has_value()) {
-    // If the BNPL issuer selected is linked, the issuer selection dialog must
-    // be showing, so close it.
+  if (ongoing_flow_state_->issuer.payment_instrument().has_value() &&
+      !AcceptTosActionRequired()) {
+    // If the BNPL issuer selected is linked and doesn't require ToS acceptance,
+    // then the issuer selection dialog must be showing, so close it.
     payments_autofill_client().DismissSelectBnplIssuerDialog();
   } else {
-    // If the BNPL issuer selected is not linked, the ToS dialog must be
-    // showing, so close it.
+    // If the BNPL issuer selected is not linked, or is linked but requires ToS
+    // acceptance, then the ToS dialog must be showing, so close it.
     payments_autofill_client().CloseBnplTos();
   }
 
@@ -495,7 +505,11 @@
 
 void BnplManager::OnTosDialogAccepted() {
   if (!ongoing_flow_state_->risk_data.empty()) {
-    CreateBnplPaymentInstrument();
+    if (AcceptTosActionRequired()) {
+      UpdateBnplPaymentInstrument();
+    } else {
+      CreateBnplPaymentInstrument();
+    }
     return;
   }
 
@@ -511,7 +525,11 @@
 void BnplManager::OnRiskDataLoadedAfterTosDialogAcceptance(
     const std::string& risk_data) {
   ongoing_flow_state_->risk_data = risk_data;
-  CreateBnplPaymentInstrument();
+  if (AcceptTosActionRequired()) {
+    UpdateBnplPaymentInstrument();
+  } else {
+    CreateBnplPaymentInstrument();
+  }
 }
 
 void BnplManager::CreateBnplPaymentInstrument() {
@@ -667,4 +685,11 @@
       });
 }
 
+bool BnplManager::AcceptTosActionRequired() const {
+  return ongoing_flow_state_->issuer.payment_instrument().has_value() &&
+         base::Contains(ongoing_flow_state_->issuer.payment_instrument()
+                            ->action_required(),
+                        PaymentInstrument::ActionRequired::kAcceptTos);
+}
+
 }  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/bnpl_manager.h b/components/autofill/core/browser/payments/bnpl_manager.h
index c971e81..4b524b4 100644
--- a/components/autofill/core/browser/payments/bnpl_manager.h
+++ b/components/autofill/core/browser/payments/bnpl_manager.h
@@ -87,6 +87,10 @@
   // 3. The URL being visited is within the BNPL issuer allowlist.
   bool IsEligibleForBnpl() const;
 
+  // Returns true if the issuer for the ongoing flow contains the required
+  // action `PaymentInstrument::ActionRequired::kAcceptTos`.
+  bool AcceptTosActionRequired() const;
+
  private:
   friend class BnplManagerTestApi;
   friend class BnplManagerTest;
@@ -161,6 +165,10 @@
   // or terms of services depending on the issuer.
   void OnIssuerSelected(BnplIssuer selected_issuer);
 
+  // This function makes the appropriate server call to retrieve the ToS legal
+  // message for the issuer.
+  void GetLegalMessageFromServer();
+
   // This function makes the appropriate call to the payments server to get info
   // from the server for creating an instrument for the selected issuer.
   void GetDetailsForCreateBnplPaymentInstrument();
diff --git a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc
index 40299f0..2c72d53 100644
--- a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc
@@ -151,6 +151,11 @@
 
 class BnplManagerTest : public Test {
  public:
+  using GetDetailsForUpdateBnplPaymentInstrumentRequestDetails::
+      GetDetailsForUpdateBnplPaymentInstrumentType::kGetDetailsForAcceptTos;
+  using UpdateBnplPaymentInstrumentRequestDetails::
+      UpdateBnplPaymentInstrumentType::kAcceptTos;
+
   const int64_t kBillingCustomerNumber = 1234;
   const std::string kRiskData = "RISK_DATA";
   const std::string kInstrumentId = "INSTRUMENT_ID";
@@ -421,6 +426,94 @@
       autofill_client_->GetPaymentsAutofillClient()->risk_data_loaded());
 }
 
+// Tests that the user accepting the ToS dialog for a linked issuer where ToS
+// acceptance is required triggers an UpdatePaymentInstrument request with the
+// loaded risk data, if it is present.
+TEST_F(BnplManagerTest,
+       TosDialogAccepted_PrefetchedRiskDataLoaded_TosAcceptanceRequired) {
+  bnpl_manager_->OnDidAcceptBnplSuggestion(/*final_checkout_amount=*/kAmount,
+                                           base::DoNothing());
+  auto* ongoing_flow_state = test_api(*bnpl_manager_).GetOngoingFlowState();
+  const std::string test_context_token = "test_context_token";
+  BnplIssuer issuer = test::GetTestLinkedBnplIssuer(
+      IssuerId::kBnplKlarna,
+      DenseSet<PaymentInstrument::ActionRequired>{
+          PaymentInstrument::ActionRequired::kAcceptTos});
+  ongoing_flow_state->context_token = test_context_token;
+  ongoing_flow_state->issuer = issuer;
+
+  ASSERT_FALSE(ongoing_flow_state->risk_data.empty());
+
+  autofill_client_->GetPaymentsAutofillClient()->set_risk_data_loaded(false);
+
+  EXPECT_CALL(
+      *payments_network_interface_,
+      UpdateBnplPaymentInstrument(/*request_details=*/
+                                  FieldsAre(
+                                      autofill_client_->GetAppLocale(),
+                                      GetBillingCustomerId(
+                                          autofill_client_
+                                              ->GetPaymentsAutofillClient()
+                                              ->GetPaymentsDataManager()),
+                                      autofill::ConvertToBnplIssuerIdString(
+                                          issuer.issuer_id()),
+                                      /*instrument_id=*/12345,
+                                      test_context_token, /*risk_data=*/_,
+                                      /*type=*/kAcceptTos),
+                                  /*callback=*/_));
+
+  test_api(*bnpl_manager_).OnTosDialogAccepted();
+
+  EXPECT_FALSE(ongoing_flow_state->risk_data.empty());
+
+  // Since risk data was cached, it was directly used, thus loading risk data
+  // was skipped.
+  EXPECT_FALSE(
+      autofill_client_->GetPaymentsAutofillClient()->risk_data_loaded());
+}
+
+// Tests that the the user accepting the ToS dialog for a linked issuer where
+// ToS acceptance is required triggers an UpdatePaymentInstrument request and
+// loads risk data after ToS dialog acceptance if it was not already loaded.
+TEST_F(BnplManagerTest,
+       TosDialogAccepted_PrefetchedRiskDataNotLoaded_TosAcceptanceRequired) {
+  bnpl_manager_->OnDidAcceptBnplSuggestion(/*final_checkout_amount=*/1000000,
+                                           base::DoNothing());
+  auto* ongoing_flow_state = test_api(*bnpl_manager_).GetOngoingFlowState();
+  const std::string test_context_token = "test_context_token";
+  BnplIssuer issuer = test::GetTestLinkedBnplIssuer(
+      IssuerId::kBnplKlarna,
+      DenseSet<PaymentInstrument::ActionRequired>{
+          PaymentInstrument::ActionRequired::kAcceptTos});
+  ongoing_flow_state->context_token = test_context_token;
+  ongoing_flow_state->issuer = issuer;
+  ongoing_flow_state->risk_data.clear();
+
+  ASSERT_TRUE(ongoing_flow_state->risk_data.empty());
+
+  EXPECT_CALL(
+      *payments_network_interface_,
+      UpdateBnplPaymentInstrument(/*request_details=*/
+                                  FieldsAre(
+                                      autofill_client_->GetAppLocale(),
+                                      GetBillingCustomerId(
+                                          autofill_client_
+                                              ->GetPaymentsAutofillClient()
+                                              ->GetPaymentsDataManager()),
+                                      autofill::ConvertToBnplIssuerIdString(
+                                          issuer.issuer_id()),
+                                      issuer.payment_instrument()
+                                          ->instrument_id(),
+                                      test_context_token,
+                                      /*risk_data=*/_, /*type=*/kAcceptTos),
+                                  /*callback=*/_));
+  test_api(*bnpl_manager_).OnTosDialogAccepted();
+
+  EXPECT_FALSE(ongoing_flow_state->risk_data.empty());
+  EXPECT_TRUE(
+      autofill_client_->GetPaymentsAutofillClient()->risk_data_loaded());
+}
+
 // Tests that FetchVcnDetails calls the payments network interface with the
 // request details filled out correctly, and verifies that the VCN is correctly
 // filled and the state of BnplManager is reset.
@@ -870,6 +963,39 @@
             unlinked_issuer);
 }
 
+// Tests that `OnIssuerSelected()` calls with a linked issuer where ToS
+// acceptance is required will call the payments network interface with the
+// request details filled out correctly.
+TEST_F(
+    BnplManagerTest,
+    OnIssuerSelected_CallsGetDetailsForUpdateBnplPaymentInstrument_TosAcceptanceRequired) {
+  bnpl_manager_->OnDidAcceptBnplSuggestion(kAmount, base::DoNothing());
+
+  ASSERT_EQ(test_api(*bnpl_manager_).GetOngoingFlowState()->app_locale,
+            kAppLocale);
+  ASSERT_EQ(
+      test_api(*bnpl_manager_).GetOngoingFlowState()->billing_customer_number,
+      kBillingCustomerNumber);
+
+  BnplIssuer issuer = test::GetTestLinkedBnplIssuer(
+      IssuerId::kBnplKlarna,
+      DenseSet<PaymentInstrument::ActionRequired>{
+          PaymentInstrument::ActionRequired::kAcceptTos});
+
+  EXPECT_CALL(*payments_network_interface_,
+              GetDetailsForUpdateBnplPaymentInstrument(
+                  /*request_details=*/
+                  FieldsAre(kAppLocale, kBillingCustomerNumber,
+                            issuer.payment_instrument()->instrument_id(),
+                            /*type=*/kGetDetailsForAcceptTos),
+                  /*callback=*/_))
+      .Times(1);
+
+  OnIssuerSelected(issuer);
+
+  EXPECT_EQ(test_api(*bnpl_manager_).GetOngoingFlowState()->issuer, issuer);
+}
+
 // Tests that `OnDidGetLegalMessageFromServer` set the BNPL manager state if the
 // request has completed successfully, and shows the ToS dialog. This test also
 // ensures the ToS dialog is closed after receiving a redirect URL for an
@@ -1008,16 +1134,13 @@
   BnplIssuer issuer = test::GetTestLinkedBnplIssuer();
   test_api(*bnpl_manager_).GetOngoingFlowState()->issuer = issuer;
 
-  EXPECT_CALL(
-      *payments_network_interface_,
-      GetDetailsForUpdateBnplPaymentInstrument(
-          /*request_details=*/
-          FieldsAre(kAppLocale, kBillingCustomerNumber,
-                    issuer.payment_instrument()->instrument_id(),
-                    GetDetailsForUpdateBnplPaymentInstrumentRequestDetails::
-                        GetDetailsForUpdateBnplPaymentInstrumentType::
-                            kGetDetailsForAcceptTos),
-          /*callback=*/_));
+  EXPECT_CALL(*payments_network_interface_,
+              GetDetailsForUpdateBnplPaymentInstrument(
+                  /*request_details=*/
+                  FieldsAre(kAppLocale, kBillingCustomerNumber,
+                            issuer.payment_instrument()->instrument_id(),
+                            /*type=*/kGetDetailsForAcceptTos),
+                  /*callback=*/_));
 
   test_api(*bnpl_manager_).GetDetailsForUpdateBnplPaymentInstrument();
 }
@@ -1038,9 +1161,7 @@
           FieldsAre(kAppLocale, kBillingCustomerNumber,
                     autofill::ConvertToBnplIssuerIdString(issuer.issuer_id()),
                     issuer.payment_instrument()->instrument_id(), kContextToken,
-                    kRiskData,
-                    UpdateBnplPaymentInstrumentRequestDetails::
-                        UpdateBnplPaymentInstrumentType::kAcceptTos),
+                    kRiskData, /*type=*/kAcceptTos),
           /*callback=*/_));
 
   test_api(*bnpl_manager_).UpdateBnplPaymentInstrument();
@@ -1603,6 +1724,43 @@
   EXPECT_EQ(test_api(*bnpl_manager_).GetOngoingFlowState(), nullptr);
 }
 
+// Tests that when UpdateBnplPaymentInstrument fails with an error the error
+// dialog is shown and the flow is reset.
+TEST_F(BnplManagerTest, UpdateBnplPaymentInstrument_Failure) {
+  bnpl_manager_->OnDidAcceptBnplSuggestion(kAmount, base::DoNothing());
+  auto* ongoing_flow_state = test_api(*bnpl_manager_).GetOngoingFlowState();
+  ongoing_flow_state->app_locale = kAppLocale;
+  ongoing_flow_state->billing_customer_number = kBillingCustomerNumber;
+  ongoing_flow_state->context_token = kContextToken;
+  ongoing_flow_state->issuer = test::GetTestLinkedBnplIssuer(
+      IssuerId::kBnplKlarna,
+      DenseSet<PaymentInstrument::ActionRequired>{
+          PaymentInstrument::ActionRequired::kAcceptTos});
+  ongoing_flow_state->risk_data = kRiskData;
+
+  EXPECT_CALL(
+      *payments_network_interface_,
+      UpdateBnplPaymentInstrument(
+          FieldsAre(
+              kAppLocale, kBillingCustomerNumber,
+              autofill::ConvertToBnplIssuerIdString(
+                  ongoing_flow_state->issuer.issuer_id()),
+              ongoing_flow_state->issuer.payment_instrument()->instrument_id(),
+              kContextToken, kRiskData,
+              /*type=*/kAcceptTos),
+          _))
+      .WillOnce(base::test::RunOnceCallback<1>(
+          PaymentsAutofillClient::PaymentsRpcResult::kPermanentFailure));
+  EXPECT_CALL(GetPaymentsAutofillClient(), CloseBnplTos);
+
+  test_api(*bnpl_manager_).UpdateBnplPaymentInstrument();
+
+  EXPECT_TRUE(autofill_client_->GetPaymentsAutofillClient()
+                  ->autofill_error_dialog_shown());
+
+  EXPECT_EQ(test_api(*bnpl_manager_).GetOngoingFlowState(), nullptr);
+}
+
 // Tests the sorting logic of `GetSortedBnplIssuerContext` for BNPL Issuers
 // based on their linked status and eligibility. The expected order is:
 // 1. Linked & Eligible
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index da6a75c..2813981 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -357,7 +357,7 @@
         break;
       }
     } else if (is_valid_cvc &&
-               field->Type().GetStorableType() == UNKNOWN_TYPE) {
+               field->Type().GetTypes().contains(UNKNOWN_TYPE)) {
       found_cvc_value_in_non_cvc_field_ = true;
     }
   }
@@ -1347,16 +1347,18 @@
     const std::u16string& cardholder_name) {
   DCHECK(should_request_name_from_user_);
 
-  OnUserDidAcceptUploadHelper({cardholder_name,
-                               /*expiration_date_month=*/std::u16string(),
-                               /*expiration_date_year=*/std::u16string()});
+  payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+  details.cardholder_name = cardholder_name;
+  OnUserDidAcceptUploadHelper(details);
 }
 
 void CreditCardSaveManager::OnUserDidAcceptExpirationDateFixFlow(
     const std::u16string& month,
     const std::u16string& year) {
-  OnUserDidAcceptUploadHelper(
-      {/*cardholder_name=*/std::u16string(), month, year});
+  payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+  details.expiration_date_month = month;
+  details.expiration_date_year = year;
+  OnUserDidAcceptUploadHelper(details);
 }
 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
 
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index f37d9a3a4..7f52889 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -1993,8 +1993,9 @@
 
   // Set a cardholder name, to be used as an user provided name for cardholder
   // name fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2212,8 +2213,9 @@
 
   // Set a cardholder name. Represents an user provided name for cardholder name
   // fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2582,8 +2584,9 @@
 
   // Set a cardholder name, to be used as an user provided name for cardholder
   // name fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2647,8 +2650,9 @@
 
   // Set a cardholder name, to be used as an user provided name for cardholder
   // name fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2720,8 +2724,9 @@
 
   // Set a cardholder name, to be used as an user provided name for cardholder
   // name fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2829,8 +2834,9 @@
 
   // Set a cardholder name. Represents user provided name during cardholder name
   // fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -2887,8 +2893,9 @@
 
   // Set a cardholder name. Represents user provided name during cardholder name
   // fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3172,8 +3179,8 @@
 
   // Set a cardholder name. Represents user provided name for cardholder name
   // fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
 
   SetCardDetailsForFixFlow(user_provided_details);
 
@@ -3246,8 +3253,9 @@
 
   // Set a cardholder name, to be used as an user provided name in the save card
   // dialog after form is submitted.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3306,9 +3314,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry date. Represents user provided expiry date for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3434,9 +3442,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry date. Represents user provided expiry date for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3527,10 +3535,10 @@
   // Set a valid cardholder name and expiry date. Represents user provided
   // cardholder name and expiry date in the save card dialog after form is
   // submitted.
-  UserProvidedCardDetails user_provided_details = {
-      .cardholder_name = u"Chrome User",
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3636,9 +3644,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry date. Represents user provided expiry date for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3704,9 +3712,9 @@
 
   // Set a valid expiry month. Represents user provided expiry date for fix
   // flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(FiveYearsFromNow())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(FiveYearsFromNow());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3772,9 +3780,10 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry year. Represents user provided expiry year for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(FiveMonthsFromNow()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month =
+      ASCIIToUTF16(FiveMonthsFromNow());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3838,9 +3847,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry date. Represents user provided expiry date for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -3909,9 +3918,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a valid expiry date. Represents user provided expiry date for fix flow.
-  UserProvidedCardDetails user_provided_details = {
-      .expiration_date_month = ASCIIToUTF16(test::NextMonth()),
-      .expiration_date_year = ASCIIToUTF16(test::NextYear())};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.expiration_date_month = ASCIIToUTF16(test::NextMonth());
+  user_provided_details.expiration_date_year = ASCIIToUTF16(test::NextYear());
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -4908,8 +4917,9 @@
 
   // Set a cardholder name, to be used as an user provided name for cardholder
   // name fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -4977,8 +4987,9 @@
 
   // Set a cardholder name. Represents an user provided name for cardholder name
   // fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
 
   FormSubmitted(credit_card_form);
@@ -5155,8 +5166,9 @@
   EXPECT_CALL(payments_client(), ShowSaveCreditCardLocally).Times(0);
 
   // Set a cardholder name. Represents an user provided name for fix flow.
-  UserProvidedCardDetails user_provided_details = {.cardholder_name =
-                                                       u"Chrome User"};
+  UserProvidedCardDetails user_provided_details;
+  user_provided_details.cardholder_name = u"Chrome User";
+
   SetCardDetailsForFixFlow(user_provided_details);
   FormSubmitted(credit_card_form);
 
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.cc b/components/autofill/core/browser/payments/payments_autofill_client.cc
index 7b85497..48ac265 100644
--- a/components/autofill/core/browser/payments/payments_autofill_client.cc
+++ b/components/autofill/core/browser/payments/payments_autofill_client.cc
@@ -29,6 +29,26 @@
 
 PaymentsAutofillClient::~PaymentsAutofillClient() = default;
 
+PaymentsAutofillClient::UserProvidedCardDetails::UserProvidedCardDetails() =
+    default;
+
+PaymentsAutofillClient::UserProvidedCardDetails::UserProvidedCardDetails(
+    const UserProvidedCardDetails&) = default;
+
+PaymentsAutofillClient::UserProvidedCardDetails&
+PaymentsAutofillClient::UserProvidedCardDetails::operator=(
+    const UserProvidedCardDetails&) = default;
+
+PaymentsAutofillClient::UserProvidedCardDetails::UserProvidedCardDetails(
+    UserProvidedCardDetails&&) = default;
+
+PaymentsAutofillClient::UserProvidedCardDetails&
+PaymentsAutofillClient::UserProvidedCardDetails::operator=(
+    UserProvidedCardDetails&&) = default;
+
+PaymentsAutofillClient::UserProvidedCardDetails::~UserProvidedCardDetails() =
+    default;
+
 #if BUILDFLAG(IS_ANDROID)
 AutofillSaveCardBottomSheetBridge*
 PaymentsAutofillClient::GetOrCreateAutofillSaveCardBottomSheetBridge() {
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.h b/components/autofill/core/browser/payments/payments_autofill_client.h
index f09da85..eb8e8c2 100644
--- a/components/autofill/core/browser/payments/payments_autofill_client.h
+++ b/components/autofill/core/browser/payments/payments_autofill_client.h
@@ -209,12 +209,20 @@
     kIgnored,
   };
 
-  // Used for explicitly requesting the user to enter/confirm cardholder name,
-  // expiration date month and year.
+  // Carries card details that were explicitly provided or confirmed by the
+  // user in a save/update UI. This can include data from a fix flow
+  // (e.g., corrected name) or optional data from an initial save (e.g., CVC).
   struct UserProvidedCardDetails {
+    UserProvidedCardDetails();
+    UserProvidedCardDetails(const UserProvidedCardDetails&);
+    UserProvidedCardDetails& operator=(const UserProvidedCardDetails&);
+    UserProvidedCardDetails(UserProvidedCardDetails&&);
+    UserProvidedCardDetails& operator=(UserProvidedCardDetails&&);
+    ~UserProvidedCardDetails();
     std::u16string cardholder_name;
     std::u16string expiration_date_month;
     std::u16string expiration_date_year;
+    std::u16string cvc;
   };
 
   enum class CardSaveAndFillDialogUserDecision {
diff --git a/components/autofill/core/browser/single_field_fillers/single_field_fill_router.cc b/components/autofill/core/browser/single_field_fillers/single_field_fill_router.cc
index 2348c58..71dbe30 100644
--- a/components/autofill/core/browser/single_field_fillers/single_field_fill_router.cc
+++ b/components/autofill/core/browser/single_field_fillers/single_field_fill_router.cc
@@ -39,11 +39,11 @@
     // them to autocomplete functionality by default.
     bool skip_because_promo_code =
         merchant_promo_code_manager_ && form_structure &&
-        form_structure->field(i)->Type().GetStorableType() ==
-            MERCHANT_PROMO_CODE;
+        form_structure->field(i)->Type().GetTypes().contains(
+            MERCHANT_PROMO_CODE);
     bool skip_because_iban =
         iban_manager_ && form_structure &&
-        form_structure->field(i)->Type().GetStorableType() == IBAN_VALUE;
+        form_structure->field(i)->Type().GetTypes().contains(IBAN_VALUE);
     if (!skip_because_iban && !skip_because_promo_code) {
       autocomplete_fields.push_back(form.fields()[i]);
     }
diff --git a/components/autofill/core/browser/suggestions/autofill_ai/autofill_ai_suggestion_generator_unittests.cc b/components/autofill/core/browser/suggestions/autofill_ai/autofill_ai_suggestion_generator_unittests.cc
index f007ecc..17028076 100644
--- a/components/autofill/core/browser/suggestions/autofill_ai/autofill_ai_suggestion_generator_unittests.cc
+++ b/components/autofill/core/browser/suggestions/autofill_ai/autofill_ai_suggestion_generator_unittests.cc
@@ -150,8 +150,8 @@
     if (!attribute) {
       return std::nullopt;
     }
-    return attribute->GetInfo(field.Type().GetStorableType(), kAppLocaleUS,
-                              field.format_string());
+    return attribute->GetInfo(field.Type().GetAutofillAiType(entity.type()),
+                              kAppLocaleUS, field.format_string());
   }
 
   std::vector<Suggestion> CreateAutofillAiFillingSuggestions(
diff --git a/components/autofill/core/browser/suggestions/payments/iban_suggestion_generator.cc b/components/autofill/core/browser/suggestions/payments/iban_suggestion_generator.cc
index 43ce001b..89b1798 100644
--- a/components/autofill/core/browser/suggestions/payments/iban_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/payments/iban_suggestion_generator.cc
@@ -69,7 +69,7 @@
                        std::vector<SuggestionGenerator::SuggestionData>>)>
         callback) {
   // The field is eligible only if it's focused on an IBAN field.
-  if (!field || field->Type().GetStorableType() != IBAN_VALUE) {
+  if (!field || !field->Type().GetTypes().contains(IBAN_VALUE)) {
     callback({FillingProduct::kIban, {}});
     return;
   }
diff --git a/components/autofill/core/browser/suggestions/payments/merchant_promo_code_suggestion_generator.cc b/components/autofill/core/browser/suggestions/payments/merchant_promo_code_suggestion_generator.cc
index 6d9a45ef..6a7dc34b 100644
--- a/components/autofill/core/browser/suggestions/payments/merchant_promo_code_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/payments/merchant_promo_code_suggestion_generator.cc
@@ -64,7 +64,7 @@
         callback) {
   // The field is eligible only if it's focused on a merchant promo code.
   if (!form || !field ||
-      field->Type().GetStorableType() != MERCHANT_PROMO_CODE) {
+      !field->Type().GetTypes().contains(MERCHANT_PROMO_CODE)) {
     callback({FillingProduct::kMerchantPromoCode, {}});
     return;
   }
diff --git a/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc b/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc
index 50ead8d0..cb97823 100644
--- a/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc
+++ b/components/autofill/core/browser/test_utils/autofill_form_test_utils.cc
@@ -12,6 +12,8 @@
 
 namespace autofill::test {
 
+using ::testing::ElementsAre;
+
 testing::Message DescribeFormData(const FormData& form_data) {
   testing::Message result;
   result << "Form contains " << form_data.fields().size() << " fields:\n";
@@ -283,8 +285,9 @@
     }
     for (size_t i = 0;
          i < test_case.expected_field_types.expected_overall_type.size(); i++) {
-      EXPECT_EQ(test_case.expected_field_types.expected_overall_type[i],
-                form_structure->field(i)->Type().GetStorableType());
+      EXPECT_THAT(
+          form_structure->field(i)->Type().GetTypes(),
+          ElementsAre(test_case.expected_field_types.expected_overall_type[i]));
     }
   }
 }
diff --git a/components/autofill/core/browser/test_utils/autofill_test_utils.cc b/components/autofill/core/browser/test_utils/autofill_test_utils.cc
index 717cddb..46a1bbc3 100644
--- a/components/autofill/core/browser/test_utils/autofill_test_utils.cc
+++ b/components/autofill/core/browser/test_utils/autofill_test_utils.cc
@@ -1338,7 +1338,7 @@
 
 BnplIssuer GetTestLinkedBnplIssuer(
     autofill::BnplIssuer::IssuerId issuer_id,
-    DenseSet<PaymentInstrument::ActionRequired> action_required) {
+    DenseSet<PaymentInstrument::ActionRequired> actions_required) {
   std::vector<BnplIssuer::EligiblePriceRange> eligible_price_ranges;
   // Currency: USD, price lower bound: $50, price upper bound: $200.
   eligible_price_ranges.emplace_back(/*currency=*/"USD",
@@ -1346,7 +1346,7 @@
                                      /*price_upper_bound=*/200'000'000);
   return BnplIssuer(
       /*instrument_id=*/12345, issuer_id, std::move(eligible_price_ranges),
-      std::move(action_required));
+      std::move(actions_required));
 }
 
 BnplIssuer GetTestUnlinkedBnplIssuer() {
diff --git a/components/autofill/core/browser/test_utils/autofill_test_utils.h b/components/autofill/core/browser/test_utils/autofill_test_utils.h
index 3a0a5557..0051eb8 100644
--- a/components/autofill/core/browser/test_utils/autofill_test_utils.h
+++ b/components/autofill/core/browser/test_utils/autofill_test_utils.h
@@ -511,7 +511,7 @@
 BnplIssuer GetTestLinkedBnplIssuer(
     autofill::BnplIssuer::IssuerId issuer_id =
         autofill::BnplIssuer::IssuerId::kBnplAffirm,
-    DenseSet<PaymentInstrument::ActionRequired> action_required =
+    DenseSet<PaymentInstrument::ActionRequired> actions_required =
         DenseSet<PaymentInstrument::ActionRequired>());
 
 // Returns an unlinked BNPL issuer with fake data.
diff --git a/components/autofill/core/browser/ui/autofill_external_delegate.cc b/components/autofill/core/browser/ui/autofill_external_delegate.cc
index f5f6f19..d59498b4 100644
--- a/components/autofill/core/browser/ui/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/ui/autofill_external_delegate.cc
@@ -1260,7 +1260,8 @@
         const AutofillField* autofill_trigger_field = GetQueriedAutofillField();
         const bool triggered_on_email_field =
             autofill_trigger_field &&
-            autofill_trigger_field->Type().group() == FieldTypeGroup::kEmail;
+            autofill_trigger_field->Type().GetGroups().contains(
+                FieldTypeGroup::kEmail);
         // Email suggestions don't have a separate suggestion type. Check that
         // the suggestions are triggered on an email field and that the popup
         // contains a plus address filling suggestion as well.
diff --git a/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc b/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc
index 3af2773..233072e5 100644
--- a/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc
@@ -366,16 +366,40 @@
                 {attributes::kEntityGuid, attributes::kAttributeType,
                  attributes::kFieldType, attributes::kValueEncrypted,
                  attributes::kVerificationStatus});
+
+  // LINT.IfChange(DecryptionStatus)
+  enum class DecryptionStatus {
+    // Decryption was successful.
+    kSuccess = 0,
+    // Temporary error (e.g. The decryption system was not available).
+    kTemporaryFailure = 1,
+    // The decryption key was lost or the data to be decrypted was corrupt.
+    kPermanentFailure = 2,
+    kMaxValue = kPermanentFailure,
+  };
+  // LINT.ThenChange(//tools/metrics/histograms/metadata/autofill/enums.xml:AutofillAiDecryptStatus)
+
   while (s.Step()) {
     base::Uuid entity_guid = base::Uuid::ParseLowercase(s.ColumnStringView(0));
     std::string attribute_type_name = s.ColumnString(1);
     std::underlying_type_t<FieldType> underlying_field_type = s.ColumnInt(2);
     std::u16string decrypted_value;
-    if (!encryptor()->DecryptString16(s.ColumnString(3), &decrypted_value)) {
-      base::UmaHistogramBoolean("Autofill.Ai.EntityTable.DecryptStatus", false);
+    os_crypt_async::Encryptor::DecryptFlags flag;
+    bool decryption_result = encryptor()->DecryptString16(
+        s.ColumnString(3), &decrypted_value, &flag);
+    base::UmaHistogramBoolean("Autofill.Ai.EntityTable.DecryptStatus",
+                              decryption_result);
+    DecryptionStatus decryption_status = DecryptionStatus::kSuccess;
+    if (!decryption_result) {
+      decryption_status = flag.temporarily_unavailable
+                              ? DecryptionStatus::kTemporaryFailure
+                              : DecryptionStatus::kPermanentFailure;
+    }
+    base::UmaHistogramEnumeration("Autofill.Ai.EntityTable.DecryptStatus2",
+                                  decryption_status);
+    if (!decryption_result) {
       continue;
     }
-    base::UmaHistogramBoolean("Autofill.Ai.EntityTable.DecryptStatus", true);
     std::underlying_type_t<VerificationStatus> underlying_verification_status =
         s.ColumnInt(4);
     attribute_records[std::move(entity_guid)][std::move(attribute_type_name)]
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index c3f15b0..90e9861d 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -1047,14 +1047,17 @@
   </message>
 
   <!-- Buy now pay later related strings -->
-  <message name="IDS_AUTOFILL_BNPL_PAY_LATER_OPTIONS_TEXT" desc="Main text for the Buy Now Pay Later option in the autofill credit card popup and in the settings page BNPL toggle. If the option is selected, a pop up will be shown to allow users choose a Buy Now Pay Later issuer.">
+  <message name="IDS_AUTOFILL_BNPL_PAY_LATER_OPTIONS_TEXT" desc="Main text for the Buy Now Pay Later option in the autofill credit card popup. If the option is selected, a pop up will be shown to allow users choose a Buy Now Pay Later issuer.">
     Pay later options
   </message>
   <message name="IDS_AUTOFILL_BNPL_CREDIT_CARD_SUGGESTION_LABEL" desc="One line label shows the minimum qualifying amount for the Buy Now Pay Later option in the autofill credit card popup. If the option is selected, a pop up will be shown to allow users choose a Buy Now Pay Later issuer.">
     Available for purchases over <ph name="RANGE_MINIMUM">$1<ex>$35</ex></ph>
   </message>
+  <message name="IDS_AUTOFILL_BNPL_SETTINGS_LABEL" desc="Label for the Buy Now Pay Later preference in the payments settings page. When enabled, users can checkout with external BNPL issuers using a pay-over-time payment option.">
+    Pay later
+  </message>
   <message name="IDS_AUTOFILL_BNPL_SETTINGS_SUBLABEL" desc="Sublabel for the Buy Now Pay Later preference in the payments settings page, including a hyperlink to learn more about pay later options. When enabled, users can checkout with external BNPL issuers using a Buy Now Pay Later option.">
-    Show <ph name="PAY_LATER_OPTIONS_HELP_LINK_BEGIN">&lt;a href="$1" aria-description="$2"&gt;</ph>pay later options<ph name="PAY_LATER_OPTIONS_HELP_LINK_END">&lt;/a&gt;</ph> at checkout
+    Show <ph name="PAY_LATER_OPTIONS_HELP_LINK_BEGIN">&lt;a href="$1" aria-description="$2"&gt;</ph>pay later<ph name="PAY_LATER_OPTIONS_HELP_LINK_END">&lt;/a&gt;</ph> options at checkout
   </message>
   <message name="IDS_AUTOFILL_BNPL_AFFIRM" desc="Name of Buy Now Pay Later provider Affirm.">
     Affirm
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_LABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_LABEL.png.sha1
new file mode 100644
index 0000000..f66bc45
--- /dev/null
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_LABEL.png.sha1
@@ -0,0 +1 @@
+25ac14eb22be8d98bedf727e6614e62c2fb4a560
\ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_SUBLABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_SUBLABEL.png.sha1
index 2f7a34b..b0c765e 100644
--- a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_SUBLABEL.png.sha1
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_BNPL_SETTINGS_SUBLABEL.png.sha1
@@ -1 +1 @@
-39c7c780d47f6955cac6efc86e34bb5be7c54bba
\ No newline at end of file
+d82dbc6a19013106f1ea226acda23bc0a01985d1
\ No newline at end of file
diff --git a/components/browser_ui/README b/components/browser_ui/README
index 848cef87..1366e08 100644
--- a/components/browser_ui/README
+++ b/components/browser_ui/README
@@ -1,3 +1,3 @@
 The browser_ui component consists of modularized build targets for common
 UI elements that are useful for building a browser. Currently it contains
-Android code that is used by WebLayer and Chrome.
+Android code that is used by Chrome.
diff --git a/components/component_updater/android/component_loader_policy.h b/components/component_updater/android/component_loader_policy.h
index fbf9b466..c127f313 100644
--- a/components/component_updater/android/component_loader_policy.h
+++ b/components/component_updater/android/component_loader_policy.h
@@ -55,7 +55,7 @@
 // Components should use `AndroidComponentLoaderPolicy` by defining a class that
 // implements the members of `ComponentLoaderPolicy`, and then registering a
 // `AndroidComponentLoaderPolicy` that has been constructed with an instance of
-// that class in an instance of embedded WebView or WebLayer with the Java
+// that class in an instance of embedded WebView with the Java
 // AndroidComponentLoaderPolicy. The `AndroidComponentLoaderPolicy` will fetch
 // the components files from the Android `ComponentsProviderService` and invoke
 // the callbacks defined in this class.
diff --git a/components/component_updater/android/java/src/org/chromium/components/component_updater/EmbeddedComponentLoader.java b/components/component_updater/android/java/src/org/chromium/components/component_updater/EmbeddedComponentLoader.java
index 9bd214c8..b67d777d 100644
--- a/components/component_updater/android/java/src/org/chromium/components/component_updater/EmbeddedComponentLoader.java
+++ b/components/component_updater/android/java/src/org/chromium/components/component_updater/EmbeddedComponentLoader.java
@@ -29,8 +29,8 @@
 import java.util.Set;
 
 /**
- * ComponentLoader that is used in embedded WebViews/WebLayers. It implements a ServiceConnection to
- * connect to the provider service to fetch components files.
+ * ComponentLoader that is used in embedded WebViews. It implements a ServiceConnection to connect
+ * to the provider service to fetch components files.
  */
 @NullMarked
 public class EmbeddedComponentLoader implements ServiceConnection {
diff --git a/components/dom_distiller/core/javascript/dom_distiller_viewer.js b/components/dom_distiller/core/javascript/dom_distiller_viewer.js
index f08701b..d9babc0 100644
--- a/components/dom_distiller/core/javascript/dom_distiller_viewer.js
+++ b/components/dom_distiller/core/javascript/dom_distiller_viewer.js
@@ -22,6 +22,50 @@
   div.innerHTML = html;
   $('content').appendChild(div);
   fillYouTubePlaceholders();
+  sanitizeLinks();
+}
+
+/**
+ * Iterates through all links on the page. If a link does not have
+ * an http or https scheme, it removes the link element from the DOM.
+ */
+function sanitizeLinks() {
+  const allLinks = document.querySelectorAll('a');
+
+  allLinks.forEach(linkElement => {
+    const href = linkElement.getAttribute('href');
+
+    if (href) {
+      let isProtocolInvalid = false;
+      // Use a try-catch block to handle malformed URLs gracefully.
+      try {
+        const url = new URL(href, window.location.href);
+        if (url.protocol !== 'http:' && url.protocol !== 'https:') {
+          isProtocolInvalid = true;
+        }
+      } catch (error) {
+        // A malformed URL is considered invalid.
+        isProtocolInvalid = true;
+      }
+
+      if (isProtocolInvalid) {
+        // If the protocol is invalid or the URL is malformed, unwrap the link.
+        const parent = linkElement.parentNode;
+
+        if (parent) {
+          // Iterate through the link's child nodes and move them to the parent.
+          // Using a spread operator to create a copy, as childNodes is a live
+          // list.
+          [...linkElement.childNodes].forEach(node => {
+            parent.insertBefore(node, linkElement);
+          });
+
+          // Remove the original anchor tag.
+          linkElement.remove();
+        }
+      }
+    }
+  });
 }
 
 function fillYouTubePlaceholders() {
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index 6416cad..4934bf14 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -431,6 +431,26 @@
       blink::mojom::PointerLockResult::kSuccess);
 }
 
+void WebContentsDelegateAndroid::RequestKeyboardLock(WebContents* web_contents,
+                                                     bool esc_key_locked) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
+  if (obj.is_null()) {
+    return;
+  }
+  Java_WebContentsDelegateAndroid_requestKeyboardLock(env, obj, esc_key_locked);
+}
+
+void WebContentsDelegateAndroid::CancelKeyboardLockRequest(
+    WebContents* web_contents) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
+  if (obj.is_null()) {
+    return;
+  }
+  Java_WebContentsDelegateAndroid_cancelKeyboardLockRequest(env, obj);
+}
+
 bool WebContentsDelegateAndroid::IsFullscreenForTabOrPending(
     const WebContents* web_contents) {
   JNIEnv* env = AttachCurrentThread();
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.h b/components/embedder_support/android/delegate/web_contents_delegate_android.h
index 7a8cdc2..13afd2d 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.h
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.h
@@ -113,6 +113,9 @@
   void RequestPointerLock(content::WebContents* web_contents,
                           bool user_gesture,
                           bool last_unlocked_by_target) override;
+  void RequestKeyboardLock(content::WebContents* web_contents,
+                           bool esc_key_locked) override;
+  void CancelKeyboardLockRequest(content::WebContents* web_contents) override;
   void OnDidBlockNavigation(
       content::WebContents* web_contents,
       const GURL& blocked_url,
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/WebContentsDelegateAndroid.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/WebContentsDelegateAndroid.java
index b7e2ad5..f635236 100644
--- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/WebContentsDelegateAndroid.java
+++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/WebContentsDelegateAndroid.java
@@ -139,8 +139,15 @@
         return false;
     }
 
+    @CalledByNative
+    public void requestKeyboardLock(boolean escKeyLocked) {}
+
+    @CalledByNative
+    public void cancelKeyboardLockRequest() {}
+
     /**
      * Called when BrowserMediaPlayerManager wants to load a media resource.
+     *
      * @param url the URL of media resource to load.
      * @return true to prevent the resource from being loaded.
      */
diff --git a/components/enterprise/connectors/core/content_area_user_provider.cc b/components/enterprise/connectors/core/content_area_user_provider.cc
index cc81b430..d831e24 100644
--- a/components/enterprise/connectors/core/content_area_user_provider.cc
+++ b/components/enterprise/connectors/core/content_area_user_provider.cc
@@ -19,27 +19,33 @@
 
 namespace {
 
-bool IncludeContentAreaAccountEmail(const GURL& url) {
+const std::set<std::string_view>& TabWorkspaceDomains() {
+  static const std::set<std::string_view> kDomains = {
+      "mail.google.com",        "meet.google.com",
+      "calendar.google.com",    "drive.google.com",
+      "docs.google.com",        "sites.google.com",
+      "keep.google.com",        "script.google.com",
+      "cloudsearch.google.com", "console.cloud.google.com",
+      "datastudio.google.com",
+  };
+  return kDomains;
+}
+
+const std::set<std::string_view>& FrameWorkspaceDomains() {
+  static const std::set<std::string_view> kDomains = {
+      "ogs.google.com",
+  };
+  return kDomains;
+}
+
+bool IncludeContentAreaAccountEmail(
+    const GURL& url,
+    const std::set<std::string_view>& allowed_domains) {
   if (!base::FeatureList::IsEnabled(kEnterpriseActiveUserDetection)) {
     return false;
   }
 
-  static constexpr auto kWorkspaceDomains =
-      base::MakeFixedFlatSet<std::string_view>({
-          "mail.google.com",
-          "meet.google.com",
-          "calendar.google.com",
-          "drive.google.com",
-          "docs.google.com",
-          "sites.google.com",
-          "keep.google.com",
-          "script.google.com",
-          "cloudsearch.google.com",
-          "console.cloud.google.com",
-          "datastudio.google.com",
-      });
-
-  for (const auto& domain : kWorkspaceDomains) {
+  for (const auto& domain : allowed_domains) {
     if (url.DomainIs(domain)) {
       return true;
     }
@@ -64,15 +70,7 @@
   return std::nullopt;
 }
 
-}  // namespace
-
-// static
-std::string GetActiveContentAreaUser(signin::IdentityManager* im,
-                                     const GURL& url) {
-  if (!IncludeContentAreaAccountEmail(url)) {
-    return "";
-  }
-
+std::string GetEmailFromUrl(signin::IdentityManager* im, const GURL& url) {
   if (!im) {
     return "";
   }
@@ -83,12 +81,39 @@
     return accounts.GetAllAccounts()[0].email;
   }
 
-  size_t user_index = GetUserIndex(url).value_or(0);
-  if (user_index >= accounts.GetAllAccounts().size()) {
+  std::optional<size_t> user_index = GetUserIndex(url);
+  if (!user_index.has_value()) {
     return "";
   }
 
-  return accounts.GetAllAccounts()[user_index].email;
+  if (*user_index >= accounts.GetAllAccounts().size()) {
+    return "";
+  }
+
+  return accounts.GetAllAccounts()[*user_index].email;
+}
+
+}  // namespace
+
+// static
+std::string GetActiveContentAreaUser(signin::IdentityManager* im,
+                                     const GURL& tab_url) {
+  if (!IncludeContentAreaAccountEmail(tab_url, TabWorkspaceDomains())) {
+    return "";
+  }
+
+  return GetEmailFromUrl(im, tab_url);
+}
+
+std::string GetActiveFrameUser(signin::IdentityManager* im,
+                               const GURL& tab_url,
+                               const GURL& frame_url) {
+  if (!IncludeContentAreaAccountEmail(tab_url, TabWorkspaceDomains()) ||
+      !IncludeContentAreaAccountEmail(frame_url, FrameWorkspaceDomains())) {
+    return "";
+  }
+
+  return GetEmailFromUrl(im, frame_url);
 }
 
 }  // namespace enterprise_connectors
diff --git a/components/enterprise/connectors/core/content_area_user_provider.h b/components/enterprise/connectors/core/content_area_user_provider.h
index 157b7a7..ac672b83 100644
--- a/components/enterprise/connectors/core/content_area_user_provider.h
+++ b/components/enterprise/connectors/core/content_area_user_provider.h
@@ -18,7 +18,14 @@
 // sites.
 // TODO(crbug.com/415002299): Add tests for this.
 std::string GetActiveContentAreaUser(signin::IdentityManager* im,
-                                     const GURL& url);
+                                     const GURL& tab_url);
+
+// Returns email of the active Gaia user based on the values found in the
+// provided frame URL and identity manager. Only returns a value if `tab_url` is
+// a Workspace site.
+std::string GetActiveFrameUser(signin::IdentityManager* im,
+                               const GURL& tab_url,
+                               const GURL& frame_url);
 
 }  // namespace enterprise_connectors
 
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
index 9df02b4..758d862 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
@@ -125,13 +125,6 @@
     boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl);
 
     /**
-     * Whether navigations started by the embedder (i.e. not by the renderer) should stay in the
-     * browser by default. Note that there are many exceptions to this, like redirects off of the
-     * navigation still being allowed to leave the browser.
-     */
-    boolean shouldEmbedderInitiatedNavigationsStayInBrowser();
-
-    /**
      * Returns the scheme (or null) used by web pages to start up the browser (Chrome Stable for
      * Chrome) without an explicit Intent.
      */
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
index 2c2dabb..bed32d8 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -1018,16 +1018,7 @@
             return NavigationChainResult.REQUIRES_PROMPT;
         }
 
-        // TODO(crbug.com/40232652): We only need to check isFromTyping because WebLayer's
-        // implementation of disabling intent processing is broken and doesn't actually disable
-        // intent processing, but to align with current weblayer behavior the first navigation has
-        // to be blocked even if the weblayer delegate tells us not to block embedder initiated
-        // navigations. See
-        // https://source.chromium.org/chromium/chromium/src/+/main:weblayer/browser/navigation_controller_impl.cc;drc=88d7b2e74349cbf8b3e15b61cc0663d65f9d1873;l=220
-        if (!initialState.isRendererInitiated
-                && !initialState.isFromIntent
-                && (mDelegate.shouldEmbedderInitiatedNavigationsStayInBrowser()
-                        || initialState.isFromTyping)) {
+        if (!initialState.isRendererInitiated && !initialState.isFromIntent) {
             if (debug()) Log.i(TAG, "Browser initiated navigation chain.");
             return NavigationChainResult.REQUIRES_PROMPT;
         }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
index b3f80eb..da20d87 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
@@ -74,7 +74,6 @@
     public static class InitialNavigationState {
         public final boolean isRendererInitiated;
         public final boolean isFromReload;
-        public final boolean isFromTyping;
         public final boolean isFromFormSubmit;
         public final boolean isFromIntent;
         public final boolean hasUserGesture;
@@ -83,13 +82,11 @@
                 boolean isRendererInitiated,
                 boolean hasUserGesture,
                 boolean isFromReload,
-                boolean isFromTyping,
                 boolean isFromFormSubmit,
                 boolean isFromIntent) {
             this.isRendererInitiated = isRendererInitiated;
             this.hasUserGesture = hasUserGesture;
             this.isFromReload = isFromReload;
-            this.isFromTyping = isFromTyping;
             this.isFromFormSubmit = isFromFormSubmit;
             this.isFromIntent = isFromIntent;
         }
@@ -258,7 +255,6 @@
         boolean isFromApi = (pageTransType & PageTransition.FROM_API) != 0;
         boolean isFromIntent = isFromApi && (mIntentState != null || mIsPrefetchLoadForIntent);
         boolean isFromReload = pageTransitionCore == PageTransition.RELOAD;
-        boolean isFromTyping = pageTransitionCore == PageTransition.TYPED;
         boolean isFromFormSubmit = pageTransitionCore == PageTransition.FORM_SUBMIT;
 
         if (!isFromIntent) {
@@ -270,7 +266,6 @@
                         isRendererInitiated,
                         hasUserGesture,
                         isFromReload,
-                        isFromTyping,
                         isFromFormSubmit,
                         isFromIntent);
 
@@ -300,13 +295,9 @@
         return mIntentState != null && mIntentState.mIsCustomTabIntent;
     }
 
-    /** @return whether navigation is from a user's typing or not. */
-    public boolean isNavigationFromUserTyping() {
-        assumeNonNull(mNavigationChainState);
-        return mNavigationChainState.mInitialNavigationState.isFromTyping;
-    }
-
-    /** @return whether we should stay in Chrome or not. */
+    /**
+     * @return whether we should stay in Chrome or not.
+     */
     public boolean shouldNotOverrideUrlLoading() {
         assumeNonNull(mNavigationChainState);
         return mNavigationChainState.mShouldNotOverrideUrlLoadingOnCurrentNavigationChain;
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index 69c6b29..fe9aa1e7 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -2824,27 +2824,6 @@
 
     @Test
     @SmallTest
-    public void testEmbedderInitiatedNavigationsLeaveBrowser() {
-        mDelegate.add(new IntentActivity(YOUTUBE_URL, YOUTUBE_PACKAGE_NAME));
-        RedirectHandler redirectHandler = RedirectHandler.create();
-        redirectHandler.updateNewUrlLoading(
-                PageTransition.AUTO_BOOKMARK, false, false, 0, false, false);
-
-        checkUrl(YOUTUBE_URL, redirectHandler)
-                .withIsRendererInitiated(false)
-                .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
-
-        mDelegate.setShouldEmbedderInitiatedNavigationsStayInBrowser(false);
-
-        checkUrl(YOUTUBE_URL, redirectHandler)
-                .withIsRendererInitiated(false)
-                .expecting(
-                        OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
-                        START_OTHER_ACTIVITY);
-    }
-
-    @Test
-    @SmallTest
     public void testExpiredNavigationChain() {
         mDelegate.add(new IntentActivity(YOUTUBE_MOBILE_URL, YOUTUBE_PACKAGE_NAME));
 
@@ -3435,11 +3414,6 @@
         }
 
         @Override
-        public boolean shouldEmbedderInitiatedNavigationsStayInBrowser() {
-            return mShouldEmbedderInitiatedNavigationsStayInBrowser;
-        }
-
-        @Override
         public String getSelfScheme() {
             return SELF_SCHEME;
         }
@@ -3537,10 +3511,6 @@
             mWillResolveToDisambiguationDialog = value;
         }
 
-        public void setShouldEmbedderInitiatedNavigationsStayInBrowser(boolean value) {
-            mShouldEmbedderInitiatedNavigationsStayInBrowser = value;
-        }
-
         public void setResolvesToOtherBrowser(boolean value) {
             mResolvesToOtherBrowser = value;
         }
@@ -3580,7 +3550,6 @@
         private boolean mShouldAvoidDisambiguationDialog;
         private boolean mWillResolveToDisambiguationDialog;
         private Context mContext;
-        private boolean mShouldEmbedderInitiatedNavigationsStayInBrowser = true;
         private boolean mResolvesToOtherBrowser;
         private boolean mShouldDisableAllExternalIntents;
         private boolean mShouldReturnAsActivityResult;
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
index 9d44018..e9089ca0 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
@@ -248,30 +248,6 @@
     @Test
     @SmallTest
     @Feature({"IntentHandling"})
-    public void testNavigationFromUserTyping() {
-        RedirectHandler handler = RedirectHandler.create();
-        handler.updateIntent(sYtIntent, false, false, false, false);
-        Assert.assertFalse(handler.isOnNavigation());
-
-        handler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, false, false);
-        Assert.assertTrue(handler.isNavigationFromUserTyping());
-        handler.updateNewUrlLoading(PageTransition.LINK, false, false, 1, false, true);
-        Assert.assertTrue(handler.isNavigationFromUserTyping());
-
-        Assert.assertTrue(handler.isOnNavigation());
-        Assert.assertEquals(0, handler.getLastCommittedEntryIndexBeforeStartingNavigation());
-
-        SystemClock.sleep(1);
-        handler.updateNewUrlLoading(PageTransition.LINK, false, true, 2, false, true);
-        Assert.assertFalse(handler.isNavigationFromUserTyping());
-
-        Assert.assertTrue(handler.isOnNavigation());
-        Assert.assertEquals(2, handler.getLastCommittedEntryIndexBeforeStartingNavigation());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"IntentHandling"})
     public void testRedirectFromCurrentNavigationShouldNotOverrideUrlLoading() {
         /////////////////////////////////////////////////////
         // 1. 3XX redirection should not override URL loading.
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index 0695276..1a8ea022 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -559,7 +559,6 @@
 using MostVisitedURLList = std::vector<MostVisitedURL>;
 using KeywordSearchTermVisitList =
     std::vector<std::unique_ptr<KeywordSearchTermVisit>>;
-using FilteredURLList = std::vector<FilteredURL>;
 
 struct MostVisitedURLWithRank {
   MostVisitedURL url;
diff --git a/components/infobars/core/infobar_container.cc b/components/infobars/core/infobar_container.cc
index ceea6aa..66c30adc 100644
--- a/components/infobars/core/infobar_container.cc
+++ b/components/infobars/core/infobar_container.cc
@@ -134,6 +134,7 @@
   // Record the infobar being displayed.
   DCHECK_NE(InfoBarDelegate::INVALID, infobar->GetIdentifier());
   base::UmaHistogramSparse("InfoBar.Shown", infobar->GetIdentifier());
+  base::UmaHistogramExactLinear("InfoBar.CountAtShow", infobars_.size(), 10);
 }
 
 }  // namespace infobars
diff --git a/components/ip_protection/common/ip_protection_data_types.h b/components/ip_protection/common/ip_protection_data_types.h
index 80134a8..08dd375 100644
--- a/components/ip_protection/common/ip_protection_data_types.h
+++ b/components/ip_protection/common/ip_protection_data_types.h
@@ -11,7 +11,10 @@
 #include <vector>
 
 #include "base/time/time.h"
-#include "components/privacy_sandbox/masked_domain_list/masked_domain_list.pb.h"
+
+namespace masked_domain_list {
+class Resource;
+}
 
 namespace ip_protection {
 
diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingMediaSource.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingMediaSource.java
index f56facb..1d35b8c 100644
--- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingMediaSource.java
+++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingMediaSource.java
@@ -33,8 +33,7 @@
     private static final String SOURCE_PREFIX = "remote-playback:";
     private static final String ENCODED_SOURCE_KEY = "source";
 
-    // Needs to be in sync with AndroidManifest meta-data key (used both by Clank and WebLayer
-    // clients).
+    // Needs to be in sync with AndroidManifest meta-data key (used by Clank).
     private static final String REMOTE_PLAYBACK_APP_ID_KEY =
             "org.chromium.content.browser.REMOTE_PLAYBACK_APP_ID";
 
diff --git a/components/metrics/dwa/dwa_entry_builder_base.cc b/components/metrics/dwa/dwa_entry_builder_base.cc
index 4755ded..0cf0020 100644
--- a/components/metrics/dwa/dwa_entry_builder_base.cc
+++ b/components/metrics/dwa/dwa_entry_builder_base.cc
@@ -10,6 +10,7 @@
 
 #include "base/containers/flat_set.h"
 #include "base/metrics/metrics_hashes.h"
+#include "components/metrics/dwa/dwa_recorder.h"
 #include "components/metrics/dwa/mojom/dwa_interface.mojom.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
diff --git a/components/metrics/dwa/dwa_entry_builder_base.h b/components/metrics/dwa/dwa_entry_builder_base.h
index a9efef61..a3b72e71 100644
--- a/components/metrics/dwa/dwa_entry_builder_base.h
+++ b/components/metrics/dwa/dwa_entry_builder_base.h
@@ -6,13 +6,15 @@
 #define COMPONENTS_METRICS_DWA_DWA_ENTRY_BUILDER_BASE_H_
 
 #include <cstdint>
-#include <optional>
 #include <string>
-#include <unordered_map>
+#include <string_view>
 
-#include "components/metrics/dwa/dwa_recorder.h"
 #include "components/metrics/dwa/mojom/dwa_interface.mojom.h"
 
+namespace metrics::dwa {
+class DwaRecorder;
+}
+
 namespace dwa::internal {
 
 // An internal base class for the generated DwaEntry builder objects and the
diff --git a/components/omnibox/browser/contextual_search_provider.cc b/components/omnibox/browser/contextual_search_provider.cc
index 96e07da4b..8d6c5fb 100644
--- a/components/omnibox/browser/contextual_search_provider.cc
+++ b/components/omnibox/browser/contextual_search_provider.cc
@@ -145,11 +145,13 @@
         (toolbelt_config.always_include_lens_action ||
          LensEntrypointEligible(input, client));
 
+    // - Restricted to when `kAiModeOmniboxEntryPoint` is disabled
     // - Restricted to DSE google
     // - Restricted to locale EN
     // - Restricted to when `kAIModeSettings` policy is enabled
     toolbelt_ai_mode =
         toolbelt &&
+        !base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint) &&
         search::DefaultSearchProviderIsGoogle(
             client->GetTemplateURLService()) &&
         l10n_util::GetLanguage(client->GetApplicationLocale()) == "en" &&
diff --git a/components/omnibox/browser/local_history_zero_suggest_provider.cc b/components/omnibox/browser/local_history_zero_suggest_provider.cc
index fe76426..12dedf7 100644
--- a/components/omnibox/browser/local_history_zero_suggest_provider.cc
+++ b/components/omnibox/browser/local_history_zero_suggest_provider.cc
@@ -24,6 +24,7 @@
 #include "components/google/core/common/google_util.h"
 #include "components/history/core/browser/history_database.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_types.h"
 #include "components/history/core/browser/keyword_search_term.h"
 #include "components/history/core/browser/keyword_search_term_util.h"
 #include "components/history/core/browser/url_database.h"
@@ -213,7 +214,7 @@
     return;
   }
 
-  std::vector<std::unique_ptr<history::KeywordSearchTermVisit>> results;
+  history::KeywordSearchTermVisitList results;
   const base::ElapsedTimer db_query_timer;
   auto enumerator = url_db->CreateKeywordSearchTermVisitEnumerator(
       template_url_service->GetDefaultSearchProvider()->id());
diff --git a/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc b/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
index 34e03f1..4e1e3a1e 100644
--- a/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/local_history_zero_suggest_provider_unittest.cc
@@ -20,6 +20,7 @@
 #include "build/build_config.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_types.h"
 #include "components/history/core/browser/keyword_search_term.h"
 #include "components/history/core/browser/keyword_search_term_util.h"
 #include "components/history/core/browser/url_database.h"
@@ -488,7 +489,7 @@
 
   // Make sure all the search terms for the default search provider that would
   // produce the deleted match are deleted.
-  std::vector<std::unique_ptr<history::KeywordSearchTermVisit>> visits;
+  history::KeywordSearchTermVisitList visits;
   auto enumerator_1 = url_db->CreateKeywordSearchTermVisitEnumerator(
       default_search_provider()->id());
   ASSERT_TRUE(enumerator_1);
@@ -605,7 +606,7 @@
 
   // Make sure all the search terms for the default search provider that would
   // produce the deleted match are deleted.
-  std::vector<std::unique_ptr<history::KeywordSearchTermVisit>> visits;
+  history::KeywordSearchTermVisitList visits;
   auto enumerator_1 = url_db->CreateKeywordSearchTermVisitEnumerator(
       default_search_provider()->id());
   ASSERT_TRUE(enumerator_1);
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index a825bea..9ed01dd 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -31,6 +31,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/timer/elapsed_timer.h"
 #include "base/trace_event/trace_event.h"
+#include "components/history/core/browser/history_types.h"
 #include "components/history/core/browser/in_memory_database.h"
 #include "components/history/core/browser/keyword_search_term.h"
 #include "components/history/core/browser/keyword_search_term_util.h"
@@ -1180,11 +1181,12 @@
 }
 
 SearchSuggestionParser::SuggestResults
-SearchProvider::ScoreHistoryResultsHelper(const HistoryResults& results,
-                                          bool base_prevent_inline_autocomplete,
-                                          bool input_multiple_words,
-                                          const std::u16string& input_text,
-                                          bool is_keyword) {
+SearchProvider::ScoreHistoryResultsHelper(
+    const history::KeywordSearchTermVisitList& results,
+    bool base_prevent_inline_autocomplete,
+    bool input_multiple_words,
+    const std::u16string& input_text,
+    bool is_keyword) {
   SearchSuggestionParser::SuggestResults scored_results;
   // True if the user has asked this exact query previously.
   bool found_what_you_typed_match = false;
@@ -1283,7 +1285,7 @@
 }
 
 void SearchProvider::ScoreHistoryResults(
-    const HistoryResults& results,
+    const history::KeywordSearchTermVisitList& results,
     bool is_keyword,
     SearchSuggestionParser::SuggestResults* scored_results) {
   DCHECK(scored_results);
diff --git a/components/omnibox/browser/search_provider.h b/components/omnibox/browser/search_provider.h
index faef1c03..210f0ca 100644
--- a/components/omnibox/browser/search_provider.h
+++ b/components/omnibox/browser/search_provider.h
@@ -21,6 +21,7 @@
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "components/history/core/browser/history_types.h"
 #include "components/omnibox/browser/answers_cache.h"
 #include "components/omnibox/browser/autocomplete_enums.h"
 #include "components/omnibox/browser/base_search_provider.h"
@@ -34,10 +35,6 @@
 class AutocompleteResult;
 class SearchProviderTest;
 
-namespace history {
-struct KeywordSearchTermVisit;
-}
-
 namespace network {
 class SimpleURLLoader;
 }
@@ -164,9 +161,6 @@
 
   class CompareScoredResults;
 
-  typedef std::vector<std::unique_ptr<history::KeywordSearchTermVisit>>
-      HistoryResults;
-
   // A helper function for UpdateAllOldResults().
   static void UpdateOldResults(bool minimal_changes,
                                SearchSuggestionParser::Results* results);
@@ -314,7 +308,7 @@
 
   // Calculates relevance scores for all |results|.
   SearchSuggestionParser::SuggestResults ScoreHistoryResultsHelper(
-      const HistoryResults& results,
+      const history::KeywordSearchTermVisitList& results,
       bool base_prevent_inline_autocomplete,
       bool input_multiple_words,
       const std::u16string& input_text,
@@ -324,7 +318,7 @@
   // conditions around multi-word queries. (See inline comments in function
   // definition for more details.)
   void ScoreHistoryResults(
-      const HistoryResults& results,
+      const history::KeywordSearchTermVisitList& results,
       bool is_keyword,
       SearchSuggestionParser::SuggestResults* scored_results);
 
@@ -393,8 +387,8 @@
   AutocompleteInput keyword_input_;
 
   // Searches in the user's history that begin with the input text.
-  HistoryResults raw_keyword_history_results_;
-  HistoryResults raw_default_history_results_;
+  history::KeywordSearchTermVisitList raw_keyword_history_results_;
+  history::KeywordSearchTermVisitList raw_default_history_results_;
 
   // Scored searches in the user's history - based on |keyword_history_results_|
   // or |default_history_results_| as appropriate.
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 195df1be..3cfadfc 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -200,6 +200,9 @@
              "OmniboxAssistantVoiceSearch",
              DISABLED);
 
+// Whether the AI Mode entrypoint is shown in the Omnibox as a RHS button.
+BASE_FEATURE(kAiModeOmniboxEntryPoint, "AiModeOmniboxEntryPoint", DISABLED);
+
 // Feature used to default typed navigations to use HTTPS instead of HTTP.
 // This only applies to navigations that don't have a scheme such as
 // "example.com". Presently, typing "example.com" in a clean browsing profile
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h
index 598426e..4530555 100644
--- a/components/omnibox/common/omnibox_features.h
+++ b/components/omnibox/common/omnibox_features.h
@@ -68,6 +68,7 @@
 // Omnibox UI - these affect the UI or function of the location bar (not the
 // popup).
 BASE_DECLARE_FEATURE(kOmniboxAssistantVoiceSearch);
+BASE_DECLARE_FEATURE(kAiModeOmniboxEntryPoint);
 
 // Navigation experiments.
 BASE_DECLARE_FEATURE(kDefaultTypedNavigationsToHttps);
diff --git a/components/optimization_guide/core/model_execution/on_device_execution.cc b/components/optimization_guide/core/model_execution/on_device_execution.cc
index ca8726c..c463be52 100644
--- a/components/optimization_guide/core/model_execution/on_device_execution.cc
+++ b/components/optimization_guide/core/model_execution/on_device_execution.cc
@@ -86,6 +86,19 @@
       tokens);
 }
 
+void LogResponseTimeToNextToken(ModelBasedCapabilityKey feature,
+                                uint32_t tokens,
+                                base::TimeDelta token_time) {
+  if (tokens == 0) {
+    return;
+  }
+  base::UmaHistogramTimes(
+      base::StrCat({"OptimizationGuide.ModelExecution."
+                    "OnDeviceResponseTokensTimeToNextToken.",
+                    GetStringNameForModelExecutionFeature(feature)}),
+      token_time / tokens);
+}
+
 std::string GenerateExecutionId() {
   return "on-device:" + base::Uuid::GenerateRandomV4().AsLowercaseString();
 }
@@ -243,7 +256,8 @@
       MutableLoggedResponse();
 
   if (current_response_.empty()) {
-    base::TimeDelta time_to_first_response = base::TimeTicks::Now() - start_;
+    first_response_time_ = base::TimeTicks::Now();
+    base::TimeDelta time_to_first_response = first_response_time_ - start_;
     base::UmaHistogramMediumTimes(
         base::StrCat(
             {"OptimizationGuide.ModelExecution.OnDeviceFirstResponseTime.",
@@ -297,14 +311,17 @@
 
 void OnDeviceExecution::OnComplete(
     on_device_model::mojom::ResponseSummaryPtr summary) {
+  base::TimeTicks completion_time = base::TimeTicks::Now();
+  base::TimeDelta time_to_completion = completion_time - start_;
   receiver_.reset();  // Suppress expected disconnect
 
   bool has_repeats = MutableLoggedResponse()->has_repeats();
 
   LogResponseHasRepeats(feature_, has_repeats);
   LogResponseCompleteTokens(feature_, num_response_tokens_);
-  base::TimeDelta time_to_completion = base::TimeTicks::Now() - start_;
   LogResponseCompleteTime(feature_, time_to_completion);
+  LogResponseTimeToNextToken(feature_, num_response_tokens_,
+                             completion_time - first_response_time_);
   MutableLoggedResponse()->set_time_to_completion_millis(
       time_to_completion.InMilliseconds());
 
diff --git a/components/optimization_guide/core/model_execution/on_device_execution.h b/components/optimization_guide/core/model_execution/on_device_execution.h
index 3b85cf39..a3dbfd2a 100644
--- a/components/optimization_guide/core/model_execution/on_device_execution.h
+++ b/components/optimization_guide/core/model_execution/on_device_execution.h
@@ -223,6 +223,8 @@
   on_device_model::mojom::ResponseConstraintPtr constraint_;
   // Time ExecuteModel() was called.
   base::TimeTicks start_;
+  // Time we receive the first token.
+  base::TimeTicks first_response_time_;
   // Used to log the result of ExecuteModel().
   std::unique_ptr<ResultLogger> histogram_logger_;
   // Used to log execution information for the request.
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
index 643453fb..b17cb28 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
@@ -570,6 +570,10 @@
     model_paths.cache =
         model_metadata_->model_path().Append(kExperimentalCacheFile);
   }
+  model_paths.encoder_cache =
+      model_metadata_->model_path().Append(kEncoderCacheFile);
+  model_paths.adapter_cache =
+      model_metadata_->model_path().Append(kAdapterCacheFile);
 
   return model_paths;
 }
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
index 658ade6..8bb0a35 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
@@ -432,6 +432,8 @@
 
   FakeBaseModelAsset base_model_with_cache({
       .cache_weight = 1015,
+      .encoder_cache_weight = 1016,
+      .adapter_cache_weight = 1017,
   });
 
   Initialize(InitializeParams{
@@ -446,7 +448,8 @@
                         response_.GetStreamingCallback());
   ASSERT_TRUE(response_.GetFinalStatus());
   EXPECT_EQ(*response_.value(),
-            "CPU backendCache weight: 1015execute:foo max:1024");
+            "CPU backendCache weight: 1015Encoder cache weight: 1016"
+            "Adapter cache weight: 1017execute:foo max:1024");
 
   // If we destroy all sessions and wait long enough, everything should idle out
   // and the service should get terminated.
@@ -2957,8 +2960,8 @@
   FakeBaseModelAsset next_model({
       .weight = 2,
       .config = ExecutionConfigWithValidation(WillFailValidationConfig()),
-      .version = "0.0.2",
   });
+  next_model.set_version("0.0.2");
   {
     base::HistogramTester histogram_tester;
     next_model.SetReadyIn(component_state_manager());
@@ -3018,8 +3021,8 @@
   // Send a new model update with no validation config.
   FakeBaseModelAsset next_model({
       .weight = 2,
-      .version = "0.0.2",
   });
+  next_model.set_version("0.0.2");
   next_model.SetReadyIn(component_state_manager());
   task_environment_.RunUntilIdle();
 
diff --git a/components/optimization_guide/core/model_execution/test/fake_model_assets.cc b/components/optimization_guide/core/model_execution/test/fake_model_assets.cc
index f48f3360..58ae996 100644
--- a/components/optimization_guide/core/model_execution/test/fake_model_assets.cc
+++ b/components/optimization_guide/core/model_execution/test/fake_model_assets.cc
@@ -24,17 +24,15 @@
 
 FakeBaseModelAsset::FakeBaseModelAsset()
     : FakeBaseModelAsset(FakeBaseModelAsset::Content{}) {}
-FakeBaseModelAsset::FakeBaseModelAsset(Content&& content)
-    : version_(content.version) {
+FakeBaseModelAsset::FakeBaseModelAsset(Content&& content) {
   CHECK(temp_dir_.CreateUniqueTempDir());
   supported_performance_hints_.Append(content.supported_performance_hint);
   Write(std::move(content));
 }
 FakeBaseModelAsset::FakeBaseModelAsset(
-    std::vector<proto::OnDeviceModelPerformanceHint> hints)
-    : version_("0.0.1") {
+    const std::vector<proto::OnDeviceModelPerformanceHint>& hints) {
   CHECK(temp_dir_.CreateUniqueTempDir());
-  for (auto hint : hints) {
+  for (const auto& hint : hints) {
     supported_performance_hints_.Append(hint);
   }
   Write({});
@@ -53,6 +51,14 @@
     CHECK(base::WriteFile(temp_dir_.GetPath().Append(kExperimentalCacheFile),
                           base::NumberToString(content.cache_weight)));
   }
+  if (content.encoder_cache_weight) {
+    CHECK(base::WriteFile(temp_dir_.GetPath().Append(kEncoderCacheFile),
+                          base::NumberToString(content.encoder_cache_weight)));
+  }
+  if (content.adapter_cache_weight) {
+    CHECK(base::WriteFile(temp_dir_.GetPath().Append(kAdapterCacheFile),
+                          base::NumberToString(content.adapter_cache_weight)));
+  }
   CHECK(base::WriteFile(
       temp_dir_.GetPath().Append(kOnDeviceModelExecutionConfigFile),
       content.config.SerializeAsString()));
diff --git a/components/optimization_guide/core/model_execution/test/fake_model_assets.h b/components/optimization_guide/core/model_execution/test/fake_model_assets.h
index 0405bf5..dedfc0a 100644
--- a/components/optimization_guide/core/model_execution/test/fake_model_assets.h
+++ b/components/optimization_guide/core/model_execution/test/fake_model_assets.h
@@ -30,15 +30,16 @@
   struct Content {
     uint32_t weight = 0;
     proto::OnDeviceModelExecutionConfig config;
-    std::string version = "0.0.1";
     uint32_t cache_weight = 0;
+    uint32_t encoder_cache_weight = 0;
+    uint32_t adapter_cache_weight = 0;
     proto::OnDeviceModelPerformanceHint supported_performance_hint =
         proto::ON_DEVICE_MODEL_PERFORMANCE_HINT_HIGHEST_QUALITY;
   };
   FakeBaseModelAsset();
   explicit FakeBaseModelAsset(Content&& content);
   explicit FakeBaseModelAsset(
-      std::vector<proto::OnDeviceModelPerformanceHint> hints);
+      const std::vector<proto::OnDeviceModelPerformanceHint>& hints);
   explicit FakeBaseModelAsset(
       proto::OnDeviceModelValidationConfig&& validation_config);
   ~FakeBaseModelAsset();
@@ -48,6 +49,7 @@
 
   const base::FilePath& path() const { return temp_dir_.GetPath(); }
 
+  void set_version(const std::string& version) { version_ = version; }
   const std::string& version() const { return version_; }
 
   // Returns a fake manifest content for this asset.
@@ -57,7 +59,7 @@
   void SetReadyIn(OnDeviceModelComponentStateManager& manager) const;
 
  private:
-  std::string version_;
+  std::string version_ = "0.0.1";
   base::Value::List supported_performance_hints_;
   base::ScopedTempDir temp_dir_;
 };
diff --git a/components/optimization_guide/core/optimization_guide_constants.cc b/components/optimization_guide/core/optimization_guide_constants.cc
index f9281bac..e0062a1 100644
--- a/components/optimization_guide/core/optimization_guide_constants.cc
+++ b/components/optimization_guide/core/optimization_guide_constants.cc
@@ -48,6 +48,12 @@
 const base::FilePath::CharType kExperimentalCacheFile[] =
     FILE_PATH_LITERAL("cache.bin");
 
+const base::FilePath::CharType kEncoderCacheFile[] =
+    FILE_PATH_LITERAL("encoder_cache.bin");
+
+const base::FilePath::CharType kAdapterCacheFile[] =
+    FILE_PATH_LITERAL("adapter_cache.bin");
+
 const base::FilePath::CharType kTsDataFile[] = FILE_PATH_LITERAL("ts.bin");
 
 const base::FilePath::CharType kTsSpModelFile[] =
diff --git a/components/optimization_guide/core/optimization_guide_constants.h b/components/optimization_guide/core/optimization_guide_constants.h
index e04ff893..96942bc 100644
--- a/components/optimization_guide/core/optimization_guide_constants.h
+++ b/components/optimization_guide/core/optimization_guide_constants.h
@@ -70,6 +70,10 @@
 COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
 extern const base::FilePath::CharType kExperimentalCacheFile[];
 COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
+extern const base::FilePath::CharType kEncoderCacheFile[];
+COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
+extern const base::FilePath::CharType kAdapterCacheFile[];
+COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
 extern const base::FilePath::CharType kOnDeviceModelExecutionConfigFile[];
 
 // Files expected to be in the text safety model bundle.
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index 76c30fc..265386b 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit 76c30fcad7ac08d84c88ddc4df6a7b5f607822f8
+Subproject commit 265386bd2ef17a972139f26b14b0017887a043dd
diff --git a/components/paint_preview/common/mojom/paint_preview_recorder.mojom b/components/paint_preview/common/mojom/paint_preview_recorder.mojom
index 2d39e27..938fa36 100644
--- a/components/paint_preview/common/mojom/paint_preview_recorder.mojom
+++ b/components/paint_preview/common/mojom/paint_preview_recorder.mojom
@@ -38,6 +38,10 @@
   kFailed,
 };
 
+// Used in PaintPreviewCaptureParams::clip_rect to center the capture around the
+// scroll offset.
+const int32 kCenterOnScrollOffset = -1;
+
 // The collection of parameters needed for a recording of a render frame.
 struct PaintPreviewCaptureParams {
   // The strategy for where to store the serialized SkPictures resulting from
@@ -52,8 +56,9 @@
   // width/height larger than the document size will be clamped to the
   // size of the document.
   //
-  // A value of -1 for x/y will center the x/y position of the capture
-  // about the current scroll offset if a width/height are specified.
+  // A value of `kCenterOnScrollOffset` for x/y will center the x/y position of
+  // the capture about the current scroll offset if a width/height are
+  // specified.
   gfx.mojom.Rect clip_rect;
 
   // Set to true if the clip rect is only a hint as to size.
diff --git a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
index 0424b0a..1ce81c58 100644
--- a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
+++ b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
@@ -247,8 +247,10 @@
 
   auto out_response = mojom::PaintPreviewCaptureResponse::New();
   content::RenderFrame* frame = GetMainRenderFrame();
-  base::FilePath skp_path =
-      RunCapture(frame, &out_response, true, gfx::Rect(-1, -1, 500, 500));
+  base::FilePath skp_path = RunCapture(
+      frame, &out_response, true,
+      gfx::Rect(paint_preview::mojom::kCenterOnScrollOffset,
+                paint_preview::mojom::kCenterOnScrollOffset, 500, 500));
 
   EXPECT_TRUE(out_response->embedding_token.has_value());
   EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(),
@@ -298,8 +300,10 @@
 
   auto out_response = mojom::PaintPreviewCaptureResponse::New();
   content::RenderFrame* frame = GetMainRenderFrame();
-  base::FilePath skp_path =
-      RunCapture(frame, &out_response, true, gfx::Rect(-1, -1, 500, 2000));
+  base::FilePath skp_path = RunCapture(
+      frame, &out_response, true,
+      gfx::Rect(paint_preview::mojom::kCenterOnScrollOffset,
+                paint_preview::mojom::kCenterOnScrollOffset, 500, 2000));
 
   EXPECT_TRUE(out_response->embedding_token.has_value());
   EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(),
@@ -353,7 +357,9 @@
   auto out_response = mojom::PaintPreviewCaptureResponse::New();
   content::RenderFrame* frame = GetMainRenderFrame();
   base::FilePath skp_path =
-      RunCapture(frame, &out_response, true, gfx::Rect(-1, -1, 0, 0));
+      RunCapture(frame, &out_response, true,
+                 gfx::Rect(paint_preview::mojom::kCenterOnScrollOffset,
+                           paint_preview::mojom::kCenterOnScrollOffset, 0, 0));
 
   EXPECT_TRUE(out_response->embedding_token.has_value());
   EXPECT_EQ(frame->GetWebFrame()->GetEmbeddingToken(),
diff --git a/components/paint_preview/renderer/paint_preview_recorder_impl.cc b/components/paint_preview/renderer/paint_preview_recorder_impl.cc
index ed02a68..32d88dd7 100644
--- a/components/paint_preview/renderer/paint_preview_recorder_impl.cc
+++ b/components/paint_preview/renderer/paint_preview_recorder_impl.cc
@@ -265,13 +265,13 @@
 
   auto offset = frame->GetScrollOffset();
   auto document_size = frame->DocumentSize();
-  // If the special values of -1 are used for the initial position center about
-  // the scroll offset.
-  if (bounds.x() == -1) {
+  // If the special values of `paint_preview::mojom::kCenterOnScrollOffset` are
+  // used for the initial position center about the scroll offset.
+  if (bounds.x() == paint_preview::mojom::kCenterOnScrollOffset) {
     bounds.set_x(
         GetBoundOrigin(document_size.width(), bounds.width(), offset.x()));
   }
-  if (bounds.y() == -1) {
+  if (bounds.y() == paint_preview::mojom::kCenterOnScrollOffset) {
     bounds.set_y(
         GetBoundOrigin(document_size.height(), bounds.height(), offset.y()));
   }
diff --git a/components/password_manager/ios/password_suggestion_helper.mm b/components/password_manager/ios/password_suggestion_helper.mm
index 9ab4412..610aa29 100644
--- a/components/password_manager/ios/password_suggestion_helper.mm
+++ b/components/password_manager/ios/password_suggestion_helper.mm
@@ -4,6 +4,7 @@
 
 #import "components/password_manager/ios/password_suggestion_helper.h"
 
+#import <algorithm>
 #import <utility>
 
 #import "base/feature_list.h"
@@ -440,27 +441,33 @@
     return YES;
   }
 
-  autofill::FieldType fieldType = (*it)->Type().GetStorableType();
-  switch (GroupTypeOfFieldType(fieldType)) {
-    case autofill::FieldTypeGroup::kPasswordField:
-    case autofill::FieldTypeGroup::kNoGroup:
-      return YES;  // May be a password field.
-    case autofill::FieldTypeGroup::kName:
-    case autofill::FieldTypeGroup::kEmail:
-    case autofill::FieldTypeGroup::kCompany:
-    case autofill::FieldTypeGroup::kAddress:
-    case autofill::FieldTypeGroup::kPhone:
-    case autofill::FieldTypeGroup::kCreditCard:
-    case autofill::FieldTypeGroup::kTransaction:
-    case autofill::FieldTypeGroup::kUsernameField:
-    case autofill::FieldTypeGroup::kUnfillable:
-    case autofill::FieldTypeGroup::kIban:
-    case autofill::FieldTypeGroup::kStandaloneCvcField:
-    case autofill::FieldTypeGroup::kAutofillAi:
-    case autofill::FieldTypeGroup::kLoyaltyCard:
-    case autofill::FieldTypeGroup::kOneTimePassword:
-      return NO;
-  }
+  return std::ranges::any_of(
+             (*it)->Type().GetTypes(),
+             [](autofill::FieldType fieldType) {
+               switch (GroupTypeOfFieldType(fieldType)) {
+                 case autofill::FieldTypeGroup::kPasswordField:
+                 case autofill::FieldTypeGroup::kNoGroup:
+                   return true;  // May be a password field.
+                 case autofill::FieldTypeGroup::kName:
+                 case autofill::FieldTypeGroup::kEmail:
+                 case autofill::FieldTypeGroup::kCompany:
+                 case autofill::FieldTypeGroup::kAddress:
+                 case autofill::FieldTypeGroup::kPhone:
+                 case autofill::FieldTypeGroup::kCreditCard:
+                 case autofill::FieldTypeGroup::kTransaction:
+                 case autofill::FieldTypeGroup::kUsernameField:
+                 case autofill::FieldTypeGroup::kUnfillable:
+                 case autofill::FieldTypeGroup::kIban:
+                 case autofill::FieldTypeGroup::kStandaloneCvcField:
+                 case autofill::FieldTypeGroup::kAutofillAi:
+                 case autofill::FieldTypeGroup::kLoyaltyCard:
+                 case autofill::FieldTypeGroup::kOneTimePassword:
+                   return false;
+               }
+               NOTREACHED();
+             })
+             ? YES
+             : NO;
 }
 
 #pragma mark - FillDataProvider
diff --git a/components/pdf_strings.grdp b/components/pdf_strings.grdp
index 106d1e7..34f86a3 100644
--- a/components/pdf_strings.grdp
+++ b/components/pdf_strings.grdp
@@ -499,6 +499,48 @@
       <message name="IDS_PDF_TOOLTIP_SAVE_TO_DRIVE" desc="Button tooltip for saving a PDF document to Google Drive">
         Save to Google Drive
       </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_CANCEL_UPLOAD_BUTTON_LABEL" desc="Label for the button that will cancel the upload.">
+        Cancel upload
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_CONNECTION_ERROR_MESSAGE" desc="A message telling the user that the upload failed due to a connection error.">
+        Check your internet connection
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_ERROR_TITLE" desc="Title of the dialog that appears when a file fails to upload to Google Drive due to a connection error.">
+        Upload unsuccessful
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_MANAGE_STORAGE_BUTTON_LABEL" desc="Label for the manage storage button in the Save to Drive dialog.">
+        Manage storage
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_OPEN_IN_DRIVE_BUTTON_LABEL" desc="Label for the open in Drive button in the Save to Drive dialog.">
+        Open in Drive
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_RETRY_BUTTON_LABEL" desc="Label for the retry button in the Save to Drive dialog.">
+        Retry
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_SESSION_TIMEOUT_ERROR_MESSAGE" desc="A message telling the user that the upload failed due to their Google Drive session timing out.">
+        Session timed out
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_STORAGE_FULL_ERROR_MESSAGE" desc="A message telling the user that the upload failed due to their Google Drive storage being full.">
+        Your Google Drive storage is full
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_MESSAGE" desc="A message telling the user can find their newly uploaded file in the bolded folder name in Google Drive. 'Save from Chrome' is a folder name example.">
+        Saved to your <ph name="FOLDER_NAME">&lt;b&gt;$1<ex>Save from Chrome</ex>&lt;/b&gt;</ph> folder
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_TITLE" desc="Title of the dialog that appears when a file is successfully uploaded to Google Drive.">
+        Upload successful
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_UNKNOWN_ERROR_MESSAGE" desc="A message telling the user that the upload failed due to an unknown error.">
+        Something unexpected happened. <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>Learn more about Drive uploads<ph name="END_LINK">&lt;/a&gt; <ex>&lt;/a&gt;</ex> </ph>
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_DONE" desc="When a download is finished, let the user know.">
+        Done
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_WITH_SEPARATOR" desc="The upload status and message are separated by a symbol, in this case bullet •, with a white space before it and a white space after it. If the bullet • resembles another symbol in the language, please translate the bullet • as a symbol (A) that is not easily mistaken for a number or letter in the language and (B) that is typically used to separate elements.">
+        <ph name="STATUS">$1<ex>100/120 MB</ex></ph> • <ph name="MESSAGE">$2<ex>4 seconds left</ex></ph>
+      </message>
+      <message name="IDS_SAVE_TO_DRIVE_DIALOG_UPLOADING_TITLE" desc="Title of the dialog that appears when a file is being uploaded to Google Drive.">
+        Uploading to Google Drive...
+      </message>
     </if>
   </if>
   <if expr="enable_screen_ai_service">
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CANCEL_UPLOAD_BUTTON_LABEL.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CANCEL_UPLOAD_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..7d90cdc
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CANCEL_UPLOAD_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+1e2dfa6b239c8a28826036b0685acc08776d0e12
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CONNECTION_ERROR_MESSAGE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CONNECTION_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..36a9fbe
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_CONNECTION_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+b0f4f94de71dd9043c1777ad4f1ebe31c7a6f3bb
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_ERROR_TITLE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_ERROR_TITLE.png.sha1
new file mode 100644
index 0000000..c9fba21
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@
+3d0947d8d7c082eccf5f45798531b85c393cd0ab
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_MANAGE_STORAGE_BUTTON_LABEL.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_MANAGE_STORAGE_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..38857c3
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_MANAGE_STORAGE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+3eee2323ca669dced7f5a284175f3f32190fbf88
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_OPEN_IN_DRIVE_BUTTON_LABEL.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_OPEN_IN_DRIVE_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..dfde11b
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_OPEN_IN_DRIVE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+cc857d9796f98d12d60bd406e22fb1f18c10e451
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_RETRY_BUTTON_LABEL.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_RETRY_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..3ae2a57
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_RETRY_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+5550cb2aa7fe0579b0656222146945c8abc7add2
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SESSION_TIMEOUT_ERROR_MESSAGE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SESSION_TIMEOUT_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..3ae2a57
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SESSION_TIMEOUT_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+5550cb2aa7fe0579b0656222146945c8abc7add2
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_STORAGE_FULL_ERROR_MESSAGE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_STORAGE_FULL_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..38857c3
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_STORAGE_FULL_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+3eee2323ca669dced7f5a284175f3f32190fbf88
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_MESSAGE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_MESSAGE.png.sha1
new file mode 100644
index 0000000..dfde11b
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_MESSAGE.png.sha1
@@ -0,0 +1 @@
+cc857d9796f98d12d60bd406e22fb1f18c10e451
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_TITLE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_TITLE.png.sha1
new file mode 100644
index 0000000..dfde11b
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_SUCCESS_TITLE.png.sha1
@@ -0,0 +1 @@
+cc857d9796f98d12d60bd406e22fb1f18c10e451
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UNKNOWN_ERROR_MESSAGE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UNKNOWN_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..c9fba21
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UNKNOWN_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+3d0947d8d7c082eccf5f45798531b85c393cd0ab
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOADING_TITLE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOADING_TITLE.png.sha1
new file mode 100644
index 0000000..7d90cdc
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOADING_TITLE.png.sha1
@@ -0,0 +1 @@
+1e2dfa6b239c8a28826036b0685acc08776d0e12
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_DONE.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_DONE.png.sha1
new file mode 100644
index 0000000..617f9ef
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_DONE.png.sha1
@@ -0,0 +1 @@
+5d12de9acbcd76cc2cc178a889531d574f70202a
\ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_WITH_SEPARATOR.png.sha1 b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_WITH_SEPARATOR.png.sha1
new file mode 100644
index 0000000..0519121e
--- /dev/null
+++ b/components/pdf_strings_grdp/IDS_SAVE_TO_DRIVE_DIALOG_UPLOAD_STATUS_WITH_SEPARATOR.png.sha1
@@ -0,0 +1 @@
+78270932c55dbf579c96dbb2929820811cada694
\ No newline at end of file
diff --git a/components/permissions/android/BUILD.gn b/components/permissions/android/BUILD.gn
index 121e071..41e495f 100644
--- a/components/permissions/android/BUILD.gn
+++ b/components/permissions/android/BUILD.gn
@@ -187,6 +187,7 @@
     "//base:service_loader_java",
     "//build/android:build_java",
     "//components/browser_ui/modaldialog/android:java",
+    "//components/browser_ui/styles/android:java",
     "//components/browser_ui/util/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/cached_flags:java",
diff --git a/components/permissions/android/DEPS b/components/permissions/android/DEPS
index 707803d..679b3288 100644
--- a/components/permissions/android/DEPS
+++ b/components/permissions/android/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/browser_ui/util/android",
   "+components/browser_ui/widget/android",
+  "+components/browser_ui/styles",
   "+components/cached_flags",
   "+components/infobars/core",
   "+components/location/android",
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
index e6838d6..7c4d758 100644
--- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
+++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCustomViewModelFactory.java
@@ -5,12 +5,13 @@
 package org.chromium.components.permissions;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.text.TextUtils;
 
-import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.content.res.ResourcesCompat;
 
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** This class creates the model for the permission dialog custom view. */
@@ -37,8 +38,8 @@
                                 context.getTheme()))
                 .with(
                         PermissionDialogCustomViewProperties.ICON_TINT,
-                        AppCompatResources.getColorStateList(
-                                context, R.color.default_icon_color_accent1_tint_list))
+                        ColorStateList.valueOf(
+                                SemanticColorUtils.getDefaultIconColorOnAccent1Container(context)))
                 .with(
                         PermissionDialogCustomViewProperties.CLOSE_BUTTON_CALLBACK,
                         delegate::onCloseButtonClicked)
diff --git a/components/permissions/prediction_service/permissions_aiv3_handler.cc b/components/permissions/prediction_service/permissions_aiv3_handler.cc
index 287ae29..1830599 100644
--- a/components/permissions/prediction_service/permissions_aiv3_handler.cc
+++ b/components/permissions/prediction_service/permissions_aiv3_handler.cc
@@ -71,7 +71,7 @@
 
 void PermissionsAiv3Handler::ExecuteModel(ExecutionCallback callback,
                                           ModelInput model_input) {
-  DCHECK(!model_input.snapshot.empty());
+  DCHECK(!model_input.snapshot.drawsNothing());
   VLOG(1) << "PermissionsAiv3Handler::ExecuteModel";
   base::UmaHistogramBoolean("Permissions.AIv3.ModelExecutionAlreadyInProgress",
                             is_execution_in_progress_);
diff --git a/components/permissions/prediction_service/permissions_aiv4_handler.cc b/components/permissions/prediction_service/permissions_aiv4_handler.cc
index e0b18af..7822f453 100644
--- a/components/permissions/prediction_service/permissions_aiv4_handler.cc
+++ b/components/permissions/prediction_service/permissions_aiv4_handler.cc
@@ -66,7 +66,7 @@
 
 void PermissionsAiv4Handler::ExecuteModel(ExecutionCallback callback,
                                           ModelInput model_input) {
-  DCHECK(!model_input.snapshot.empty());
+  DCHECK(!model_input.snapshot.drawsNothing());
   VLOG(1) << "[PermissionsAIv4] PermissionsAiv4Handler::ExecuteModel";
   base::UmaHistogramBoolean("Permissions.AIv4.ModelExecutionAlreadyInProgress",
                             is_execution_in_progress_);
diff --git a/components/permissions/prediction_service/prediction_common.cc b/components/permissions/prediction_service/prediction_common.cc
index ee35b26..c877670 100644
--- a/components/permissions/prediction_service/prediction_common.cc
+++ b/components/permissions/prediction_service/prediction_common.cc
@@ -137,8 +137,8 @@
   FillInStatsFeatures(entity.requested_permission_counts,
                       permission_features->mutable_permission_stats());
   if (base::FeatureList::IsEnabled(permissions::features::kPermissionsAIv1) ||
-      base::FeatureList::IsEnabled(permissions::features::kPermissionsAIv3)) {
-    // TODO(crbug.com/382447738) check for Aiv4 as well
+      base::FeatureList::IsEnabled(permissions::features::kPermissionsAIv3) ||
+      base::FeatureList::IsEnabled(permissions::features::kPermissionsAIv4)) {
     permission_features->set_permission_relevance(
         ConvertToProtoRelevance(entity.permission_relevance));
   }
diff --git a/components/plus_addresses/fake_plus_address_service.cc b/components/plus_addresses/fake_plus_address_service.cc
index 7725220..a37bb69 100644
--- a/components/plus_addresses/fake_plus_address_service.cc
+++ b/components/plus_addresses/fake_plus_address_service.cc
@@ -53,7 +53,7 @@
     bool is_off_the_record,
     const autofill::FormData& focused_form,
     const autofill::FormFieldData& focused_field,
-    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
+    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroupSet>&
         form_field_type_groups,
     const autofill::PasswordFormClassification& focused_form_classification,
     autofill::AutofillSuggestionTriggerSource trigger_source) {
@@ -165,9 +165,10 @@
 
 bool FakePlusAddressService::IsFieldEligibleForPlusAddress(
     const autofill::AutofillField& field) const {
-  autofill::FillingProduct filling_product =
-      autofill::GetFillingProductFromFieldTypeGroup(field.Type().group());
-  if (filling_product == autofill::FillingProduct::kAddress) {
+  auto filling_products = autofill::DenseSet<autofill::FillingProduct>(
+      field.Type().GetGroups(), &autofill::GetFillingProductFromFieldTypeGroup);
+
+  if (filling_products.contains(autofill::FillingProduct::kAddress)) {
     return true;
   }
 
diff --git a/components/plus_addresses/fake_plus_address_service.h b/components/plus_addresses/fake_plus_address_service.h
index 2872a985..73f4417 100644
--- a/components/plus_addresses/fake_plus_address_service.h
+++ b/components/plus_addresses/fake_plus_address_service.h
@@ -41,8 +41,8 @@
       bool is_off_the_record,
       const autofill::FormData& focused_form,
       const autofill::FormFieldData& focused_field,
-      const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
-          form_field_type_groups,
+      const base::flat_map<autofill::FieldGlobalId,
+                           autofill::FieldTypeGroupSet>& form_field_type_groups,
       const autofill::PasswordFormClassification& focused_form_classification,
       autofill::AutofillSuggestionTriggerSource trigger_source) override;
   autofill::Suggestion GetManagePlusAddressSuggestion() const override;
diff --git a/components/plus_addresses/plus_address_service_impl.cc b/components/plus_addresses/plus_address_service_impl.cc
index 8aa9907..5c867a0c 100644
--- a/components/plus_addresses/plus_address_service_impl.cc
+++ b/components/plus_addresses/plus_address_service_impl.cc
@@ -290,10 +290,10 @@
 
 bool PlusAddressServiceImpl::IsFieldEligibleForPlusAddress(
     const autofill::AutofillField& field) const {
-  autofill::FillingProduct filling_product =
-      autofill::GetFillingProductFromFieldTypeGroup(field.Type().group());
+  auto filling_products = autofill::DenseSet<autofill::FillingProduct>(
+      field.Type().GetGroups(), &autofill::GetFillingProductFromFieldTypeGroup);
 
-  if (filling_product == autofill::FillingProduct::kAddress) {
+  if (filling_products.contains(autofill::FillingProduct::kAddress)) {
     return true;
   }
 
@@ -325,7 +325,7 @@
     bool is_off_the_record,
     const autofill::FormData& focused_form,
     const autofill::FormFieldData& focused_field,
-    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
+    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroupSet>&
         form_field_type_groups,
     const autofill::PasswordFormClassification& focused_form_classification,
     AutofillSuggestionTriggerSource trigger_source) {
diff --git a/components/plus_addresses/plus_address_service_impl.h b/components/plus_addresses/plus_address_service_impl.h
index 5ee95415..92baf00 100644
--- a/components/plus_addresses/plus_address_service_impl.h
+++ b/components/plus_addresses/plus_address_service_impl.h
@@ -84,8 +84,8 @@
       bool is_off_the_record,
       const autofill::FormData& focused_form,
       const autofill::FormFieldData& focused_field,
-      const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
-          form_field_type_groups,
+      const base::flat_map<autofill::FieldGlobalId,
+                           autofill::FieldTypeGroupSet>& form_field_type_groups,
       const autofill::PasswordFormClassification& focused_form_classification,
       autofill::AutofillSuggestionTriggerSource trigger_source) override;
   autofill::Suggestion GetManagePlusAddressSuggestion() const override;
diff --git a/components/plus_addresses/plus_address_suggestion_generator.cc b/components/plus_addresses/plus_address_suggestion_generator.cc
index 483ba11..0e1b0de 100644
--- a/components/plus_addresses/plus_address_suggestion_generator.cc
+++ b/components/plus_addresses/plus_address_suggestion_generator.cc
@@ -58,7 +58,7 @@
 // whether we offer plus address creation depends on the form type.
 bool ShouldOfferPlusAddressCreationOnForm(
     const autofill::FormData& focused_form,
-    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
+    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroupSet>&
         form_field_type_groups,
     const PasswordFormClassification& form_classification,
     autofill::FieldGlobalId focused_field_id) {
@@ -102,7 +102,7 @@
           }
           auto it = form_field_type_groups.find(field.global_id());
           return it != form_field_type_groups.end() &&
-                 kUnexpectedFieldTypeGroupsInLoginForm.contains(it->second);
+                 it->second.contains_any(kUnexpectedFieldTypeGroupsInLoginForm);
         });
   };
 
@@ -177,7 +177,7 @@
     bool is_creation_enabled,
     const autofill::FormData& focused_form,
     const autofill::FormFieldData& focused_field,
-    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
+    const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroupSet>&
         form_field_type_groups,
     const autofill::PasswordFormClassification& focused_form_classification,
     autofill::AutofillSuggestionTriggerSource trigger_source) {
diff --git a/components/plus_addresses/plus_address_suggestion_generator.h b/components/plus_addresses/plus_address_suggestion_generator.h
index c6c250b..d493e7d 100644
--- a/components/plus_addresses/plus_address_suggestion_generator.h
+++ b/components/plus_addresses/plus_address_suggestion_generator.h
@@ -47,8 +47,8 @@
       bool is_creation_enabled,
       const autofill::FormData& focused_form,
       const autofill::FormFieldData& focused_field,
-      const base::flat_map<autofill::FieldGlobalId, autofill::FieldTypeGroup>&
-          form_field_type_groups,
+      const base::flat_map<autofill::FieldGlobalId,
+                           autofill::FieldTypeGroupSet>& form_field_type_groups,
       const autofill::PasswordFormClassification& focused_form_classification,
       autofill::AutofillSuggestionTriggerSource trigger_source);
 
diff --git a/components/plus_addresses/plus_address_suggestion_generator_unittest.cc b/components/plus_addresses/plus_address_suggestion_generator_unittest.cc
index eb4ea46..51ae979 100644
--- a/components/plus_addresses/plus_address_suggestion_generator_unittest.cc
+++ b/components/plus_addresses/plus_address_suggestion_generator_unittest.cc
@@ -273,11 +273,11 @@
       autofill::test::CreateTestPasswordFormData());
   ASSERT_THAT(login_form.fields(), SizeIs(2));
   const autofill::FormFieldData focused_field = login_form.fields()[0];
-  const base::flat_map<FieldGlobalId, autofill::FieldTypeGroup>
-      form_field_type_groups = {
-          {focused_field.global_id(), autofill::FieldTypeGroup::kUsernameField},
-          {login_form.fields()[1].global_id(),
-           autofill::FieldTypeGroup::kPasswordField}};
+  const base::flat_map<FieldGlobalId, autofill::FieldTypeGroupSet>
+      form_field_type_groups = {{focused_field.global_id(),
+                                 {autofill::FieldTypeGroup::kUsernameField}},
+                                {login_form.fields()[1].global_id(),
+                                 {autofill::FieldTypeGroup::kPasswordField}}};
   PasswordFormClassification classification;
   classification.type = PasswordFormClassification::Type::kLoginForm;
   classification.username_field = focused_field.global_id();
@@ -308,12 +308,13 @@
   form = SetGeneratedFrameTokenAndHostFormId(std::move(form));
   ASSERT_THAT(form.fields(), SizeIs(3));
   const autofill::FormFieldData focused_field = form.fields()[0];
-  const base::flat_map<FieldGlobalId, autofill::FieldTypeGroup>
+  const base::flat_map<FieldGlobalId, autofill::FieldTypeGroupSet>
       form_field_type_groups = {
-          {focused_field.global_id(), autofill::FieldTypeGroup::kUsernameField},
+          {focused_field.global_id(),
+           {autofill::FieldTypeGroup::kUsernameField}},
           {form.fields()[1].global_id(),
-           autofill::FieldTypeGroup::kPasswordField},
-          {form.fields()[2].global_id(), autofill::FieldTypeGroup::kName}};
+           {autofill::FieldTypeGroup::kPasswordField}},
+          {form.fields()[2].global_id(), {autofill::FieldTypeGroup::kName}}};
   PasswordFormClassification classification;
   classification.type = PasswordFormClassification::Type::kLoginForm;
   classification.username_field = focused_field.global_id();
diff --git a/components/safe_browsing/DEPS b/components/safe_browsing/DEPS
index ccf7ebc..78b72394 100644
--- a/components/safe_browsing/DEPS
+++ b/components/safe_browsing/DEPS
@@ -1,7 +1,7 @@
 include_rules = [
   # NOTE: Dependencies on signin and sync are restricted to specific
-  # subdirectories to facilitate reuse of this component on WebLayer, which
-  # doesn't use signin or sync.
+  # subdirectories to facilitate reuse of this component in embedders which
+  # don't use signin or sync.
   "+components/content_settings/core/browser",
   "+components/enterprise/connectors",
   "+components/grit/safe_browsing_resources.h",
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 7b9605d4..2dfb838f 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_host.cc
@@ -1275,6 +1275,7 @@
         &phishing_image_embedder_);
 
     if (phishing_image_embedder_.is_bound()) {
+      image_embedding_start_time_ = tick_clock_->NowTicks();
       phishing_image_embedder_->StartImageEmbedding(
           current_url_,
           base::BindOnce(&ClientSideDetectionHost::PhishingImageEmbeddingDone,
@@ -1294,8 +1295,21 @@
     std::optional<bool> did_match_high_confidence_allowlist,
     mojom::PhishingImageEmbeddingResult result,
     std::optional<mojo_base::ProtoWrapper> image_feature_embedding) {
+  std::string request_type_name =
+      GetRequestTypeName(verdict->client_side_detection_type());
+  base::TimeDelta image_embedding_duration =
+      base::TimeTicks::Now() - image_embedding_start_time_;
+  base::UmaHistogramMediumTimes(
+      "SBClientPhishing.PhishingImageEmbeddingDuration",
+      image_embedding_duration);
+  base::UmaHistogramMediumTimes(
+      "SBClientPhishing.PhishingImageEmbeddingDuration." + request_type_name,
+      image_embedding_duration);
   base::UmaHistogramEnumeration("SBClientPhishing.PhishingImageEmbeddingResult",
                                 result);
+  base::UmaHistogramEnumeration(
+      "SBClientPhishing.PhishingImageEmbeddingResult." + request_type_name,
+      result);
   if (result == mojom::PhishingImageEmbeddingResult::kSuccess) {
     std::optional<ImageFeatureEmbedding> embedding;
     if (image_feature_embedding.has_value()) {
diff --git a/components/safe_browsing/content/browser/client_side_detection_host.h b/components/safe_browsing/content/browser/client_side_detection_host.h
index 987bac8e..2b387b1 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.h
+++ b/components/safe_browsing/content/browser/client_side_detection_host.h
@@ -430,6 +430,8 @@
 
   // Records the start time of when phishing detection started.
   base::TimeTicks phishing_detection_start_time_;
+  // Records the start time of when image embedding started.
+  base::TimeTicks image_embedding_start_time_;
   raw_ptr<const base::TickClock> tick_clock_;
 
   std::unique_ptr<Delegate> delegate_;
diff --git a/components/safe_browsing/content/browser/safe_browsing_blocking_page.h b/components/safe_browsing/content/browser/safe_browsing_blocking_page.h
index 1d16f7d5..18d0e0a 100644
--- a/components/safe_browsing/content/browser/safe_browsing_blocking_page.h
+++ b/components/safe_browsing/content/browser/safe_browsing_blocking_page.h
@@ -43,10 +43,6 @@
 class SharedURLLoaderFactory;
 }
 
-namespace weblayer {
-class WebLayerSafeBrowsingBlockingPageFactory;
-}
-
 namespace safe_browsing {
 
 class SafeBrowsingNavigationObserverManager;
@@ -73,7 +69,6 @@
 
  protected:
   friend class ChromeSafeBrowsingBlockingPageFactory;
-  friend class weblayer::WebLayerSafeBrowsingBlockingPageFactory;
   friend class SafeBrowsingBlockingPageTestBase;
   friend class SafeBrowsingBlockingPageBrowserTest;
   friend class SafeBrowsingBlockingQuietPageFactoryImpl;
diff --git a/components/safe_browsing/content/browser/ui_manager.cc b/components/safe_browsing/content/browser/ui_manager.cc
index 7f9ae9f..d3ce8de 100644
--- a/components/safe_browsing/content/browser/ui_manager.cc
+++ b/components/safe_browsing/content/browser/ui_manager.cc
@@ -241,8 +241,7 @@
                                                 WebContents* web_contents) {
   return web_contents &&
          hit_report->extended_reporting_level != SBER_LEVEL_OFF &&
-         !web_contents->GetBrowserContext()->IsOffTheRecord() &&
-         delegate_->IsSendingOfHitReportsEnabled();
+         !web_contents->GetBrowserContext()->IsOffTheRecord();
 }
 
 bool SafeBrowsingUIManager::ShouldSendClientSafeBrowsingWarningShownReport(
diff --git a/components/safe_browsing/content/browser/ui_manager.h b/components/safe_browsing/content/browser/ui_manager.h
index bfbad53..9ede9f1 100644
--- a/components/safe_browsing/content/browser/ui_manager.h
+++ b/components/safe_browsing/content/browser/ui_manager.h
@@ -118,14 +118,6 @@
 
     // Returns true if metrics reporting is enabled.
     virtual bool IsMetricsAndCrashReportingEnabled() = 0;
-
-    // Returns true if sending of hit reports is enabled, in which case
-    // SafeBrowsingUIManager will send hit reports when it deems the context
-    // appropriate to do so (see ShouldSendHitReport()). If this method returns
-    // false, SafeBrowsingUIManager will never send hit reports.
-    // TODO(crbug.com/40780174): Eliminate this method if/once hit report
-    // sending is enabled in WebLayer.
-    virtual bool IsSendingOfHitReportsEnabled() = 0;
   };
 
   SafeBrowsingUIManager(
diff --git a/components/safe_browsing/content/browser/ui_manager_unittest.cc b/components/safe_browsing/content/browser/ui_manager_unittest.cc
index fed8644..f61716c 100644
--- a/components/safe_browsing/content/browser/ui_manager_unittest.cc
+++ b/components/safe_browsing/content/browser/ui_manager_unittest.cc
@@ -226,8 +226,6 @@
   }
   bool IsMetricsAndCrashReportingEnabled() override { return false; }
 
-  bool IsSendingOfHitReportsEnabled() override { return false; }
-
   void set_is_hosting_extension(bool is_hosting_extension) {
     is_hosting_extension_ = is_hosting_extension;
   }
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc
index 50a99946..54a2d53 100644
--- a/components/search_engines/template_url.cc
+++ b/components/search_engines/template_url.cc
@@ -626,11 +626,11 @@
 
   // We need a search term in the template URL to extract something.
   if (search_term_key_.empty() &&
-      (search_term_key_location_ != url::Parsed::PATH))
+      search_term_key_location_ != url::Parsed::PATH)
     return false;
 
   // Host, port, and path must match.
-  if ((url.host() != host_) || (url.port() != port_) ||
+  if (url.host() != host_ || url.port() != port_ ||
       (!PathIsEqual(url) && (search_term_key_location_ != url::Parsed::PATH))) {
     return false;
   }
@@ -1808,7 +1808,7 @@
                 // It would be useful to disambiguate between regional variants
                 // of some engines that could be using different icons. It is
                 // not a use case we have for now, so that's unnecessary.
-                /*regional_prepopulated_engines=*/ {});
+                /*regional_prepopulated_engines=*/{});
 
     if (reference_builtin_engine &&
         reference_builtin_engine->base_builtin_resource_id) {
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 41a957b..9e697795b 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -65,9 +65,9 @@
 #include "components/sync/base/features.h"
 #include "components/sync/model/sync_change.h"
 #include "components/sync/model/sync_change_processor.h"
+#include "components/sync/protocol/entity_data.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
 #include "components/sync/protocol/search_engine_specifics.pb.h"
-#include "components/sync/protocol/entity_data.h"
 #include "components/url_formatter/url_fixer.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
@@ -169,9 +169,9 @@
   return FindTemplateURL(template_urls, turl) != template_urls->end();
 }
 
-bool IsCreatedByExtension(const TemplateURL* template_url) {
-  return template_url->type() == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION ||
-         template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION;
+bool IsCreatedByExtension(const TemplateURL& template_url) {
+  return template_url.type() == TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION ||
+         template_url.type() == TemplateURL::OMNIBOX_API_EXTENSION;
 }
 
 // Check if `is_active` status should be merged.  This is true if the
@@ -760,7 +760,7 @@
 TemplateURL* TemplateURLService::Add(
     std::unique_ptr<TemplateURL> template_url) {
   DCHECK(template_url);
-  DCHECK(!IsCreatedByExtension(template_url.get()) ||
+  DCHECK(!IsCreatedByExtension(*template_url.get()) ||
          (!FindTemplateURLForExtension(
               template_url->GetExtensionInfo()->extension_id,
               template_url->type()) &&
@@ -1000,7 +1000,7 @@
                                           const std::u16string& title,
                                           const std::u16string& keyword,
                                           const std::string& search_url) {
-  DCHECK(!IsCreatedByExtension(url));
+  DCHECK(!IsCreatedByExtension(*url));
   DCHECK(!keyword.empty());
   DCHECK(!search_url.empty());
 
@@ -1207,7 +1207,7 @@
 
   Scoper scoper(this);
   for (TemplateURL* turl : urls_for_host_copy) {
-    if (!IsCreatedByExtension(turl) &&
+    if (!IsCreatedByExtension(*turl) &&
         turl->policy_origin() !=
             TemplateURLData::PolicyOrigin::kSearchAggregator &&
         turl->IsSearchURL(potential_search_url, search_terms_data()) &&
@@ -1238,7 +1238,7 @@
   // Omnibox keywords cannot be made default. Extension-controlled search
   // engines can be made default only by the extension itself because they
   // aren't persisted.
-  DCHECK(!url || !IsCreatedByExtension(url));
+  DCHECK(!url || !IsCreatedByExtension(*url));
   if (url) {
     url->set_is_active(TemplateURLData::ActiveStatus::kTrue);
   }
@@ -2467,11 +2467,11 @@
   }
 
   pref_change_registrar_.Init(&prefs_.get());
-    pref_change_registrar_.Add(
-        prefs::kDefaultSearchProviderGUID,
-        base::BindRepeating(
-            &TemplateURLService::OnDefaultSearchProviderGUIDChanged,
-            base::Unretained(this)));
+  pref_change_registrar_.Add(
+      prefs::kDefaultSearchProviderGUID,
+      base::BindRepeating(
+          &TemplateURLService::OnDefaultSearchProviderGUIDChanged,
+          base::Unretained(this)));
 
   DefaultSearchManager::Source source = DefaultSearchManager::FROM_USER;
   const TemplateURLData* dse =
@@ -2745,7 +2745,7 @@
       // later after iteration.
       // Note: Update() will replace the entry from the container of this
       // iterator, so update here directly will cause an error about it.
-      if (!IsCreatedByExtension(*i)) {
+      if (!IsCreatedByExtension(**i)) {
         visited_url = *i;
       }
     }
diff --git a/components/sensitive_content/sensitive_content_manager.cc b/components/sensitive_content/sensitive_content_manager.cc
index 5e40bbac..6d4b8eba 100644
--- a/components/sensitive_content/sensitive_content_manager.cc
+++ b/components/sensitive_content/sensitive_content_manager.cc
@@ -84,8 +84,8 @@
   if (const autofill::FormStructure* form =
           manager.FindCachedFormById(form_id)) {
     for (const std::unique_ptr<AutofillField>& field : form->fields()) {
-      const bool field_is_sensitive =
-          IsSensitiveAutofillType(field->Type().GetStorableType());
+      const bool field_is_sensitive = std::ranges::any_of(
+          field->Type().GetTypes(), &IsSensitiveAutofillType);
       // The feature param check is done first because reparsing by password
       // manager (calling `ClassifyAsPasswordForm`) can take long. Moreover,
       // this feature param exists only to check whether reparsing has a
@@ -168,7 +168,8 @@
       const std::vector<std::unique_ptr<AutofillField>>& fields =
           form_structure->fields();
       for (const std::unique_ptr<AutofillField>& field : fields) {
-        if (IsSensitiveAutofillType(field->Type().GetStorableType())) {
+        if (std::ranges::any_of(field->Type().GetTypes(),
+                                &IsSensitiveAutofillType)) {
           sensitive_fields_.insert(field->global_id());
         }
       }
diff --git a/components/supervised_user/core/common/BUILD.gn b/components/supervised_user/core/common/BUILD.gn
index 68960d9..2cf1451 100644
--- a/components/supervised_user/core/common/BUILD.gn
+++ b/components/supervised_user/core/common/BUILD.gn
@@ -50,22 +50,6 @@
   ]
 }
 
-source_set("test_utils") {
-  testonly = true
-
-  sources = [
-    "features_testutils.cc",
-    "features_testutils.h",
-  ]
-
-  deps = [
-    "//base",
-    "//base/test:test_support",
-    "//components/supervised_user/core/common:features",
-    "//testing/gtest",
-  ]
-}
-
 source_set("unit_tests") {
   testonly = true
   sources = [ "features_unittest.cc" ]
diff --git a/components/supervised_user/core/common/features.cc b/components/supervised_user/core/common/features.cc
index 11875d9..18216bc 100644
--- a/components/supervised_user/core/common/features.cc
+++ b/components/supervised_user/core/common/features.cc
@@ -22,11 +22,7 @@
 // user's device.
 BASE_FEATURE(kLocalWebApprovals,
              "LocalWebApprovals",
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_IOS)
              base::FEATURE_ENABLED_BY_DEFAULT);
-#else
-             base::FEATURE_DISABLED_BY_DEFAULT);
-#endif
 
 // TODO(crbug.com/391799078): Support local web approval for subframes on
 // Desktop.
@@ -58,13 +54,16 @@
              "PacpWidgetSupportsUrlPayload",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// TODO(crbug.com/435635774): Release the interstitial v3 in all platforms.
 BASE_FEATURE(kSupervisedUserBlockInterstitialV3,
              "SupervisedUserBlockInterstitialV3",
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || \
+    BUILDFLAG(IS_IOS)
              base::FEATURE_ENABLED_BY_DEFAULT);
 #else
              base::FEATURE_DISABLED_BY_DEFAULT);
-#endif  //  BUILDFLAG(IS_IOS)
+#endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) ||
+        // BUILDFLAG(IS_IOS)
 
 bool IsGoogleBrandedBuild() {
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/components/supervised_user/core/common/features_testutils.cc b/components/supervised_user/core/common/features_testutils.cc
deleted file mode 100644
index 534ac066..0000000
--- a/components/supervised_user/core/common/features_testutils.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <string>
-
-#include "base/test/scoped_feature_list.h"
-#include "components/supervised_user/core/common/features.h"
-#include "components/supervised_user/core/common/features_testutils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace supervised_user::testing {
-
-// static
-::testing::internal::ParamGenerator<LocalWebApprovalsTestCase>
-LocalWebApprovalsTestCase::Values() {
-  return ::testing::Values(LocalWebApprovalsTestCase(true),
-                           LocalWebApprovalsTestCase(false));
-}
-::testing::internal::ParamGenerator<LocalWebApprovalsTestCase>
-LocalWebApprovalsTestCase::OnlySupported() {
-  return ::testing::Values(LocalWebApprovalsTestCase(true));
-}
-
-LocalWebApprovalsTestCase::LocalWebApprovalsTestCase(
-    bool is_local_web_approvals_supported)
-    : is_local_web_approvals_supported_(is_local_web_approvals_supported) {}
-
-std::unique_ptr<base::test::ScopedFeatureList>
-LocalWebApprovalsTestCase::MakeFeatureList() {
-  auto feature_list = std::make_unique<base::test::ScopedFeatureList>();
-  if (is_local_web_approvals_supported_) {
-    feature_list->InitAndEnableFeature(kLocalWebApprovals);
-  } else {
-    feature_list->InitAndDisableFeature(kLocalWebApprovals);
-  }
-  return feature_list;
-}
-
-std::string LocalWebApprovalsTestCase::ToString() const {
-  if (is_local_web_approvals_supported_) {
-    return "LocalWebApprovalsSupported";
-  } else {
-    return "LocalWebApprovalsUnsupported";
-  }
-}
-
-}  // namespace supervised_user::testing
diff --git a/components/supervised_user/core/common/features_testutils.h b/components/supervised_user/core/common/features_testutils.h
deleted file mode 100644
index f7a3db9..0000000
--- a/components/supervised_user/core/common/features_testutils.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_TESTUTILS_H_
-#define COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_TESTUTILS_H_
-
-#include <memory>
-#include <string>
-
-#include "base/test/scoped_feature_list.h"
-#include "base/types/strong_alias.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace supervised_user::testing {
-
-// Defines possible space of valid states of this test use case, and for each
-// state configures the features.
-class LocalWebApprovalsTestCase {
- public:
-  // Enumerates possible values of the test case.
-  static ::testing::internal::ParamGenerator<LocalWebApprovalsTestCase>
-  Values();
-  static ::testing::internal::ParamGenerator<LocalWebApprovalsTestCase>
-  OnlySupported();
-
-  explicit LocalWebApprovalsTestCase(bool is_local_web_approvals_supported);
-
-  // Constructs the FeatureList to be held by test fixture. ScopedFeatureList is
-  // not copyable nor assignable.
-  std::unique_ptr<base::test::ScopedFeatureList> MakeFeatureList();
-
-  // Stringifies the test name as requested (but doesn't indicate effective
-  // value).
-  std::string ToString() const;
-  explicit operator std::string() const { return ToString(); }
-
- private:
-  bool is_local_web_approvals_supported_;
-};
-}  // namespace supervised_user::testing
-
-#endif  // COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_TESTUTILS_H_
diff --git a/components/test/data/viz/backdrop_filter_blur_radius_skia_graphite.png b/components/test/data/viz/backdrop_filter_blur_radius_skia_graphite.png
index 49d9f99c..c2a9cb4 100644
--- a/components/test/data/viz/backdrop_filter_blur_radius_skia_graphite.png
+++ b/components/test/data/viz/backdrop_filter_blur_radius_skia_graphite.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_0_33skia_graphite.png b/components/test/data/viz/backdrop_filter_quality_0_33skia_graphite.png
index ede72de..ee69f79 100644
--- a/components/test/data/viz/backdrop_filter_quality_0_33skia_graphite.png
+++ b/components/test/data/viz/backdrop_filter_quality_0_33skia_graphite.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png b/components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png
index 1fc5815..ca07448 100644
--- a/components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png
+++ b/components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_rotated_skia_graphite.png b/components/test/data/viz/backdrop_filter_rotated_skia_graphite.png
index 5905bbd..0e5d6a1 100644
--- a/components/test/data/viz/backdrop_filter_rotated_skia_graphite.png
+++ b/components/test/data/viz/backdrop_filter_rotated_skia_graphite.png
Binary files differ
diff --git a/components/test/data/viz/rounded_corner_render_pass_graphite.png b/components/test/data/viz/rounded_corner_render_pass_graphite.png
index 61d5fed..9c022be 100644
--- a/components/test/data/viz/rounded_corner_render_pass_graphite.png
+++ b/components/test/data/viz/rounded_corner_render_pass_graphite.png
Binary files differ
diff --git a/components/test/data/viz/zoom_filter_skia_graphite.png b/components/test/data/viz/zoom_filter_skia_graphite.png
index 646b443..e6d5dc7 100644
--- a/components/test/data/viz/zoom_filter_skia_graphite.png
+++ b/components/test/data/viz/zoom_filter_skia_graphite.png
Binary files differ
diff --git a/components/user_data_importer/content/stable_portability_data_importer.cc b/components/user_data_importer/content/stable_portability_data_importer.cc
index 0340389..a25d0a8 100644
--- a/components/user_data_importer/content/stable_portability_data_importer.cc
+++ b/components/user_data_importer/content/stable_portability_data_importer.cc
@@ -49,7 +49,7 @@
 void StablePortabilityDataImporter::
     RustHistoryCallbackForStablePortabilityFormat::Fail() {
   if (done_callback_) {
-    std::move(done_callback_).Run(0);
+    std::move(done_callback_).Run(-1);
   }
 }
 
@@ -77,7 +77,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (!file.IsValid()) {
-    PostCallback(std::move(bookmarks_callback), 0);
+    PostCallback(std::move(bookmarks_callback), -1);
     return;
   }
 
@@ -104,14 +104,14 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!bookmark_model_) {
-    PostCallback(std::move(bookmarks_callback), 0);
+    PostCallback(std::move(bookmarks_callback), -1);
     return;
   }
 
   ASSIGN_OR_RETURN(BookmarkParser::ParsedBookmarks value, std::move(result),
                    [this, &bookmarks_callback](auto) {
                      // TODO(crbug.com/414604427): Log error to UMA.
-                     PostCallback(std::move(bookmarks_callback), 0);
+                     PostCallback(std::move(bookmarks_callback), -1);
                    });
 
   // Add the parsed bookmarks to the user's storage.
@@ -128,7 +128,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (!file.IsValid()) {
-    PostCallback(std::move(reading_list_callback), 0);
+    PostCallback(std::move(reading_list_callback), -1);
     return;
   }
 
@@ -155,14 +155,14 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!reading_list_model_) {
-    PostCallback(std::move(reading_list_callback), 0);
+    PostCallback(std::move(reading_list_callback), -1);
     return;
   }
 
   ASSIGN_OR_RETURN(BookmarkParser::ParsedBookmarks value, std::move(result),
                    [this, &reading_list_callback](auto) {
                      // TODO(crbug.com/414604427): Log error to UMA.
-                     PostCallback(std::move(reading_list_callback), 0);
+                     PostCallback(std::move(reading_list_callback), -1);
                    });
 
   // Add the parsed reading list entries to the user's storage.
@@ -227,7 +227,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (!file.IsValid()) {
-    PostCallback(std::move(history_callback), 0);
+    PostCallback(std::move(history_callback), -1);
     return;
   }
 
diff --git a/components/user_data_importer/content/stable_portability_data_importer.h b/components/user_data_importer/content/stable_portability_data_importer.h
index 73db688..2b54f1d 100644
--- a/components/user_data_importer/content/stable_portability_data_importer.h
+++ b/components/user_data_importer/content/stable_portability_data_importer.h
@@ -37,7 +37,8 @@
 class StablePortabilityDataImporter {
  public:
   // A callback used by the caller to obtain the number of successfully imported
-  // bookmarks, reading list items, or urls (for history import).
+  // bookmarks, reading list items, or history entries. In case of an error, the
+  // reported count will be -1.
   using ImportCallback = base::OnceCallback<void(int)>;
 
   // `history_service`, `bookmark_model`, and `reading_list_model` may be null,
diff --git a/components/user_data_importer/content/stable_portability_data_importer_unittest.cc b/components/user_data_importer/content/stable_portability_data_importer_unittest.cc
index b81bad9..106ad25f 100644
--- a/components/user_data_importer/content/stable_portability_data_importer_unittest.cc
+++ b/components/user_data_importer/content/stable_portability_data_importer_unittest.cc
@@ -514,6 +514,20 @@
                            ))))));
 }
 
+TEST_F(StablePortabilityDataImporterTest, Bookmarks_EmptyInput) {
+  ImportBookmarks("");
+  // Empty input data is considered an error. (In practice, this could also
+  // happen if the file read fails for some reason.)
+  EXPECT_EQ(GetNumberOfBookmarksImported(), -1);
+}
+
+TEST_F(StablePortabilityDataImporterTest, ReadingList_EmptyInput) {
+  ImportReadingList("");
+  // Empty input data is considered an error. (In practice, this could also
+  // happen if the file read fails for some reason.)
+  EXPECT_EQ(GetNumberOfReadingListImported(), -1);
+}
+
 // History parsing is only implemented on Posix systems for now, because the
 // file is passed to the Rust parser in the form of a native "fd" (file
 // descriptor).
@@ -579,6 +593,7 @@
         "title": "Google",
   })";  // Invalid JSON, missing closing brackets.
   ImportHistory(kHistoryJson);
+  // TODO(crbug.com/435386347): The result should be "-1" to indicate the error.
   EXPECT_EQ(GetNumberOfHistoryImported(), 0);
 }
 
@@ -636,13 +651,16 @@
 TEST_F(StablePortabilityDataImporterTest, CallbacksAreCalled) {
   ImportBookmarksFile(
       base::FilePath(FILE_PATH_LITERAL("/invalid/path/to/bookmarks/file")));
+  EXPECT_EQ(GetNumberOfBookmarksImported(), -1);
 
   ImportReadingListFile(
       base::FilePath(FILE_PATH_LITERAL("/invalid/path/to/reading_list/file")));
+  EXPECT_EQ(GetNumberOfReadingListImported(), -1);
 
 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
   ImportHistoryFile(
       base::FilePath(FILE_PATH_LITERAL("/invalid/path/to/history/file")));
+  EXPECT_EQ(GetNumberOfHistoryImported(), -1);
 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
 }
 
diff --git a/components/user_education/common/BUILD.gn b/components/user_education/common/BUILD.gn
index 2e47757..fb60155 100644
--- a/components/user_education/common/BUILD.gn
+++ b/components/user_education/common/BUILD.gn
@@ -48,6 +48,10 @@
     "help_bubble/help_bubble_factory_registry.h",
     "help_bubble/help_bubble_params.cc",
     "help_bubble/help_bubble_params.h",
+    "menu/highlighting_menu_button_helper.cc",
+    "menu/highlighting_menu_button_helper.h",
+    "menu/highlighting_simple_menu_model_delegate.cc",
+    "menu/highlighting_simple_menu_model_delegate.h",
     "new_badge/new_badge_controller.cc",
     "new_badge/new_badge_controller.h",
     "new_badge/new_badge_policy.cc",
diff --git a/components/user_education/common/menu/highlighting_menu_button_helper.cc b/components/user_education/common/menu/highlighting_menu_button_helper.cc
new file mode 100644
index 0000000..43dbd5d
--- /dev/null
+++ b/components/user_education/common/menu/highlighting_menu_button_helper.cc
@@ -0,0 +1,31 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/user_education/common/menu/highlighting_menu_button_helper.h"
+
+#include "base/types/pass_key.h"
+#include "components/user_education/common/feature_promo/feature_promo_controller.h"
+#include "components/user_education/common/menu/highlighting_simple_menu_model_delegate.h"
+
+namespace user_education {
+
+HighlightingMenuButtonHelper::~HighlightingMenuButtonHelper() = default;
+
+void HighlightingMenuButtonHelper::MaybeHighlight(
+    FeaturePromoController* controller,
+    ui::ElementIdentifier button_element_id,
+    HighlightingSimpleMenuModelDelegate* menu_model_delegate) {
+  if (!controller || !button_element_id) {
+    return;
+  }
+  if (const auto* spec = controller->GetCurrentPromoSpecificationForAnchor(
+          button_element_id)) {
+    menu_model_delegate->SetHighlight(
+        base::PassKey<HighlightingMenuButtonHelper>(),
+        spec->highlighted_menu_identifier(),
+        controller->CloseBubbleAndContinuePromo(*spec->feature()));
+  }
+}
+
+}  // namespace user_education
diff --git a/components/user_education/common/menu/highlighting_menu_button_helper.h b/components/user_education/common/menu/highlighting_menu_button_helper.h
new file mode 100644
index 0000000..b1b7ae76
--- /dev/null
+++ b/components/user_education/common/menu/highlighting_menu_button_helper.h
@@ -0,0 +1,36 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_MENU_BUTTON_HELPER_H_
+#define COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_MENU_BUTTON_HELPER_H_
+
+#include "components/user_education/common/menu/highlighting_simple_menu_model_delegate.h"
+#include "ui/base/interaction/element_identifier.h"
+
+namespace user_education {
+
+class FeaturePromoController;
+
+// Can be instantiated by a button to handle the case where an IPH is anchored
+// to the button, and then the button is clicked producing a menu.
+//
+// In this case, the IPH should have its bubble closed (so as not to fight with
+// the menu) and possibly highlight a menu item associated with the promo.
+class HighlightingMenuButtonHelper {
+ public:
+  virtual ~HighlightingMenuButtonHelper();
+
+  // Maybe ends an IPH owned by `controller`, anchored to `button_element_id`,
+  // and possibly highlights a menu item in `menu_model_delegate`.
+  //
+  // Most specializations of this class will hide this method and provide a
+  // simpler API to look up the controller, etc.
+  void MaybeHighlight(FeaturePromoController* controller,
+                      ui::ElementIdentifier button_element_id,
+                      HighlightingSimpleMenuModelDelegate* menu_model_delegate);
+};
+
+}  // namespace user_education
+
+#endif  // COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_MENU_BUTTON_HELPER_H_
diff --git a/components/user_education/common/menu/highlighting_simple_menu_model_delegate.cc b/components/user_education/common/menu/highlighting_simple_menu_model_delegate.cc
new file mode 100644
index 0000000..26fc178f
--- /dev/null
+++ b/components/user_education/common/menu/highlighting_simple_menu_model_delegate.cc
@@ -0,0 +1,36 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/user_education/common/menu/highlighting_simple_menu_model_delegate.h"
+
+namespace user_education {
+
+HighlightingSimpleMenuModelDelegate::~HighlightingSimpleMenuModelDelegate() =
+    default;
+
+bool HighlightingSimpleMenuModelDelegate::IsElementIdAlerted(
+    ui::ElementIdentifier element_id) const {
+  return element_id == highlighted_menu_identifier_;
+}
+
+void HighlightingSimpleMenuModelDelegate::MenuClosed(
+    ui::SimpleMenuModel* model) {
+  promo_handle_.Release();
+  OnMenuClosed(model);
+}
+
+void HighlightingSimpleMenuModelDelegate::SetHighlight(
+    base::PassKey<HighlightingMenuButtonHelper>,
+    ui::ElementIdentifier highlighted_menu_identifier,
+    FeaturePromoHandle promo_handle) {
+  highlighted_menu_identifier_ = highlighted_menu_identifier;
+  promo_handle_ = std::move(promo_handle);
+}
+
+void HighlightingSimpleMenuModelDelegate::OnMenuClosed(
+    ui::SimpleMenuModel* model) {
+  // Default is to do nothing; derived classes can add additional behavior.
+}
+
+}  // namespace user_education
diff --git a/components/user_education/common/menu/highlighting_simple_menu_model_delegate.h b/components/user_education/common/menu/highlighting_simple_menu_model_delegate.h
new file mode 100644
index 0000000..6517aaa1
--- /dev/null
+++ b/components/user_education/common/menu/highlighting_simple_menu_model_delegate.h
@@ -0,0 +1,46 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_SIMPLE_MENU_MODEL_DELEGATE_H_
+#define COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_SIMPLE_MENU_MODEL_DELEGATE_H_
+
+#include "base/types/pass_key.h"
+#include "components/user_education/common/feature_promo/feature_promo_handle.h"
+#include "ui/menus/simple_menu_model.h"
+
+namespace user_education {
+
+class HighlightingMenuButtonHelper;
+
+// Base class for menu delegates that want to support user ed highlighting.
+class HighlightingSimpleMenuModelDelegate
+    : public ui::SimpleMenuModel::Delegate {
+ public:
+  ~HighlightingSimpleMenuModelDelegate() override;
+
+  // SimpleMenuModel::Delegate:
+  bool IsElementIdAlerted(ui::ElementIdentifier element_id) const final;
+  void MenuClosed(ui::SimpleMenuModel*) final;
+
+  // When an IPH is dismissed as a menu opens, indicates the highlight to show
+  // in the menu (if any) as well as the promo handle (if any). The handle is
+  // provided so no new promos can show while the menu is open.
+  void SetHighlight(base::PassKey<HighlightingMenuButtonHelper>,
+                    ui::ElementIdentifier highlighted_menu_identifier,
+                    FeaturePromoHandle promo_handle);
+
+ protected:
+  // Called by `MenuClosed()` to provide derived classes an opportunity to
+  // perform actions; do not override `MenuClosed()` directly.
+  // Defaults to no-op.
+  virtual void OnMenuClosed(ui::SimpleMenuModel*);
+
+ private:
+  ui::ElementIdentifier highlighted_menu_identifier_;
+  FeaturePromoHandle promo_handle_;
+};
+
+}  // namespace user_education
+
+#endif  // COMPONENTS_USER_EDUCATION_COMMON_MENU_HIGHLIGHTING_SIMPLE_MENU_MODEL_DELEGATE_H_
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index 8b11204..3d2881ae4 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -152,13 +152,6 @@
       "//components/variations/android:variations_seed_jni",
     ]
   }
-
-  if (is_chromeos) {
-    deps += [
-      "//chromeos/ash/components/dbus/featured",
-      "//chromeos/ash/components/dbus/featured:proto",
-    ]
-  }
 }
 
 if (is_android) {
@@ -297,13 +290,6 @@
     "//url",
   ]
 
-  if (is_chromeos) {
-    deps += [
-      "//chromeos/ash/components/dbus/featured",
-      "//chromeos/ash/components/dbus/featured:proto",
-    ]
-  }
-
   # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and
   # enable the diagnostic by removing this line.
   configs += [ "//build/config/compiler:no_exit_time_destructors" ]
@@ -355,7 +341,7 @@
       ":variations",
       "proto",
       "//base/test:test_support",
-      "//components/variations/service:service",
+      "//components/variations/service",
       "//third_party/libprotobuf-mutator",
     ]
     seed_corpus = "fuzzers/testcases/create_trials_from_seed/"
diff --git a/components/variations/DEPS b/components/variations/DEPS
index 95ae852..ac021f6a 100644
--- a/components/variations/DEPS
+++ b/components/variations/DEPS
@@ -2,7 +2,6 @@
 # dependencies to a minimal set.
 # TODO(crbug.com/40796017): Remove components/metrics, it's only used for tests.
 include_rules = [
-  "+chromeos/ash/components/dbus/featured",
   "-components",
   "+components/compression",
   "+components/crash/android",
diff --git a/components/variations/limited_layer_entropy_cost_tracker.cc b/components/variations/limited_layer_entropy_cost_tracker.cc
index a219fca..d719638 100644
--- a/components/variations/limited_layer_entropy_cost_tracker.cc
+++ b/components/variations/limited_layer_entropy_cost_tracker.cc
@@ -34,6 +34,12 @@
 
 // Returns the number of bits of entropy used by a single study.
 double GetEntropyUsedByStudy(const Study& study) {
+  if (study.consistency() == Study::SESSION) {
+    // Session-consistent studies do not consume entropy. They are randomized
+    // for each Chrome browser process' lifetime; they use neither the low
+    // entropy source nor the limited entropy randomization source.
+    return 0.0;
+  }
   // Use uint32_t to match the type of `probability_weight` field in the
   // experiment proto.
   uint32_t min_weight = std::numeric_limits<uint32_t>::max();
diff --git a/components/variations/limited_layer_entropy_cost_tracker_unittest.cc b/components/variations/limited_layer_entropy_cost_tracker_unittest.cc
index a72d15f..a072b62 100644
--- a/components/variations/limited_layer_entropy_cost_tracker_unittest.cc
+++ b/components/variations/limited_layer_entropy_cost_tracker_unittest.cc
@@ -79,6 +79,7 @@
                           layer_member_reference = std::nullopt) {
   Study study;
   study.set_name("test_study");
+  study.set_consistency(Study::PERMANENT);
 
   for (size_t i = 0; i < experiments.size(); ++i) {
     Study_Experiment* experiment_to_add = study.add_experiment();
@@ -462,6 +463,24 @@
 }
 
 TEST_F(LimitedLayerEntropyCostTrackerTest,
+       TestAddEntropyUsedByStudy_SessionConsistency) {
+  std::vector<Study::Experiment> experiments = {
+      CreateTriggerExperiment(25, 100001), CreateTriggerExperiment(25, 100002),
+      CreateExperiment(50)};
+  auto test_layer = CreateLayer(
+      kTestLayerId, /*num_slots=*/100, /*entropy_mode=*/Layer::LIMITED,
+      {CreateLayerMember(kTestLayerMemberId, {{0, 99}})});
+  auto test_study = CreateTestStudy(
+      experiments,
+      CreateLayerMemberReference(kTestLayerId, {kTestLayerMemberId}));
+  test_study.set_consistency(Study::SESSION);
+  LimitedLayerEntropyCostTracker limited_entropy_tracker(test_layer, 13);
+
+  EXPECT_TRUE(limited_entropy_tracker.AddEntropyUsedByStudy(test_study));
+  EXPECT_EQ(0, limited_entropy_tracker.GetMaxEntropyUsedForTesting());
+}
+
+TEST_F(LimitedLayerEntropyCostTrackerTest,
        TestAddEntropyUsedByStudy_StudiesOfDifferentEntropyInLayerMember) {
   // TODO(siakabaro): The test name doesn't seems to match the code?
   auto test_layer = CreateLayer(
diff --git a/components/variations/service/limited_entropy_randomization_unittest.cc b/components/variations/service/limited_entropy_randomization_unittest.cc
index cd7c184..c2c488e5 100644
--- a/components/variations/service/limited_entropy_randomization_unittest.cc
+++ b/components/variations/service/limited_entropy_randomization_unittest.cc
@@ -88,6 +88,7 @@
 Study CreateTestStudy(const std::vector<Study::Experiment>& experiments) {
   Study study;
   study.set_name("test_study");
+  study.set_consistency(Study::PERMANENT);
 
   std::vector<Study::Experiment> copied_experiments(experiments);
   for (size_t i = 0; i < copied_experiments.size(); ++i) {
@@ -237,6 +238,26 @@
   histogram_tester_.ExpectTotalCount(kSeedRejectionReasonHistogram, 0);
 }
 
+// This is exactly the same test as SeedRejection_EntropyOveruse, below, except
+// that the study has session consistency so it does not consume entropy.
+TEST_F(LimitedEntropyRandomizationTest, SessionConsistency) {
+  // Creates a layer with LIMITED entropy mode that takes 1 bit of entropy from
+  // the layer member.
+  auto test_layer = CreateLayer(
+      /*layer_id=*/kTestLayerId, /*num_slots=*/100,
+      /*entropy_mode=*/Layer::LIMITED,
+      /*layer_members=*/{CreateLayerMember(kTestLayerMemberId, {{0, 49}})});
+  auto test_study = CreateTestStudy(CreateExperimentsWithTwoBitsOfEntropy(),
+                                     CreateLayerMemberReference(
+                                         kTestLayerId, {kTestLayerMemberId}));
+  test_study.set_consistency(Study::SESSION);
+  auto test_seed = CreateTestSeed({test_layer}, {test_study});
+  // Seed should not be rejected since the study is session consistency, which
+  // does not consume entropy.
+  EXPECT_FALSE(SeedHasMisconfiguredEntropy(client_state_, test_seed, 2));
+  histogram_tester_.ExpectTotalCount(kSeedRejectionReasonHistogram, 0);
+}
+
 TEST_F(LimitedEntropyRandomizationTest, SeedRejection_EntropyOveruse) {
   // Creates a layer with LIMITED entropy mode that takes 1 bit of entropy from
   // the layer member.
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc
index d45f1d2..2787a0f 100644
--- a/components/variations/service/variations_field_trial_creator.cc
+++ b/components/variations/service/variations_field_trial_creator.cc
@@ -216,7 +216,7 @@
           switches::kVariationsOverrideCountry));
   return !override_country.empty()
              ? override_country
-             : std::string(seed_store_->GetLatestCountry());
+             : seed_store_->GetLatestCountry();
 }
 
 bool VariationsFieldTrialCreator::SetUpFieldTrials(
diff --git a/components/variations/service/variations_field_trial_creator_unittest.cc b/components/variations/service/variations_field_trial_creator_unittest.cc
index 75eddd79..82fe01d 100644
--- a/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -121,6 +121,7 @@
   VariationsSeed seed;
   Study* study = seed.add_study();
   study->set_name(kTestSeedStudyName);
+  study->set_consistency(Study::PERMANENT);
   study->set_default_experiment_name(kTestSeedExperimentName);
   Study_Experiment* experiment = study->add_experiment();
   experiment->set_name(kTestSeedExperimentName);
@@ -150,6 +151,7 @@
 
   auto* study = seed.add_study();
   study->set_name(kTestLimitedLayerStudyName);
+  study->set_consistency(Study::PERMANENT);
 
   auto* experiment = study->add_experiment();
   experiment->set_name(kTestSeedExperimentName);
@@ -188,6 +190,7 @@
   // Add a study that uses the tiny member.
   Study* study = seed.add_study();
   study->set_name(kTestLimitedLayerStudyName);
+  study->set_consistency(Study::PERMANENT);
   auto* layer_member_reference = study->mutable_layer();
   layer_member_reference->set_layer_id(1);
   layer_member_reference->add_layer_member_ids(1);
diff --git a/components/variations/variations_seed_store.cc b/components/variations/variations_seed_store.cc
index 9ca2270..bd0fdcec 100644
--- a/components/variations/variations_seed_store.cc
+++ b/components/variations/variations_seed_store.cc
@@ -38,12 +38,6 @@
 #include "components/variations/metrics.h"
 #endif  // BUILDFLAG(IS_ANDROID)
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "base/functional/callback.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#include "chromeos/ash/components/dbus/featured/featured_client.h"
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 #if BUILDFLAG(IS_IOS)
 #include "components/variations/metrics.h"
 #endif  // BUILDFLAG(IS_IOS)
@@ -65,12 +59,6 @@
 };
 
 
-#if BUILDFLAG(IS_CHROMEOS)
-// Number of attempts to send the safe seed from Chrome to CrOS platforms before
-// giving up.
-constexpr int kSendPlatformSafeSeedMaxAttempts = 2;
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 // LINT.IfChange
 // The name of the seed file that stores the latest seed data.
 const base::FilePath::CharType kSeedFilename[] =
@@ -769,16 +757,6 @@
     // match the latest seed's.
     safe_seed_store_->SetFetchTime(latest_seed.client_fetch_time);
   }
-
-#if BUILDFLAG(IS_CHROMEOS)
-  // `SendSafeSeedToPlatform` will send the safe seed at most twice and should
-  // only be called if the seed is successfully validated.
-  // This is a best effort attempt and it is possible that the safe seed for
-  // platform and Chrome are different if sending the safe seed fails twice.
-  send_seed_to_platform_attempts_ = 0;
-  SendSafeSeedToPlatform(GetSafeSeedStateForPlatform(
-      seed, seed_milestone, client_state, seed_fetch_time));
-#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
 // static
@@ -916,49 +894,4 @@
   return true;
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
-featured::SeedDetails VariationsSeedStore::GetSafeSeedStateForPlatform(
-    const ValidatedSeed& seed,
-    const int seed_milestone,
-    const ClientFilterableState& client_state,
-    const base::Time seed_fetch_time) {
-  featured::SeedDetails safe_seed;
-  safe_seed.set_b64_compressed_data(seed.base64_seed_data);
-  safe_seed.set_locale(client_state.locale);
-  safe_seed.set_milestone(seed_milestone);
-  safe_seed.set_permanent_consistency_country(
-      client_state.permanent_consistency_country);
-  safe_seed.set_session_consistency_country(
-      client_state.session_consistency_country);
-  safe_seed.set_signature(seed.base64_seed_signature);
-  safe_seed.set_date(
-      client_state.reference_date.ToDeltaSinceWindowsEpoch().InMilliseconds());
-  safe_seed.set_fetch_time(
-      seed_fetch_time.ToDeltaSinceWindowsEpoch().InMilliseconds());
-
-  return safe_seed;
-}
-
-void VariationsSeedStore::MaybeRetrySendSafeSeed(
-    const featured::SeedDetails& safe_seed,
-    bool success) {
-  // Do not retry after two failed attempts.
-  if (!success &&
-      send_seed_to_platform_attempts_ < kSendPlatformSafeSeedMaxAttempts) {
-    SendSafeSeedToPlatform(safe_seed);
-  }
-}
-
-void VariationsSeedStore::SendSafeSeedToPlatform(
-    const featured::SeedDetails& safe_seed) {
-  send_seed_to_platform_attempts_++;
-  ash::featured::FeaturedClient* client = ash::featured::FeaturedClient::Get();
-  if (client) {
-    client->HandleSeedFetched(
-        safe_seed, base::BindOnce(&VariationsSeedStore::MaybeRetrySendSafeSeed,
-                                  weak_ptr_factory_.GetWeakPtr(), safe_seed));
-  }
-}
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 }  // namespace variations
diff --git a/components/variations/variations_seed_store.h b/components/variations/variations_seed_store.h
index 65fdcb4c1..677d0e0 100644
--- a/components/variations/variations_seed_store.h
+++ b/components/variations/variations_seed_store.h
@@ -24,10 +24,6 @@
 #include "components/variations/seed_response.h"
 #include "components/variations/variations_safe_seed_store.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 class PrefService;
 class PrefRegistrySimple;
 
@@ -414,28 +410,6 @@
   // Handles reads and writes to seed files.
   std::unique_ptr<SeedReaderWriter> seed_reader_writer_;
 
-#if BUILDFLAG(IS_CHROMEOS)
-  // Gets the combined server and client state used for early boot variations
-  // platform disaster recovery.
-  featured::SeedDetails GetSafeSeedStateForPlatform(
-      const ValidatedSeed& seed,
-      const int seed_milestone,
-      const ClientFilterableState& client_state,
-      const base::Time seed_fetch_time);
-
-  // Retries sending the safe seed to platform. Does not retry after two failed
-  // attempts.
-  void MaybeRetrySendSafeSeed(const featured::SeedDetails& safe_seed,
-                              bool success);
-
-  // Sends the safe seed to the platform.
-  void SendSafeSeedToPlatform(const featured::SeedDetails& safe_seed);
-
-  // A counter that keeps track of how many times the current safe seed is sent
-  // to platform.
-  size_t send_seed_to_platform_attempts_ = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<VariationsSeedStore> weak_ptr_factory_{this};
diff --git a/components/variations/variations_seed_store_unittest.cc b/components/variations/variations_seed_store_unittest.cc
index a8ad80e..4070514 100644
--- a/components/variations/variations_seed_store_unittest.cc
+++ b/components/variations/variations_seed_store_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_entropy_provider.h"
-#include "base/test/protobuf_matchers.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
@@ -42,15 +41,9 @@
 #include "components/variations/android/variations_seed_bridge.h"
 #endif  // BUILDFLAG(IS_ANDROID)
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "chromeos/ash/components/dbus/featured/fake_featured_client.h"
-#include "chromeos/ash/components/dbus/featured/featured.pb.h"
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 namespace variations {
 namespace {
 
-using ::base::test::EqualsProto;
 using ::testing::IsEmpty;
 using ::testing::Not;
 
@@ -2482,177 +2475,4 @@
 }
 #endif  // BUILDFLAG(IS_ANDROID)
 
-#if BUILDFLAG(IS_CHROMEOS)
-const featured::SeedDetails CreateDummySafeSeed(
-    ClientFilterableState* client_state,
-    base::Time fetch_time_to_store) {
-  featured::SeedDetails expected_seed;
-  expected_seed.set_b64_compressed_data(kTestSeedData.base64_compressed_data);
-  expected_seed.set_signature(kTestSeedData.base64_signature);
-  expected_seed.set_milestone(92);
-  expected_seed.set_locale(client_state->locale);
-  expected_seed.set_date(
-      client_state->reference_date.ToDeltaSinceWindowsEpoch().InMilliseconds());
-  expected_seed.set_permanent_consistency_country(
-      client_state->permanent_consistency_country);
-  expected_seed.set_session_consistency_country(
-      client_state->session_consistency_country);
-  expected_seed.set_fetch_time(
-      fetch_time_to_store.ToDeltaSinceWindowsEpoch().InMilliseconds());
-  return expected_seed;
-}
-
-// Checks that |platform_data| and |expected_data| deserialize to the same
-// VariationsSeed proto.
-// |platform_data| and |expected_data| are base64_compressed forms of seed data.
-void ExpectSeedData(const std::string& platform_data,
-                    const std::string& expected_data) {
-  std::string decoded_platform_data;
-  EXPECT_TRUE(base::Base64Decode(platform_data, &decoded_platform_data));
-  std::string uncompressed_decoded_platform_data;
-  EXPECT_TRUE(compression::GzipUncompress(decoded_platform_data,
-                                          &uncompressed_decoded_platform_data));
-  VariationsSeed platform_seed;
-  EXPECT_TRUE(
-      platform_seed.ParseFromString(uncompressed_decoded_platform_data));
-
-  std::string decoded_expected_data;
-  EXPECT_TRUE(base::Base64Decode(expected_data, &decoded_expected_data));
-  std::string uncompressed_decoded_expected_data;
-  EXPECT_TRUE(compression::GzipUncompress(decoded_expected_data,
-                                          &uncompressed_decoded_expected_data));
-  VariationsSeed expected_seed;
-  EXPECT_TRUE(
-      expected_seed.ParseFromString(uncompressed_decoded_expected_data));
-
-  EXPECT_THAT(platform_seed, EqualsProto(expected_seed));
-}
-
-// Manually verifying each field in featured::SeedDetails rather than using
-// EqualsProto is necessary because the
-// featured::SeedDetails::b64_compressed_data field may be different between
-// |platform| and |expected| even if the data unserializes to the same
-// VariationsSeed. This could be caused by implementation differences between
-// different versions of compression::GzipCompress.
-//
-// To accurately compare two featured::SeedDetails protos, the
-// `b64_compressed_data` should be deserialized into a VariationsSeed proto and
-// the two VariationsSeed protos should be compared.
-void ExpectSafeSeed(const featured::SeedDetails& platform,
-                    const featured::SeedDetails expected) {
-  ExpectSeedData(platform.b64_compressed_data(),
-                 expected.b64_compressed_data());
-  EXPECT_EQ(platform.locale(), expected.locale());
-  EXPECT_EQ(platform.milestone(), expected.milestone());
-  EXPECT_EQ(platform.permanent_consistency_country(),
-            expected.permanent_consistency_country());
-  EXPECT_EQ(platform.session_consistency_country(),
-            expected.session_consistency_country());
-  EXPECT_EQ(platform.signature(), expected.signature());
-  EXPECT_EQ(platform.date(), expected.date());
-  EXPECT_EQ(platform.fetch_time(), expected.fetch_time());
-}
-
-TEST_P(StoreSafeSeedDataAllGroupsTest,
-       SendSafeSeedToPlatform_SucceedFirstAttempt) {
-  TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath(),
-                                     /*signature_verification_needed=*/true);
-  ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial),
-            GetParam().field_trial_group);
-
-  ash::featured::FeaturedClient::InitializeFake();
-  ash::featured::FakeFeaturedClient* client =
-      ash::featured::FakeFeaturedClient::Get();
-  client->AddResponse(true);
-
-  std::unique_ptr<ClientFilterableState> client_state =
-      CreateDummyClientFilterableState();
-  const base::Time fetch_time_to_store = base::Time::Now() - base::Hours(1);
-  featured::SeedDetails expected_platform_seed =
-      CreateDummySafeSeed(client_state.get(), fetch_time_to_store);
-  std::string expected_seed_data;
-  ASSERT_TRUE(base::Base64Decode(kTestSeedData.base64_uncompressed_data,
-                                 &expected_seed_data));
-
-  // Verify that storing the safe seed succeeded.
-  ASSERT_TRUE(seed_store.StoreSafeSeed(
-      expected_seed_data, expected_platform_seed.signature(),
-      expected_platform_seed.milestone(), *client_state, fetch_time_to_store));
-
-  // Verify that the validated safe seed was received on Platform.
-  ExpectSafeSeed(client->latest_safe_seed(), expected_platform_seed);
-  EXPECT_EQ(client->handle_seed_fetched_attempts(), 1);
-
-  ash::featured::FeaturedClient::Shutdown();
-}
-
-TEST_P(StoreSafeSeedDataAllGroupsTest,
-       SendSafeSeedToPlatform_FailFirstAttempt) {
-  TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath(),
-                                     /*signature_verification_needed=*/true);
-  ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial),
-            GetParam().field_trial_group);
-
-  ash::featured::FeaturedClient::InitializeFake();
-  ash::featured::FakeFeaturedClient* client =
-      ash::featured::FakeFeaturedClient::Get();
-  client->AddResponse(false);
-  client->AddResponse(true);
-
-  std::unique_ptr<ClientFilterableState> client_state =
-      CreateDummyClientFilterableState();
-  const base::Time fetch_time_to_store = base::Time::Now() - base::Hours(1);
-  featured::SeedDetails expected_platform_seed =
-      CreateDummySafeSeed(client_state.get(), fetch_time_to_store);
-  std::string expected_seed_data;
-  ASSERT_TRUE(base::Base64Decode(kTestSeedData.base64_uncompressed_data,
-                                 &expected_seed_data));
-
-  // Verify that storing the safe seed succeeded.
-  ASSERT_TRUE(seed_store.StoreSafeSeed(
-      expected_seed_data, expected_platform_seed.signature(),
-      expected_platform_seed.milestone(), *client_state, fetch_time_to_store));
-
-  // Verify that the validated safe seed was received on Platform.
-  ExpectSafeSeed(client->latest_safe_seed(), expected_platform_seed);
-  EXPECT_EQ(client->handle_seed_fetched_attempts(), 2);
-
-  ash::featured::FeaturedClient::Shutdown();
-}
-
-TEST_P(StoreSafeSeedDataAllGroupsTest, SendSafeSeedToPlatform_FailTwoAttempts) {
-  TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath(),
-                                     /*signature_verification_needed=*/true);
-  ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial),
-            GetParam().field_trial_group);
-
-  ash::featured::FeaturedClient::InitializeFake();
-  ash::featured::FakeFeaturedClient* client =
-      ash::featured::FakeFeaturedClient::Get();
-  client->AddResponse(false);
-  client->AddResponse(false);
-
-  std::unique_ptr<ClientFilterableState> client_state =
-      CreateDummyClientFilterableState();
-  const base::Time fetch_time_to_store = base::Time::Now() - base::Hours(1);
-  featured::SeedDetails seed =
-      CreateDummySafeSeed(client_state.get(), fetch_time_to_store);
-  std::string seed_data;
-  ASSERT_TRUE(
-      base::Base64Decode(kTestSeedData.base64_uncompressed_data, &seed_data));
-
-  // Verify that storing the safe seed succeeded.
-  ASSERT_TRUE(seed_store.StoreSafeSeed(seed_data, seed.signature(),
-                                       seed.milestone(), *client_state,
-                                       fetch_time_to_store));
-
-  // Verify that the validated safe seed was not received on Platform.
-  featured::SeedDetails empty_seed;
-  EXPECT_THAT(client->latest_safe_seed(), EqualsProto(empty_seed));
-  EXPECT_EQ(client->handle_seed_fetched_attempts(), 2);
-
-  ash::featured::FeaturedClient::Shutdown();
-}
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
 }  // namespace variations
diff --git a/components/viz/common/frame_sinks/copy_output_request.cc b/components/viz/common/frame_sinks/copy_output_request.cc
index 91ef0cd..adcf0c3 100644
--- a/components/viz/common/frame_sinks/copy_output_request.cc
+++ b/components/viz/common/frame_sinks/copy_output_request.cc
@@ -31,6 +31,8 @@
       return "I420";
     case viz::CopyOutputRequest::ResultFormat::NV12:
       return "NV12";
+    case viz::CopyOutputRequest::ResultFormat::RGBAF16:
+      return "RGBAF16";
   }
 }
 
@@ -120,7 +122,8 @@
   DCHECK(!blit_request_);
   DCHECK_EQ(result_destination(), ResultDestination::kSharedImage);
   DCHECK(result_format() == ResultFormat::NV12 ||
-         result_format() == ResultFormat::RGBA);
+         result_format() == ResultFormat::RGBA ||
+         result_format() == ResultFormat::RGBAF16);
   DCHECK(has_result_selection());
 
   if (result_format() == ResultFormat::NV12) {
diff --git a/components/viz/common/frame_sinks/copy_output_request.h b/components/viz/common/frame_sinks/copy_output_request.h
index bd000dfc..b02aad7 100644
--- a/components/viz/common/frame_sinks/copy_output_request.h
+++ b/components/viz/common/frame_sinks/copy_output_request.h
@@ -138,9 +138,10 @@
   // called before blit request was set on the copy request.
   void set_result_selection(const gfx::Rect& selection) {
     DCHECK(result_format_ == ResultFormat::RGBA ||
+           result_format_ == ResultFormat::RGBAF16 ||
            (selection.width() % 2 == 0 && selection.height() % 2 == 0))
         << "CopyOutputRequest supports odd-sized result_selection() only for "
-           "RGBA!";
+           "RGBA and RGBAF16!";
     DCHECK(!has_blit_request());
     result_selection_ = selection;
   }
diff --git a/components/viz/common/frame_sinks/copy_output_result.cc b/components/viz/common/frame_sinks/copy_output_result.cc
index 48fb2680..0849d9a4 100644
--- a/components/viz/common/frame_sinks/copy_output_result.cc
+++ b/components/viz/common/frame_sinks/copy_output_result.cc
@@ -36,6 +36,8 @@
   switch (format) {
     case CopyOutputResult::Format::RGBA:
       return SinglePlaneFormat::kRGBA_8888;
+    case CopyOutputResult::Format::RGBAF16:
+      return SinglePlaneFormat::kRGBA_F16;
     case CopyOutputResult::Format::I420_PLANES:
       return MultiPlaneFormat::kI420;
     case CopyOutputResult::Format::NV12:
@@ -53,8 +55,8 @@
       destination_(destination),
       rect_(rect),
       needs_lock_for_bitmap_(needs_lock_for_bitmap) {
-  DCHECK(format_ == Format::RGBA || format_ == Format::I420_PLANES ||
-         format == Format::NV12);
+  DCHECK(format_ == Format::RGBA || format_ == Format::RGBAF16 ||
+         format_ == Format::I420_PLANES || format == Format::NV12);
   DCHECK(destination_ == Destination::kSystemMemory ||
          destination_ == Destination::kSharedImage);
 }
diff --git a/components/viz/common/frame_sinks/copy_output_result.h b/components/viz/common/frame_sinks/copy_output_result.h
index 7a25ffcf..a0a66270 100644
--- a/components/viz/common/frame_sinks/copy_output_result.h
+++ b/components/viz/common/frame_sinks/copy_output_result.h
@@ -51,6 +51,9 @@
     // can only be delivered on the same task runner sequence that runs the
     // DirectRenderer implementation.
     NV12,
+    // A RGBAF16 shared texture. Results should be returned in a texture, will
+    // be a SharedImageFormat::kRGBA_F16.
+    RGBAF16,
   };
 
   // Specifies how the results are delivered to the issuer of the request.
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 41b8124..1686ea17 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -845,6 +845,8 @@
     SkSurface::RescaleMode rescale_mode,
     bool is_downscale_or_identity_in_both_dimensions,
     std::unique_ptr<CopyOutputRequest> request) {
+  DCHECK_EQ(request->result_format(), CopyOutputRequest::ResultFormat::RGBA);
+
   // If we can't convert |color_space| to a SkColorSpace (e.g. PIECEWISE_HDR),
   // request a sRGB destination color space for the copy result instead.
   gfx::ColorSpace dest_color_space = color_space;
@@ -929,8 +931,6 @@
     SkSurface::RescaleMode rescale_mode,
     bool is_downscale_or_identity_in_both_dimensions,
     std::unique_ptr<CopyOutputRequest> request) {
-  DCHECK_EQ(request->result_format(), CopyOutputRequest::ResultFormat::RGBA);
-
   switch (request->result_destination()) {
     case CopyOutputRequest::ResultDestination::kSystemMemory:
       CopyOutputRGBAInMemory(
@@ -954,6 +954,9 @@
     SkSurface::RescaleMode rescale_mode,
     bool is_downscale_or_identity_in_both_dimensions,
     std::unique_ptr<CopyOutputRequest> request) {
+  DCHECK(request->result_format() == CopyOutputRequest::ResultFormat::RGBA ||
+         request->result_format() == CopyOutputRequest::ResultFormat::RGBAF16);
+
   // Check if the request is valid.
   if (!IsValidInTextureCopyOutputRequest(geometry, *request)) {
     return;
@@ -971,8 +974,12 @@
     representation = dependency_->GetSharedImageManager()->ProduceSkia(
         mailbox, context_state_->memory_type_tracker(), context_state_);
   } else {
+    auto plane_format =
+        request->result_format() == CopyOutputRequest::ResultFormat::RGBA
+            ? SinglePlaneFormat::kRGBA_8888
+            : SinglePlaneFormat::kRGBA_F16;
     representation = CreateSharedImageRepresentationSkia(
-        SinglePlaneFormat::kRGBA_8888,
+        plane_format,
         gfx::Size(geometry.result_selection.width(),
                   geometry.result_selection.height()),
         color_space, "CopyOutputRGBA");
@@ -1133,7 +1140,7 @@
             std::move(representation)));
 
     request->SendResult(std::make_unique<CopyOutputSharedImageResult>(
-        CopyOutputResult::Format::RGBA, geometry.result_selection, mailbox,
+        request->result_format(), geometry.result_selection, mailbox,
         color_space, "CopyOutputRGBAInTexture", std::move(release_callbacks)));
   }
 }
@@ -1789,7 +1796,8 @@
                      std::move(request));
       break;
     }
-    case CopyOutputRequest::ResultFormat::RGBA: {
+    case CopyOutputRequest::ResultFormat::RGBA:
+    case CopyOutputRequest::ResultFormat::RGBAF16: {
       CopyOutputRGBA(surface, geometry, color_space, src_rect, rescale_mode,
                      is_downscale_or_identity_in_both_dimensions,
                      std::move(request));
diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc
index 80b4d99c..44c58bd 100644
--- a/components/viz/service/display_embedder/software_output_device_mac.cc
+++ b/components/viz/service/display_embedder/software_output_device_mac.cc
@@ -15,6 +15,7 @@
 #include "base/apple/foundation_util.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/trace_event/trace_event.h"
+#include "components/viz/common/resources/shared_image_format.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/ca_layer_params.h"
 #include "ui/gfx/geometry/skia_conversions.h"
@@ -134,7 +135,7 @@
   if (!current_paint_buffer_) {
     std::unique_ptr<Buffer> new_buffer(new Buffer);
     new_buffer->io_surface =
-        gfx::CreateIOSurface(pixel_size_, gfx::BufferFormat::BGRA_8888);
+        gfx::CreateIOSurface(pixel_size_, SinglePlaneFormat::kBGRA_8888);
     if (!new_buffer->io_surface)
       return nullptr;
     // Set the initial damage to be the full buffer.
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index 0f1c08d3..8769532 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -105,17 +105,21 @@
     GmbVideoFramePoolContextProvider* context_provider) {
   CHECK(format == media::PIXEL_FORMAT_I420 ||
         format == media::PIXEL_FORMAT_NV12 ||
-        format == media::PIXEL_FORMAT_ARGB);
+        format == media::PIXEL_FORMAT_ARGB ||
+        format == media::PIXEL_FORMAT_RGBAF16);
 
   switch (format) {
     case media::PIXEL_FORMAT_I420:
       return std::make_unique<SharedMemoryVideoFramePool>(capacity);
-    case media::PIXEL_FORMAT_ARGB: {
+    case media::PIXEL_FORMAT_ARGB:
+    case media::PIXEL_FORMAT_RGBAF16: {
+      auto color_space = format == media::PIXEL_FORMAT_ARGB
+                             ? gfx::ColorSpace::CreateSRGB()
+                             : gfx::ColorSpace::CreateSRGBLinear();
       switch (buffer_format_preference) {
         case mojom::BufferFormatPreference::kPreferGpuMemoryBuffer:
           return std::make_unique<GpuMemoryBufferVideoFramePool>(
-              capacity, format, gfx::ColorSpace::CreateSRGB(),
-              context_provider);
+              capacity, format, color_space, context_provider);
         case mojom::BufferFormatPreference::kDefault:
           return std::make_unique<SharedMemoryVideoFramePool>(capacity);
         default:
@@ -139,6 +143,8 @@
       return CopyOutputRequest::ResultFormat::NV12;
     case media::PIXEL_FORMAT_ARGB:
       return CopyOutputRequest::ResultFormat::RGBA;
+    case media::PIXEL_FORMAT_RGBAF16:
+      return CopyOutputRequest::ResultFormat::RGBAF16;
     default:
       NOTREACHED();
   }
@@ -148,8 +154,11 @@
                             media::VideoPixelFormat format) {
   CHECK(format == media::PIXEL_FORMAT_I420 ||
         format == media::PIXEL_FORMAT_NV12 ||
-        format == media::PIXEL_FORMAT_ARGB);
-  if (format == media::PIXEL_FORMAT_ARGB) {
+        format == media::PIXEL_FORMAT_ARGB ||
+        format == media::PIXEL_FORMAT_RGBAF16);
+
+  if (format == media::PIXEL_FORMAT_ARGB ||
+      format == media::PIXEL_FORMAT_RGBAF16) {
     // No special requirements:
     return true;
   }
@@ -284,9 +293,11 @@
 
   if (format != media::PIXEL_FORMAT_I420 &&
       format != media::PIXEL_FORMAT_ARGB &&
-      format != media::PIXEL_FORMAT_NV12) {
-    LOG(DFATAL) << "Invalid pixel format: Only I420, ARGB & NV12 formats are "
-                   "supported.";
+      format != media::PIXEL_FORMAT_NV12 &&
+      format != media::PIXEL_FORMAT_RGBAF16) {
+    LOG(DFATAL)
+        << "Invalid pixel format: Only I420, ARGB, RGBAF16 & NV12 formats are "
+           "supported.";
   } else {
     // We only support NV12 if we got a context provider for pool creation:
     CHECK(format != media::PIXEL_FORMAT_NV12 ||
@@ -458,8 +469,14 @@
         buffer_format_preference_ ==
             mojom::BufferFormatPreference::kPreferGpuMemoryBuffer);
 
+  // Only support RGBAF16 with kPreferGpuMemoryBuffer
+  CHECK(pixel_format_ != media::PIXEL_FORMAT_RGBAF16 ||
+        buffer_format_preference_ ==
+            mojom::BufferFormatPreference::kPreferGpuMemoryBuffer);
+
   // If we are using ARGB format with GMB, we must have the pool context
-  CHECK(pixel_format_ != media::PIXEL_FORMAT_ARGB ||
+  CHECK((pixel_format_ != media::PIXEL_FORMAT_ARGB &&
+         pixel_format_ != media::PIXEL_FORMAT_RGBAF16) ||
         buffer_format_preference_ !=
             mojom::BufferFormatPreference::kPreferGpuMemoryBuffer ||
         gmb_video_frame_pool_context_provider_);
@@ -570,13 +587,13 @@
     media::VideoPixelFormat pixel_format) {
   CHECK(pixel_format == media::PIXEL_FORMAT_I420 ||
         pixel_format == media::PIXEL_FORMAT_NV12 ||
-        pixel_format == media::PIXEL_FORMAT_ARGB);
+        pixel_format == media::PIXEL_FORMAT_ARGB ||
+        pixel_format == media::PIXEL_FORMAT_RGBAF16);
 
   if (pixel_format == media::PIXEL_FORMAT_I420 ||
       pixel_format == media::PIXEL_FORMAT_NV12) {
     return media::ComputeLetterboxRegionForI420(visible_rect, source_size);
   } else {
-    CHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format);
     const gfx::Rect content_rect =
         media::ComputeLetterboxRegion(visible_rect, source_size);
 
@@ -1022,6 +1039,7 @@
                                        frame->stride(VideoFrame::Plane::kV));
           break;
         case media::PIXEL_FORMAT_ARGB:
+        case media::PIXEL_FORMAT_RGBAF16:
           strides = base::StringPrintf("strideARGB:%d",
                                        frame->stride(VideoFrame::Plane::kARGB));
           break;
@@ -1064,9 +1082,12 @@
     if (pixel_format_ == media::PIXEL_FORMAT_I420 ||
         pixel_format_ == media::PIXEL_FORMAT_NV12) {
       frame->set_color_space(gfx::ColorSpace::CreateREC709());
-    } else {
-      CHECK_EQ(pixel_format_, media::PIXEL_FORMAT_ARGB);
+    } else if (pixel_format_ == media::PIXEL_FORMAT_ARGB) {
       frame->set_color_space(gfx::ColorSpace::CreateSRGB());
+    } else if (pixel_format_ == media::PIXEL_FORMAT_RGBAF16) {
+      frame->set_color_space(gfx::ColorSpace::CreateSRGBLinear());
+    } else {
+      NOTREACHED() << "Unexpected pixel format: " << pixel_format_;
     }
 
     dirty_rect_ = gfx::Rect();
@@ -1110,7 +1131,8 @@
       buffer_format_preference_ ==
           mojom::BufferFormatPreference::kPreferGpuMemoryBuffer &&
       (pixel_format_ == media::PIXEL_FORMAT_NV12 ||
-       pixel_format_ == media::PIXEL_FORMAT_ARGB);
+       pixel_format_ == media::PIXEL_FORMAT_ARGB ||
+       pixel_format_ == media::PIXEL_FORMAT_RGBAF16);
 
   std::optional<BlitRequest> blit_request;
   if (capture_texture_results) {
@@ -1250,6 +1272,11 @@
             break;
         }
         break;
+      case CopyOutputResult::Format::RGBAF16:
+        format = "RGBAF16_Texture";
+        strides = base::StringPrintf("strideARGB:%d",
+                                     frame->stride(VideoFrame::Plane::kARGB));
+        break;
     }
     consumer_->OnLog(base::StringPrintf(
         "FrameSinkVideoCapturerImpl: got CopyOutputResult: format=%s size:%s "
@@ -1306,7 +1333,8 @@
       frame_capture.CaptureFailed(CaptureResult::kI420ReadbackFailed);
     }
     UMA_HISTOGRAM_CAPTURE_SUCCEEDED("I420", success);
-  } else if (pixel_format_ == media::PIXEL_FORMAT_ARGB) {
+  } else if (pixel_format_ == media::PIXEL_FORMAT_ARGB ||
+             pixel_format_ == media::PIXEL_FORMAT_RGBAF16) {
     if (buffer_format_preference_ == mojom::BufferFormatPreference::kDefault) {
       int stride = frame->stride(VideoFrame::Plane::kARGB);
       // Note: ResultFormat::RGBA CopyOutputResult's format currently is
@@ -1533,7 +1561,8 @@
 
 gfx::Size FrameSinkVideoCapturerImpl::AdjustSizeForPixelFormat(
     const gfx::Size& raw_size) const {
-  if (pixel_format_ == media::PIXEL_FORMAT_ARGB) {
+  if (pixel_format_ == media::PIXEL_FORMAT_ARGB ||
+      pixel_format_ == media::PIXEL_FORMAT_RGBAF16) {
     gfx::Size result(raw_size);
     if (result.width() <= 0) {
       result.set_width(1);
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index 64ce43b..af234a4 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -110,6 +110,8 @@
       return media::PIXEL_FORMAT_NV12;
     case CopyOutputRequest::ResultFormat::RGBA:
       return media::PIXEL_FORMAT_ARGB;
+    case CopyOutputRequest::ResultFormat::RGBAF16:
+      return media::PIXEL_FORMAT_RGBAF16;
     default:
       NOTREACHED();
   }
@@ -122,6 +124,8 @@
       return gfx::ColorSpace::CreateREC709();
     case media::PIXEL_FORMAT_ARGB:
       return gfx::ColorSpace::CreateSRGB();
+    case media::PIXEL_FORMAT_RGBAF16:
+      return gfx::ColorSpace::CreateSRGBLinear();
     default:
       NOTREACHED();
   }
@@ -133,6 +137,7 @@
   switch (format) {
     case media::PIXEL_FORMAT_ABGR:
     case media::PIXEL_FORMAT_ARGB:
+    case media::PIXEL_FORMAT_RGBAF16:
       return coded_size;
     case media::PIXEL_FORMAT_NV12:
       return {cc::MathUtil::CheckedRoundUp(coded_size.width(), 2),
@@ -1747,7 +1752,8 @@
   expected_frame_update_rect.Offset(
       size_set().ExpectedContentRect(pixel_format_).OffsetFromOrigin());
   // Do not align when we are testing RGBA
-  if (pixel_format_ != media::PIXEL_FORMAT_ARGB) {
+  if (pixel_format_ != media::PIXEL_FORMAT_ARGB &&
+      pixel_format_ != media::PIXEL_FORMAT_RGBAF16) {
     EXPECT_FALSE(
         AlignsWithI420SubsamplingBoundaries(expected_frame_update_rect));
     expected_frame_update_rect =
@@ -2234,6 +2240,8 @@
         std::tuple(mojom::BufferFormatPreference::kPreferGpuMemoryBuffer,
                    media::PIXEL_FORMAT_NV12),
         std::tuple(mojom::BufferFormatPreference::kPreferGpuMemoryBuffer,
-                   media::PIXEL_FORMAT_ARGB)));
+                   media::PIXEL_FORMAT_ARGB),
+        std::tuple(mojom::BufferFormatPreference::kPreferGpuMemoryBuffer,
+                   media::PIXEL_FORMAT_RGBAF16)));
 
 }  // namespace viz
diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/BUILD.gn
index 7b7bfd5..7b8533d 100644
--- a/components/webauthn/android/BUILD.gn
+++ b/components/webauthn/android/BUILD.gn
@@ -20,6 +20,7 @@
   sources = [
     "//content/browser/webauth/authenticator_request_outcome_enums.h",
     "cred_man_support.h",
+    "webauthn_client_android.h",
     "webauthn_mode.h",
   ]
   visibility = [ ":*" ]
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
index 19ebd0b3..191fee3 100644
--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
+++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
@@ -35,6 +35,8 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.blink.mojom.AuthenticatorStatus;
 import org.chromium.blink.mojom.AuthenticatorTransport;
+import org.chromium.blink.mojom.CredentialInfo;
+import org.chromium.blink.mojom.CredentialTypeFlags;
 import org.chromium.blink.mojom.GetAssertionAuthenticatorResponse;
 import org.chromium.blink.mojom.MakeCredentialAuthenticatorResponse;
 import org.chromium.blink.mojom.Mediation;
@@ -451,18 +453,14 @@
 
         if (options.mediation == Mediation.IMMEDIATE) {
             WebContents webContents = mAuthenticationContextProvider.getWebContents();
-            // TODO(https://crbug.com/393055190): Implement Immediate Mediation for when CredMan is
-            // not available.
-            if (!isChrome(webContents) || getBarrierMode() == Barrier.Mode.ONLY_FIDO_2_API) {
-                returnErrorAndResetCallback(AuthenticatorStatus.NOT_IMPLEMENTED);
-                return;
-            }
             if (options.allowCredentials != null && options.allowCredentials.length != 0) {
+                log(TAG, "Immediate Get called with non-empty allowCredentials");
                 mGetAssertionErrorOutcome = GetAssertionOutcome.SECURITY_ERROR;
                 returnErrorAndResetCallback(AuthenticatorStatus.NOT_ALLOWED_ERROR);
                 return;
             }
             if (webContents != null && webContents.isIncognito()) {
+                log(TAG, "Immediate Get called in Incognito mode");
                 returnErrorAndResetCallback(AuthenticatorStatus.NOT_ALLOWED_ERROR);
                 return;
             }
@@ -587,12 +585,8 @@
         }
 
         // Payments should still go through Google Play Services.
-        // TODO(https://crbug.com/393055190): Immediate mediation should work with parallel mode
-        // when it is made to work with Chrome UI.
         final byte[] finalClientDataHash = clientDataHash;
-        if (payment == null
-                && (getBarrierMode() == Barrier.Mode.ONLY_CRED_MAN
-                        || options.mediation == Mediation.IMMEDIATE)) {
+        if (payment == null && getBarrierMode() == Barrier.Mode.ONLY_CRED_MAN) {
             if (options.mediation == Mediation.CONDITIONAL) {
                 mBarrier.resetAndSetWaitStatus(Barrier.Mode.ONLY_CRED_MAN);
                 mCredManHelper.startPrefetchRequest(
@@ -875,6 +869,7 @@
                 options.allowCredentials != null && options.allowCredentials.length != 0;
         boolean isConditionalRequest = options.mediation == Mediation.CONDITIONAL;
         assert isConditionalRequest || !hasAllowCredentials;
+        boolean isImmediateRequest = options.mediation == Mediation.IMMEDIATE;
 
         if (mConditionalUiState == ConditionalUiState.CANCEL_PENDING) {
             // The request was completed synchronously when the cancellation was received,
@@ -901,12 +896,13 @@
         }
 
         if (!isConditionalRequest
+                && !isImmediateRequest
                 && discoverableCredentials.isEmpty()
                 && getBarrierMode() != Barrier.Mode.BOTH) {
             mConditionalUiState = ConditionalUiState.NONE;
-            // When no passkeys are present for a non-conditional request, pass the request
-            // through to GMSCore. It will show an error message to the user, but can offer the
-            // user alternatives to use external passkeys.
+            // When no passkeys are present for a non-conditional non-immediate request pass the
+            // request through to GMSCore. It will show an error message to the user, but can offer
+            // the user alternatives to use external passkeys.
             // If the barrier mode is BOTH, the no passkeys state is handled by Chrome. Do not pass
             // the request to GMSCore.
             maybeDispatchGetAssertionRequest(options, callerOriginString, clientDataHash, null);
@@ -921,20 +917,57 @@
                                     options, callerOriginString, clientDataHash);
         }
 
+        @AssertionMediationType int mediationType = AssertionMediationType.MODAL;
+        Callback<Integer> rejectImmediateCallback = null;
+        Callback<CredentialInfo> passwordCallback = null;
+        if (isConditionalRequest) {
+            mediationType = AssertionMediationType.CONDITIONAL;
+        } else if (isImmediateRequest) {
+            if ((options.requestedCredentialTypeFlags & CredentialTypeFlags.PASSWORD) != 0) {
+                mediationType = AssertionMediationType.IMMEDIATE_WITH_PASSWORDS;
+                passwordCallback =
+                        (passwordCredential) -> {
+                            assumeNonNull(mGetCredentialCallback);
+                            mGetCredentialCallback.onCredentialResponse(
+                                    /* assertionResponse= */ null, passwordCredential);
+                        };
+            } else {
+                if (discoverableCredentials.isEmpty()) {
+                    log(TAG, "Immediate Get request did not display UI: no passkeys found");
+                    // Since passwords were not requested as a part of this immediate request, we
+                    // already know there are no credentials to provide, so the request can be
+                    // rejected now.
+                    returnErrorAndResetCallback(AuthenticatorStatus.NOT_ALLOWED_ERROR);
+                    return;
+                }
+                mediationType = AssertionMediationType.IMMEDIATE_PASSKEYS_ONLY;
+            }
+            rejectImmediateCallback =
+                    (rejectReason) -> {
+                        log(TAG, "Immediate Get request did not display UI: Code " + rejectReason);
+                        // TODO(https://crbug.com/433543129): Add metrics for the rejection reason
+                        // in order to distinguish user dismissal from no credentials being
+                        // available.
+                        returnErrorAndResetCallback(AuthenticatorStatus.NOT_ALLOWED_ERROR);
+                    };
+        }
+
         mConditionalUiState = ConditionalUiState.WAITING_FOR_SELECTION;
         assumeNonNull(getBridge());
         getBridge()
                 .onCredentialsDetailsListReceived(
                         mAuthenticationContextProvider.getRenderFrameHost(),
                         discoverableCredentials,
-                        isConditionalRequest,
+                        mediationType,
                         (selectedCredentialId) ->
                                 maybeDispatchGetAssertionRequest(
                                         options,
                                         callerOriginString,
                                         clientDataHash,
                                         selectedCredentialId),
-                        hybridCallback);
+                        passwordCallback,
+                        hybridCallback,
+                        rejectImmediateCallback);
     }
 
     /**
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/WebauthnBrowserBridge.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/WebauthnBrowserBridge.java
index b24aa29..b243025 100644
--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/WebauthnBrowserBridge.java
+++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/WebauthnBrowserBridge.java
@@ -11,9 +11,12 @@
 import org.jni_zero.NativeMethods;
 
 import org.chromium.base.Callback;
+import org.chromium.blink.mojom.CredentialInfo;
+import org.chromium.blink.mojom.CredentialType;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.content_public.browser.RenderFrameHost;
+import org.chromium.mojo_base.mojom.String16;
 
 import java.util.List;
 
@@ -39,28 +42,37 @@
      * fields. For non-conditional requests, a selection sheet is shown immediately. The callback is
      * invoked when a user selects one of the credentials from the list.
      *
+     * <p>TODO(https://crbug.com/433543129): This interface has gotten a bit overly complicated. It
+     * should be simplified by combining the callbacks into just two: one for credentials being
+     * returned (password or passkey), and another for other actions.
+     *
      * @param frameHost The RenderFrameHost for the frame that generated the request.
      * @param credentialList The list of credentials that can be used as autofill suggestions.
-     * @param isConditionalRequest Boolean indicating whether this is a conditional UI request or
-     *     not.
-     * @param getAssertionCallback The callback to be invoked with the credential ID of a selected
-     *     credential.
+     * @param mediationType Value indicating whether the credentials are for a modal, conditional,
+     *     or immediate request.
+     * @param passkeyCallback The callback to be invoked with the credential ID of a selected
+     *     WebAuthn credential.
+     * @param passwordCallback The callback to be invoked with a selected password credential.
      * @param hybridCallback The callback to be invoked if a user initiates a cross-device hybrid
      *     sign-in.
+     * @param rejectImmediateCallback The callback to be invoked if an immediate request will be
+     *     completed without a credential.
      */
     public void onCredentialsDetailsListReceived(
             @Nullable RenderFrameHost frameHost,
             List<WebauthnCredentialDetails> credentialList,
-            boolean isConditionalRequest,
-            Callback<byte[]> getAssertionCallback,
-            @Nullable Runnable hybridCallback) {
+            @AssertionMediationType int mediationType,
+            Callback<byte[]> passkeyCallback,
+            @Nullable Callback<CredentialInfo> passwordCallback,
+            @Nullable Runnable hybridCallback,
+            @Nullable Callback<Integer> rejectImmediateCallback) {
         assert credentialList != null;
-        assert getAssertionCallback != null;
+        assert passkeyCallback != null;
         log(
                 TAG,
-                "onCredentialsDetailsListReceived, isConditionalRequest: %b, number of credentials:"
+                "onCredentialsDetailsListReceived, mediationType: %d, number of credentials:"
                         + " %d",
-                isConditionalRequest,
+                mediationType,
                 credentialList.size());
         prepareNativeBrowserBridgeIfRequired();
 
@@ -71,9 +83,11 @@
                         mNativeWebauthnBrowserBridge,
                         credentialArray,
                         frameHost,
-                        isConditionalRequest,
-                        getAssertionCallback,
-                        hybridCallback);
+                        mediationType,
+                        passkeyCallback,
+                        passwordCallback,
+                        hybridCallback,
+                        rejectImmediateCallback);
     }
 
     /**
@@ -160,6 +174,19 @@
         mNativeWebauthnBrowserBridge = 0;
     }
 
+    public static @Nullable String16 stringToMojoString16(@Nullable String javaString) {
+        if (javaString == null) {
+            return null;
+        }
+        short[] data = new short[javaString.length()];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = (short) javaString.charAt(i);
+        }
+        String16 mojoString = new String16();
+        mojoString.data = data;
+        return mojoString;
+    }
+
     @CalledByNative
     private static @Nullable String getWebauthnCredentialDetailsUserName(
             WebauthnCredentialDetails cred) {
@@ -184,6 +211,17 @@
         return cred.mCredentialId;
     }
 
+    @CalledByNative
+    private static CredentialInfo createPasswordCredentialInfo(String username, String password) {
+        CredentialInfo passwordCredential = new CredentialInfo();
+        passwordCredential.type = CredentialType.PASSWORD;
+        String16 name = stringToMojoString16(username);
+        passwordCredential.name = name;
+        passwordCredential.id = name;
+        passwordCredential.password = stringToMojoString16(password);
+        return passwordCredential;
+    }
+
     private void prepareNativeBrowserBridgeIfRequired() {
         if (mNativeWebauthnBrowserBridge == 0) {
             log(TAG, "prepareNativeBrowserBridgeIfRequired");
@@ -201,9 +239,11 @@
                 long nativeWebauthnBrowserBridge,
                 WebauthnCredentialDetails[] credentialList,
                 @Nullable RenderFrameHost frameHost,
-                boolean isConditionalRequest,
+                @AssertionMediationType int mediationType,
                 Callback<byte[]> getAssertionCallback,
-                @Nullable Runnable hybridCallback);
+                @Nullable Callback<CredentialInfo> passwordCallback,
+                @Nullable Runnable hybridCallback,
+                @Nullable Callback<Integer> rejectImmediateCallback);
 
         void onCredManConditionalRequestPending(
                 long nativeWebauthnBrowserBridge,
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/cred_man/CredManHelper.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/cred_man/CredManHelper.java
index 335ccdc..01d507f4 100644
--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/cred_man/CredManHelper.java
+++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/cred_man/CredManHelper.java
@@ -420,12 +420,12 @@
                                 CredentialInfo passwordCredential = new CredentialInfo();
                                 passwordCredential.type = CredentialType.PASSWORD;
                                 String16 name =
-                                        stringToMojoString16(
+                                        WebauthnBrowserBridge.stringToMojoString16(
                                                 data.getString(CRED_MAN_PREFIX + "BUNDLE_KEY_ID"));
                                 passwordCredential.name = name;
                                 passwordCredential.id = name;
                                 passwordCredential.password =
-                                        stringToMojoString16(
+                                        WebauthnBrowserBridge.stringToMojoString16(
                                                 data.getString(
                                                         CRED_MAN_PREFIX + "BUNDLE_KEY_PASSWORD"));
                                 assumeNonNull(getCallback);
@@ -655,19 +655,6 @@
                 e);
     }
 
-    private static @Nullable String16 stringToMojoString16(@Nullable String javaString) {
-        if (javaString == null) {
-            return null;
-        }
-        short[] data = new short[javaString.length()];
-        for (int i = 0; i < data.length; i++) {
-            data[i] = (short) javaString.charAt(i);
-        }
-        String16 mojoString = new String16();
-        mojoString.data = data;
-        return mojoString;
-    }
-
     public static @Nullable MakeCredentialAuthenticatorResponse parseCreateCredentialResponseData(
             Bundle data) {
         String json = data.getString(BUNDLE_KEY_REGISTRATION_RESPONSE_JSON);
diff --git a/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java b/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java
index d79f18a9..d001ba5 100644
--- a/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java
+++ b/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java
@@ -321,7 +321,13 @@
                         /* ignoreGpm= */ eq(true));
         verify(mBrowserBridgeMock)
                 .onCredentialsDetailsListReceived(
-                        eq(mFrameHost), eq(Collections.emptyList()), eq(false), any(), any());
+                        eq(mFrameHost),
+                        eq(Collections.emptyList()),
+                        eq(AssertionMediationType.MODAL),
+                        any(),
+                        any(),
+                        any(),
+                        any());
         assertThat(mFido2ApiCallHelper.mGetAssertionCalled).isFalse();
     }
 
@@ -535,7 +541,14 @@
                         /* barrier= */ any(),
                         /* ignoreGpm= */ eq(true));
         verify(mBrowserBridgeMock, times(1))
-                .onCredentialsDetailsListReceived(any(), any(), eq(true), any(), any());
+                .onCredentialsDetailsListReceived(
+                        any(),
+                        any(),
+                        eq(AssertionMediationType.CONDITIONAL),
+                        any(),
+                        any(),
+                        any(),
+                        any());
         verify(mBrowserBridgeMock, never()).onCredManUiClosed(any(), anyBoolean());
     }
 
diff --git a/components/webauthn/android/webauthn_browser_bridge.cc b/components/webauthn/android/webauthn_browser_bridge.cc
index 084b978..c2c8080 100644
--- a/components/webauthn/android/webauthn_browser_bridge.cc
+++ b/components/webauthn/android/webauthn_browser_bridge.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -28,7 +29,9 @@
 // Must come after all headers that specialize FromJniType() / ToJniType().
 #include "components/webauthn/android/jni_headers/WebauthnBrowserBridge_jni.h"
 
+using base::android::AttachCurrentThread;
 using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF16ToJavaString;
 using base::android::ScopedJavaGlobalRef;
 using base::android::ScopedJavaLocalRef;
 
@@ -78,8 +81,25 @@
     const base::android::JavaRef<jobject>& jcallback,
     const std::vector<uint8_t>& credential_id) {
   base::android::RunObjectCallbackAndroid(
-      jcallback, base::android::ToJavaByteArray(
-                     base::android::AttachCurrentThread(), credential_id));
+      jcallback,
+      base::android::ToJavaByteArray(AttachCurrentThread(), credential_id));
+}
+
+void OnPasswordCredentialSelected(
+    const base::android::JavaRef<jobject>& jcallback,
+    std::u16string_view username,
+    std::u16string_view password) {
+  JNIEnv* env = AttachCurrentThread();
+  base::android::RunObjectCallbackAndroid(
+      jcallback, Java_WebauthnBrowserBridge_createPasswordCredentialInfo(
+                     env, ConvertUTF16ToJavaString(env, username),
+                     ConvertUTF16ToJavaString(env, password)));
+}
+
+void OnRejectImmediate(const base::android::JavaRef<jobject>& jcallback,
+                       ImmediateRequestRejectionReason rejection_reason) {
+  base::android::RunIntCallbackAndroid(jcallback,
+                                       static_cast<int32_t>(rejection_reason));
 }
 
 void OnHybridAssertionInvoked(
@@ -104,9 +124,12 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobjectArray>& credentials,
     const base::android::JavaParamRef<jobject>& jframe_host,
-    jboolean is_conditional_request,
+    jint mediation_type,
     const base::android::JavaParamRef<jobject>& jget_assertion_callback,
-    const base::android::JavaParamRef<jobject>& jhybrid_callback) const {
+    const base::android::JavaParamRef<jobject>& jpassword_callback,
+    const base::android::JavaParamRef<jobject>& jhybrid_callback,
+    const base::android::JavaParamRef<jobject>& jreject_immediate_callback)
+    const {
   auto* client = WebAuthnClientAndroid::GetClient();
   auto* render_frame_host =
       content::RenderFrameHost::FromJavaRenderFrameHost(jframe_host);
@@ -128,6 +151,23 @@
   ConvertJavaCredentialArrayToMetadataVector(env, credentials,
                                              &credentials_metadata);
 
+  CHECK(AssertionMediationType(mediation_type) !=
+            AssertionMediationType::kImmediatePasskeysOnly ||
+        !credentials_metadata.empty());
+
+  base::RepeatingCallback<void(const std::vector<uint8_t>&)> passkey_callback =
+      base::BindRepeating(
+          &OnWebauthnCredentialSelected,
+          ScopedJavaGlobalRef<jobject>(env, jget_assertion_callback));
+
+  base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+      password_callback;
+  if (!jpassword_callback.is_null()) {
+    password_callback = base::BindRepeating(
+        &OnPasswordCredentialSelected,
+        ScopedJavaGlobalRef<jobject>(env, jpassword_callback));
+  }
+
   base::RepeatingCallback<void()> hybrid_callback;
   if (!jhybrid_callback.is_null()) {
     hybrid_callback = base::BindRepeating(
@@ -135,12 +175,19 @@
         ScopedJavaGlobalRef<jobject>(env, jhybrid_callback));
   }
 
+  base::RepeatingCallback<void(ImmediateRequestRejectionReason)>
+      reject_immediate_callback;
+  if (!jreject_immediate_callback.is_null()) {
+    reject_immediate_callback = base::BindRepeating(
+        &OnRejectImmediate,
+        ScopedJavaGlobalRef<jobject>(env, jreject_immediate_callback));
+  }
+
   client->OnWebAuthnRequestPending(
-      render_frame_host, credentials_metadata, is_conditional_request,
-      base::BindRepeating(
-          &OnWebauthnCredentialSelected,
-          ScopedJavaGlobalRef<jobject>(env, jget_assertion_callback)),
-      std::move(hybrid_callback));
+      render_frame_host, std::move(credentials_metadata),
+      AssertionMediationType(mediation_type), std::move(passkey_callback),
+      std::move(password_callback), std::move(hybrid_callback),
+      std::move(reject_immediate_callback));
 }
 
 void TriggerFullRequest(
diff --git a/components/webauthn/android/webauthn_browser_bridge.h b/components/webauthn/android/webauthn_browser_bridge.h
index 325d5d8..2a8b13b1 100644
--- a/components/webauthn/android/webauthn_browser_bridge.h
+++ b/components/webauthn/android/webauthn_browser_bridge.h
@@ -25,9 +25,12 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobjectArray>& credentials,
       const base::android::JavaParamRef<jobject>& jframe_host,
-      jboolean is_conditional_request,
-      const base::android::JavaParamRef<jobject>& jgetAssertionCallback,
-      const base::android::JavaParamRef<jobject>& jhybridCallback) const;
+      jint mediation_type,
+      const base::android::JavaParamRef<jobject>& jget_assertion_callback,
+      const base::android::JavaParamRef<jobject>& jpassword_callback,
+      const base::android::JavaParamRef<jobject>& jhybrid_callback,
+      const base::android::JavaParamRef<jobject>& jreject_immediate_callback)
+      const;
 
   void CleanupRequest(
       JNIEnv* env,
diff --git a/components/webauthn/android/webauthn_client_android.h b/components/webauthn/android/webauthn_client_android.h
index 90d365346..3e4376d 100644
--- a/components/webauthn/android/webauthn_client_android.h
+++ b/components/webauthn/android/webauthn_client_android.h
@@ -22,6 +22,21 @@
 
 namespace webauthn {
 
+// The type of mediation that is being used for a WebAuthn GetAssertion request.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.webauthn
+// GENERATED_JAVA_PREFIX_TO_STRIP: k
+enum class AssertionMediationType {
+  kModal = 0,
+  kConditional = 1,
+  kImmediatePasskeysOnly = 3,
+  kImmediateWithPasswords = 4,
+};
+
+enum class ImmediateRequestRejectionReason {
+  kNoCredentials = 0,
+  kUserDismissed = 1,
+};
+
 class WebAuthnClientAndroid {
  public:
   virtual ~WebAuthnClientAndroid();
@@ -37,11 +52,15 @@
   // if and when a user selects a credential from a selection dialog.
   virtual void OnWebAuthnRequestPending(
       content::RenderFrameHost* frame_host,
-      const std::vector<device::DiscoverableCredentialMetadata>& credentials,
-      bool is_conditional_request,
+      std::vector<device::DiscoverableCredentialMetadata> credentials,
+      AssertionMediationType mediation_type,
       base::RepeatingCallback<void(const std::vector<uint8_t>& id)>
-          getAssertionCallback,
-      base::RepeatingCallback<void()> hybridCallback) = 0;
+          passkey_callback,
+      base::RepeatingCallback<void(std::u16string_view, std::u16string_view)>
+          password_callback,
+      base::RepeatingCallback<void()> hybrid_callback,
+      base::RepeatingCallback<void(ImmediateRequestRejectionReason)>
+          reject_immediate_callback) = 0;
 
   // Closes an outstanding conditional UI request, so passkeys will no longer be
   // displayed through autofill.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 03fe19e..caa77f2 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -73,6 +73,13 @@
     "//content/test/fuzzer:media_stream_dispatcher_host_mojolpm_fuzzer",
   ]
 
+  if (use_fuzzing_engine && is_android) {
+    visibility += [
+      ":*",
+      "//content/test/fuzzer:*",
+    ]
+  }
+
   configs += [
     "//build/config:precompiled_headers",
     "//content:content_implementation",
diff --git a/content/browser/blob_storage/chrome_blob_storage_context.cc b/content/browser/blob_storage/chrome_blob_storage_context.cc
index 01d2a426..2f5aea9 100644
--- a/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -332,6 +332,4 @@
   return blob_storage_context->context();
 }
 
-const char kBlobStorageContextKeyName[] = "content_blob_storage_context";
-
 }  // namespace content
diff --git a/content/browser/blob_storage/chrome_blob_storage_context.h b/content/browser/blob_storage/chrome_blob_storage_context.h
index 1b1927386..b80835c 100644
--- a/content/browser/blob_storage/chrome_blob_storage_context.h
+++ b/content/browser/blob_storage/chrome_blob_storage_context.h
@@ -151,7 +151,8 @@
 storage::BlobStorageContext* GetBlobStorageContext(
     ChromeBlobStorageContext* blob_storage_context);
 
-extern const char kBlobStorageContextKeyName[];
+inline constexpr char kBlobStorageContextKeyName[] =
+    "content_blob_storage_context";
 
 }  // namespace content
 
diff --git a/content/browser/browsing_topics/header_util.cc b/content/browser/browsing_topics/header_util.cc
index c93244d..bc90694b 100644
--- a/content/browser/browsing_topics/header_util.cc
+++ b/content/browser/browsing_topics/header_util.cc
@@ -41,8 +41,6 @@
 
 }  // namespace
 
-const char kBrowsingTopicsRequestHeaderKey[] = "Sec-Browsing-Topics";
-
 std::string DeriveTopicsHeaderValue(
     const std::vector<blink::mojom::EpochTopicPtr>& topics,
     int num_versions_in_epochs) {
diff --git a/content/browser/browsing_topics/header_util.h b/content/browser/browsing_topics/header_util.h
index d235444..cb2efef 100644
--- a/content/browser/browsing_topics/header_util.h
+++ b/content/browser/browsing_topics/header_util.h
@@ -12,7 +12,7 @@
 
 namespace content {
 
-extern const char kBrowsingTopicsRequestHeaderKey[];
+inline constexpr char kBrowsingTopicsRequestHeaderKey[] = "Sec-Browsing-Topics";
 
 // Derive the header value for `Sec-Browsing-Topics` given `topics` and
 // `num_versions_in_epochs`.
diff --git a/content/browser/fenced_frame/fenced_frame_config.cc b/content/browser/fenced_frame/fenced_frame_config.cc
index 51702d3..56a25d5 100644
--- a/content/browser/fenced_frame/fenced_frame_config.cc
+++ b/content/browser/fenced_frame/fenced_frame_config.cc
@@ -17,8 +17,6 @@
 
 namespace content {
 
-const char kUrnUuidPrefix[] = "urn:uuid:";
-
 GURL GenerateUrnUuid() {
   return GURL(kUrnUuidPrefix +
               base::Uuid::GenerateRandomV4().AsLowercaseString());
diff --git a/content/browser/fenced_frame/fenced_frame_config.h b/content/browser/fenced_frame/fenced_frame_config.h
index c69e2ab..3579df1 100644
--- a/content/browser/fenced_frame/fenced_frame_config.h
+++ b/content/browser/fenced_frame/fenced_frame_config.h
@@ -87,7 +87,7 @@
 
 class FencedFrameURLMapping;
 
-extern const char kUrnUuidPrefix[];
+inline constexpr char kUrnUuidPrefix[] = "urn:uuid:";
 GURL CONTENT_EXPORT GenerateUrnUuid();
 
 // Used by the fenced frame properties getter. It specifies the node source
diff --git a/content/browser/indexed_db/file_path_util.cc b/content/browser/indexed_db/file_path_util.cc
index 47146e1..e199f21a 100644
--- a/content/browser/indexed_db/file_path_util.cc
+++ b/content/browser/indexed_db/file_path_util.cc
@@ -37,13 +37,6 @@
 constexpr char kSqliteEmptyDatabaseNameFileName[] = "0";
 }  // namespace
 
-const base::FilePath::CharType kLevelDBExtension[] =
-    FILE_PATH_LITERAL(".leveldb");
-const base::FilePath::CharType kIndexedDBExtension[] =
-    FILE_PATH_LITERAL(".indexeddb");
-const base::FilePath::CharType kIndexedDBFile[] =
-    FILE_PATH_LITERAL("indexeddb");
-
 bool ShouldUseLegacyFilePath(const storage::BucketLocator& bucket_locator) {
   return bucket_locator.storage_key.IsFirstPartyContext() &&
          bucket_locator.is_default;
diff --git a/content/browser/indexed_db/file_path_util.h b/content/browser/indexed_db/file_path_util.h
index cba0f40..db675e35 100644
--- a/content/browser/indexed_db/file_path_util.h
+++ b/content/browser/indexed_db/file_path_util.h
@@ -19,9 +19,12 @@
 
 namespace content::indexed_db {
 
-extern CONTENT_EXPORT const base::FilePath::CharType kIndexedDBExtension[];
-extern const base::FilePath::CharType kIndexedDBFile[];
-extern CONTENT_EXPORT const base::FilePath::CharType kLevelDBExtension[];
+inline constexpr base::FilePath::CharType kLevelDBExtension[] =
+    FILE_PATH_LITERAL(".leveldb");
+inline constexpr base::FilePath::CharType kIndexedDBExtension[] =
+    FILE_PATH_LITERAL(".indexeddb");
+inline constexpr base::FilePath::CharType kIndexedDBFile[] =
+    FILE_PATH_LITERAL("indexeddb");
 
 // Returns whether the legacy (first-party/default-bucket) path should be used
 // for storing IDB files for the given bucket.
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc
index 5f87aa1..30ef7d0 100644
--- a/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -475,6 +475,10 @@
 }
 
 IN_PROC_BROWSER_TEST_P(IndexedDBBrowserTest, Bug941965Test) {
+  if (using_sqlite_) {
+    GTEST_SKIP() << "Flaky with SQLite, see crbug.com/435459644";
+  }
+
   // Double-open an incognito window to test that saving & reading a blob from
   // indexeddb works.
   Shell* incognito_browser = CreateOffTheRecordBrowser();
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 9f06bf76..73b8a06 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -362,8 +362,6 @@
 
 }  // namespace
 
-const unsigned char kMinimumIndexId = 30;
-
 std::string MaxIDBKey() {
   std::string ret;
   EncodeByte(kIndexedDBKeyNullTypeByte, &ret);
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.h b/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 4ee8493..2de29d45 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -26,20 +26,20 @@
 // 3 - Adds metadata needed for blob support.
 // 4 - Adds size & last_modified to 'file' blob_info encodings.
 // 5 - One time verification that blob files exist on disk.
-const constexpr int64_t kLatestKnownSchemaVersion = 5;
+inline constexpr int64_t kLatestKnownSchemaVersion = 5;
 // Migration from version 2 to 3 occurred in 2014, and migration to version 4
 // began in early 2020, so we currently continue to support schema that are as
 // old as 2014.
-const constexpr int64_t kEarliestSupportedSchemaVersion = 3;
+inline constexpr int64_t kEarliestSupportedSchemaVersion = 3;
 
-CONTENT_EXPORT extern const unsigned char kMinimumIndexId;
+inline constexpr unsigned char kMinimumIndexId = 30;
 
 CONTENT_EXPORT std::string MaxIDBKey();
 CONTENT_EXPORT std::string MinIDBKey();
 
 // DatabaseId, BlobNumber
-typedef std::pair<int64_t, int64_t> BlobJournalEntryType;
-typedef std::vector<BlobJournalEntryType> BlobJournalType;
+using BlobJournalEntryType = std::pair<int64_t, int64_t>;
+using BlobJournalType = std::vector<BlobJournalEntryType>;
 
 CONTENT_EXPORT void EncodeByte(unsigned char value, std::string* into);
 CONTENT_EXPORT void EncodeBool(bool value, std::string* into);
diff --git a/content/browser/interest_group/ad_auction_headers_util.cc b/content/browser/interest_group/ad_auction_headers_util.cc
index 41896c61..a695e4a 100644
--- a/content/browser/interest_group/ad_auction_headers_util.cc
+++ b/content/browser/interest_group/ad_auction_headers_util.cc
@@ -40,13 +40,6 @@
 
 namespace content {
 
-const char kAdAuctionRequestHeaderKey[] = "Sec-Ad-Auction-Fetch";
-const char kAdAuctionResultResponseHeaderKey[] = "Ad-Auction-Result";
-const char kAdAuctionResultNonceResponseHeaderKey[] = "Ad-Auction-Result-Nonce";
-const char kAdAuctionSignalsResponseHeaderKey[] = "Ad-Auction-Signals";
-const char kAdAuctionAdditionalBidResponseHeaderKey[] =
-    "Ad-Auction-Additional-Bid";
-
 namespace {
 
 // These values are persisted to logs. Entries should not be renumbered and
diff --git a/content/browser/interest_group/ad_auction_headers_util.h b/content/browser/interest_group/ad_auction_headers_util.h
index 65238f31..9b3a8ce 100644
--- a/content/browser/interest_group/ad_auction_headers_util.h
+++ b/content/browser/interest_group/ad_auction_headers_util.h
@@ -39,14 +39,17 @@
 
 // The request header key that triggers interception of the auction result,
 // signals, and additional bids from their associated response headers.
-extern const char kAdAuctionRequestHeaderKey[];
+inline constexpr char kAdAuctionRequestHeaderKey[] = "Sec-Ad-Auction-Fetch";
 
 // Response header keys associated with auction result, nonce, signals, and
 // additional bids, respectively.
-extern const char CONTENT_EXPORT kAdAuctionResultResponseHeaderKey[];
-extern const char CONTENT_EXPORT kAdAuctionResultNonceResponseHeaderKey[];
-extern const char CONTENT_EXPORT kAdAuctionSignalsResponseHeaderKey[];
-extern const char CONTENT_EXPORT kAdAuctionAdditionalBidResponseHeaderKey[];
+inline constexpr char kAdAuctionResultResponseHeaderKey[] = "Ad-Auction-Result";
+inline constexpr char kAdAuctionResultNonceResponseHeaderKey[] =
+    "Ad-Auction-Result-Nonce";
+inline constexpr char kAdAuctionSignalsResponseHeaderKey[] =
+    "Ad-Auction-Signals";
+inline constexpr char kAdAuctionAdditionalBidResponseHeaderKey[] =
+    "Ad-Auction-Additional-Bid";
 
 // Returns whether or not this request is eligible for ad auction headers
 // requested for fetch requests. The `initiator_rfh` should be the
diff --git a/content/browser/preloading/anchor_element_interaction_host_impl.cc b/content/browser/preloading/anchor_element_interaction_host_impl.cc
index ac40b38..9fa4d1b 100644
--- a/content/browser/preloading/anchor_element_interaction_host_impl.cc
+++ b/content/browser/preloading/anchor_element_interaction_host_impl.cc
@@ -13,7 +13,6 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/origin_util.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-data-view.h"
 
 namespace content {
 
@@ -148,10 +147,7 @@
 void AnchorElementInteractionHostImpl::OnPointerHoverEager(
     const GURL& url,
     blink::mojom::AnchorElementPointerDataPtr mouse_data) {
-  auto* preloading_decider =
-      PreloadingDecider::GetOrCreateForCurrentDocument(&render_frame_host());
-  preloading_decider->OnPointerHover(
-      url, std::move(mouse_data), blink::mojom::SpeculationEagerness::kEager);
+  // TODO(https://crbug.com/40287486): pipe this to PreloadingDecider.
 }
 
 void AnchorElementInteractionHostImpl::OnPointerHoverModerate(
@@ -159,9 +155,7 @@
     blink::mojom::AnchorElementPointerDataPtr mouse_data) {
   auto* preloading_decider =
       PreloadingDecider::GetOrCreateForCurrentDocument(&render_frame_host());
-  preloading_decider->OnPointerHover(
-      url, std::move(mouse_data),
-      blink::mojom::SpeculationEagerness::kModerate);
+  preloading_decider->OnPointerHover(url, std::move(mouse_data));
   MaybePrewarmHttpDiskCache(url, render_frame_host());
   MaybeWarmUpServiceWorkerOnPointerHover(url, render_frame_host());
 }
diff --git a/content/browser/preloading/anchor_element_interaction_host_impl_unittest.cc b/content/browser/preloading/anchor_element_interaction_host_impl_unittest.cc
index a38a65f4..5efe7211 100644
--- a/content/browser/preloading/anchor_element_interaction_host_impl_unittest.cc
+++ b/content/browser/preloading/anchor_element_interaction_host_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "content/test/test_web_contents.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-data-view.h"
 #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-forward.h"
 #include "ui/base/page_transition_types.h"
 
@@ -41,23 +40,10 @@
       const std::vector<blink::mojom::SpeculationCandidatePtr>& candidates)
       override {}
   void OnPointerDown(const GURL& url) override { on_pointer_down_url_ = url; }
-  void OnPointerHover(
-      const GURL& url,
-      blink::mojom::SpeculationEagerness target_eagerness) override {
-    on_pointer_hover_url_ = url;
-    on_pointer_hover_target_eagerness_ = target_eagerness;
-  }
-
-  void Reset() {
-    on_pointer_down_url_.reset();
-    on_pointer_hover_url_.reset();
-    on_pointer_hover_target_eagerness_.reset();
-  }
+  void OnPointerHover(const GURL& url) override { on_pointer_hover_url_ = url; }
 
   std::optional<GURL> on_pointer_down_url_;
   std::optional<GURL> on_pointer_hover_url_;
-  std::optional<blink::mojom::SpeculationEagerness>
-      on_pointer_hover_target_eagerness_;
 
  private:
   raw_ptr<RenderFrameHostImpl> rfh_;
@@ -74,13 +60,16 @@
                                            remote.BindNewPipeAndPassReceiver());
 
   ScopedPreloadingDeciderObserver observer(render_frame_host);
+  observer.on_pointer_down_url_.reset();
+  observer.on_pointer_hover_url_.reset();
   const auto pointer_down_url = GURL("www.example.com/page1.html");
   remote->OnPointerDown(pointer_down_url);
   remote.FlushForTesting();
   EXPECT_EQ(pointer_down_url, observer.on_pointer_down_url_);
   EXPECT_FALSE(observer.on_pointer_hover_url_.has_value());
 
-  observer.Reset();
+  observer.on_pointer_down_url_.reset();
+  observer.on_pointer_hover_url_.reset();
   const auto pointer_hover_url = GURL("www.example.com/page2.html");
   remote->OnPointerHoverModerate(
       pointer_hover_url,
@@ -88,20 +77,6 @@
   remote.FlushForTesting();
   EXPECT_FALSE(observer.on_pointer_down_url_.has_value());
   EXPECT_EQ(pointer_hover_url, observer.on_pointer_hover_url_);
-  EXPECT_TRUE(observer.on_pointer_hover_target_eagerness_.has_value());
-  EXPECT_EQ(observer.on_pointer_hover_target_eagerness_,
-            blink::mojom::SpeculationEagerness::kModerate);
-
-  observer.Reset();
-  remote->OnPointerHoverEager(
-      pointer_hover_url,
-      blink::mojom::AnchorElementPointerData::New(false, 0.0, 0.0));
-  remote.FlushForTesting();
-  EXPECT_FALSE(observer.on_pointer_down_url_.has_value());
-  EXPECT_EQ(pointer_hover_url, observer.on_pointer_hover_url_);
-  EXPECT_TRUE(observer.on_pointer_hover_target_eagerness_.has_value());
-  EXPECT_EQ(observer.on_pointer_hover_target_eagerness_,
-            blink::mojom::SpeculationEagerness::kEager);
 }
 
 TEST_F(AnchorElementInteractionHostImplTest, OnViewportHeuristicTriggered) {
diff --git a/content/browser/preloading/preloading_decider.cc b/content/browser/preloading/preloading_decider.cc
index 628cb0d..05ededc8 100644
--- a/content/browser/preloading/preloading_decider.cc
+++ b/content/browser/preloading/preloading_decider.cc
@@ -9,7 +9,6 @@
 #include <string_view>
 #include <vector>
 
-#include "base/check_is_test.h"
 #include "base/check_op.h"
 #include "base/containers/enum_set.h"
 #include "base/feature_list.h"
@@ -34,8 +33,6 @@
 #include "content/public/browser/web_contents.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/preloading/anchor_element_interaction_host.mojom.h"
-#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-data-view.h"
-#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-forward.h"
 
 namespace content {
 
@@ -106,14 +103,6 @@
     pointer_hover_eagerness_ =
         EagernessSet{blink::mojom::SpeculationEagerness::kModerate};
 
-    if (base::FeatureList::IsEnabled(
-            blink::features::kPreloadingEagerHeuristics)) {
-      pointer_down_eagerness_.Put(blink::mojom::SpeculationEagerness::kEager);
-      pointer_hover_eagerness_.Put(blink::mojom::SpeculationEagerness::kEager);
-    }
-
-    CHECK(pointer_down_eagerness_.HasAll(pointer_hover_eagerness_));
-
     static const base::FeatureParam<std::string> kViewportHeuristicEagerness{
         &blink::features::kPreloadingViewportHeuristics,
         "viewport_heuristic_eagerness", "moderate"};
@@ -305,17 +294,9 @@
 
 void PreloadingDecider::OnPointerHover(
     const GURL& url,
-    blink::mojom::AnchorElementPointerDataPtr mouse_data,
-    blink::mojom::SpeculationEagerness target_eagerness) {
-  // In non-test code, target eagerness must be either "moderate" or "eager".
-  if (target_eagerness != blink::mojom::SpeculationEagerness::kModerate &&
-      target_eagerness != blink::mojom::SpeculationEagerness::kEager) {
-    CHECK_IS_TEST();
-    return;
-  }
-
+    blink::mojom::AnchorElementPointerDataPtr mouse_data) {
   if (observer_for_testing_) {
-    observer_for_testing_->OnPointerHover(url, target_eagerness);
+    observer_for_testing_->OnPointerHover(url);
   }
 
   WebContents* web_contents =
@@ -333,16 +314,9 @@
   // Preconnecting on hover events should not be done if the link is not safe
   // to prefetch or prerender.
   constexpr bool fallback_to_preconnect = false;
-  // Filter `kModerate` for the "eager" mouse hover to prevent false preloading.
-  EagernessSet eagerness_to_exclude;
-  if (base::FeatureList::IsEnabled(
-          blink::features::kPreloadingEagerHeuristics)) {
-    eagerness_to_exclude = EagernessSet::All();
-    eagerness_to_exclude.Remove(target_eagerness);
-  }
   MaybeEnactCandidate(url, preloading_predictor::kUrlPointerHoverOnAnchor,
                       PreloadingConfidence{100}, fallback_to_preconnect,
-                      eagerness_to_exclude);
+                      /*eagerness_to_exclude=*/{});
 }
 
 void PreloadingDecider::OnViewportHeuristicTriggered(const GURL& url) {
diff --git a/content/browser/preloading/preloading_decider.h b/content/browser/preloading/preloading_decider.h
index 497607a..79aa43c 100644
--- a/content/browser/preloading/preloading_decider.h
+++ b/content/browser/preloading/preloading_decider.h
@@ -27,9 +27,7 @@
   virtual void UpdateSpeculationCandidates(
       const std::vector<blink::mojom::SpeculationCandidatePtr>& candidates) = 0;
   virtual void OnPointerDown(const GURL& url) = 0;
-  virtual void OnPointerHover(
-      const GURL& url,
-      blink::mojom::SpeculationEagerness target_eagerness) = 0;
+  virtual void OnPointerHover(const GURL& url) = 0;
 };
 
 // Processes user interaction events and developer provided speculation-rules
@@ -53,8 +51,7 @@
 
   // Receives and processes on pointer hover event for 'url' target link.
   void OnPointerHover(const GURL& url,
-                      blink::mojom::AnchorElementPointerDataPtr mouse_data,
-                      blink::mojom::SpeculationEagerness target_eagerness);
+                      blink::mojom::AnchorElementPointerDataPtr mouse_data);
 
   //  Receives and processes ML model score for 'url' target link.
   void OnPreloadingHeuristicsModelDone(const GURL& url, float score);
diff --git a/content/browser/preloading/preloading_decider_browsertest.cc b/content/browser/preloading/preloading_decider_browsertest.cc
index 439e1fe0..17398447 100644
--- a/content/browser/preloading/preloading_decider_browsertest.cc
+++ b/content/browser/preloading/preloading_decider_browsertest.cc
@@ -182,8 +182,7 @@
   } else if (predictor() == preloading_predictor::kUrlPointerHoverOnAnchor) {
     preloading_decider->OnPointerHover(
         next_page_url,
-        blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0),
-        blink::mojom::SpeculationEagerness::kModerate);
+        blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0));
   } else if (predictor() ==
              preloading_predictor::kPreloadingHeuristicsMLModel) {
     preloading_decider->OnPreloadingHeuristicsModelDone(next_page_url,
diff --git a/content/browser/preloading/preloading_decider_unittest.cc b/content/browser/preloading/preloading_decider_unittest.cc
index 5cdc74ca..511e141 100644
--- a/content/browser/preloading/preloading_decider_unittest.cc
+++ b/content/browser/preloading/preloading_decider_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/feature_list.h"
 #include "base/strings/strcat.h"
 #include "base/strings/to_string.h"
 #include "base/test/scoped_feature_list.h"
@@ -32,7 +31,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/preloading/anchor_element_interaction_host.mojom.h"
-#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-data-view.h"
 #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-shared.h"
 
 namespace content {
@@ -229,9 +227,6 @@
       PreloadingDecider::GetOrCreateForCurrentDocument(&GetPrimaryMainFrame());
   ASSERT_TRUE(preloading_decider != nullptr);
 
-  const bool use_eager_heurisctics =
-      base::FeatureList::IsEnabled(blink::features::kPreloadingEagerHeuristics);
-
   // Create list of SpeculationCandidatePtrs.
   std::vector<std::tuple<bool, GURL, blink::mojom::SpeculationAction,
                          blink::mojom::SpeculationEagerness>>
@@ -241,10 +236,7 @@
                  {true, GetCrossOriginUrl("/candidate2.html"),
                   blink::mojom::SpeculationAction::kPrefetch,
                   blink::mojom::SpeculationEagerness::kModerate},
-                 {use_eager_heurisctics, GetCrossOriginUrl("/candidate3.html"),
-                  blink::mojom::SpeculationAction::kPrefetch,
-                  blink::mojom::SpeculationEagerness::kEager},
-                 {false, GetCrossOriginUrl("/candidate4.html"),
+                 {false, GetCrossOriginUrl("/candidate3.html"),
                   blink::mojom::SpeculationAction::kPrefetch,
                   blink::mojom::SpeculationEagerness::kImmediate},
                  {true, GetCrossOriginUrl("/candidate1.html"),
@@ -253,10 +245,7 @@
                  {true, GetCrossOriginUrl("/candidate2.html"),
                   blink::mojom::SpeculationAction::kPrerender,
                   blink::mojom::SpeculationEagerness::kModerate},
-                 {use_eager_heurisctics, GetCrossOriginUrl("/candidate3.html"),
-                  blink::mojom::SpeculationAction::kPrerender,
-                  blink::mojom::SpeculationEagerness::kEager},
-                 {false, GetCrossOriginUrl("/candidate4.html"),
+                 {false, GetCrossOriginUrl("/candidate3.html"),
                   blink::mojom::SpeculationAction::kPrerender,
                   blink::mojom::SpeculationEagerness::kImmediate}};
   std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
@@ -277,22 +266,7 @@
 class PreloadingDeciderPointerEventHeuristicsTest
     : public PreloadingDeciderTest,
       public ::testing::WithParamInterface<
-          std::tuple<EventType, blink::mojom::SpeculationEagerness>> {
- public:
-  void SetUp() override {
-    feature_list_.InitAndEnableFeature(
-        blink::features::kPreloadingEagerHeuristics);
-    PreloadingDeciderTest::SetUp();
-  }
-
-  void TearDown() override {
-    PreloadingDeciderTest::TearDown();
-    feature_list_.Reset();
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
+          std::tuple<EventType, blink::mojom::SpeculationEagerness>> {};
 
 TEST_P(PreloadingDeciderPointerEventHeuristicsTest,
        PrefetchOnPointerEventHeuristics) {
@@ -317,8 +291,7 @@
         break;
       case EventType::kPointerHover:
         preloading_decider->OnPointerHover(
-            url, blink::mojom::AnchorElementPointerData::New(false, 0.0, 0.0),
-            eagerness);
+            url, blink::mojom::AnchorElementPointerData::New(false, 0.0, 0.0));
         break;
     }
   };
@@ -426,8 +399,7 @@
         break;
       case EventType::kPointerHover:
         preloading_decider->OnPointerHover(
-            url, blink::mojom::AnchorElementPointerData::New(false, 0.0, 0.0),
-            eagerness);
+            url, blink::mojom::AnchorElementPointerData::New(false, 0.0, 0.0));
         break;
     }
   };
@@ -526,8 +498,7 @@
     PreloadingDeciderPointerEventHeuristicsTest,
     testing::Combine(
         testing::Values(EventType::kPointerDown, EventType::kPointerHover),
-        testing::Values(blink::mojom::SpeculationEagerness::kEager,
-                        blink::mojom::SpeculationEagerness::kModerate,
+        testing::Values(blink::mojom::SpeculationEagerness::kModerate,
                         blink::mojom::SpeculationEagerness::kConservative)));
 
 TEST_F(PreloadingDeciderTest, UmaRecallStats) {
@@ -617,17 +588,15 @@
   candidates.push_back(candidate_1.Clone());
   candidates.push_back(candidate_2.Clone());
 
-  // Add conservative and moderate preload candidate and preload on
+  // Add conservative and moderate  preload candidate and preload on
   // pointer-hover.
   preloading_decider->UpdateSpeculationCandidates(candidates);
   const auto& prefetches = GetPrefetchService()->prefetches_;
   preloading_decider->OnPointerHover(
-      url,
-      blink::mojom::AnchorElementPointerData::New(
-          /*is_mouse_pointer=*/true,
-          /*mouse_velocity=*/75.0,
-          /*mouse_acceleration=*/0.0),
-      blink::mojom::SpeculationEagerness::kModerate);
+      url, blink::mojom::AnchorElementPointerData::New(
+               /*is_mouse_pointer=*/true,
+               /*mouse_velocity=*/75.0,
+               /*mouse_acceleration=*/0.0));
 
   EXPECT_TRUE(prefetches[0]->HasSpeculationRulesTags());
   EXPECT_EQ(prefetches[0]->GetSpeculationRulesTagsHeaderString().value(),
@@ -988,21 +957,17 @@
 
   GURL url1{"https://www.example.com"};
   preloading_decider->OnPointerHover(
-      url1,
-      blink::mojom::AnchorElementPointerData::New(
-          /*is_mouse_pointer=*/true,
-          /*mouse_velocity=*/50.0,
-          /*mouse_acceleration=*/0.0),
-      /*is_eager=*/blink::mojom::SpeculationEagerness::kModerate);
+      url1, blink::mojom::AnchorElementPointerData::New(
+                /*is_mouse_pointer=*/true,
+                /*mouse_velocity=*/50.0,
+                /*mouse_acceleration=*/0.0));
 
   GURL url2{"https://www.google.com"};
   preloading_decider->OnPointerHover(
-      url2,
-      blink::mojom::AnchorElementPointerData::New(
-          /*is_mouse_pointer=*/true,
-          /*mouse_velocity=*/75.0,
-          /*mouse_acceleration=*/0.0),
-      /*is_eager=*/blink::mojom::SpeculationEagerness::kModerate);
+      url2, blink::mojom::AnchorElementPointerData::New(
+                /*is_mouse_pointer=*/true,
+                /*mouse_velocity=*/75.0,
+                /*mouse_acceleration=*/0.0));
 
   // Navigate to `url2`.
   NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url2);
@@ -1197,8 +1162,7 @@
   // The page has never received a prediction from the ML model, so we fallback
   // to the decisions of the hover heuristic.
   preloading_decider->OnPointerHover(
-      url, blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0),
-      blink::mojom::SpeculationEagerness::kModerate);
+      url, blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0));
   EXPECT_EQ(1u, prefetches.size());
 }
 
@@ -1356,8 +1320,7 @@
   // The model has indicated that the candidate is not worth prefetching, so we
   // should not prefetch based on the hover heuristic either.
   preloading_decider->OnPointerHover(
-      url, blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0),
-      blink::mojom::SpeculationEagerness::kModerate);
+      url, blink::mojom::AnchorElementPointerData::New(true, 0.0, 0.0));
   EXPECT_TRUE(prefetches.empty());
   // But once we have a stronger signal like pointer down, we should prefetch.
   preloading_decider->OnPointerDown(url);
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc
index 98475c7..d23ffef1 100644
--- a/content/browser/preloading/prerender/prerender_browsertest.cc
+++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
-#include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback_forward.h"
@@ -36,7 +35,6 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/test/test_timeouts.h"
 #include "base/thread_annotations.h"
-#include "base/time/time.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "cc/base/features.h"
@@ -887,9 +885,7 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
   }
 
-  void PointerHoverToAnchor(
-      const GURL& url,
-      const std::optional<base::TimeDelta>& hover_time = std::nullopt) {
+  void PointerHoverToAnchor(const GURL& url) {
     ResetPointerPosition();
 
 #if !BUILDFLAG(IS_ANDROID)
@@ -900,13 +896,6 @@
     SimulateMouseEvent(web_contents(), blink::WebMouseEvent::Type::kMouseMove,
                        blink::WebMouseEvent::Button::kNoButton, point);
     waiter.Wait();
-    if (hover_time) {
-      base::RunLoop run_loop;
-      base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
-          FROM_HERE, run_loop.QuitClosure(), *hover_time);
-      run_loop.Run();
-      ResetPointerPosition();
-    }
 #else
     // TODO(crbug.com/40269669): Simulate |WebGestureEvent| to make this
     // function work for Android.
@@ -10630,9 +10619,6 @@
  public:
   void SetUp() override {
 #if !BUILDFLAG(IS_ANDROID)
-    sub_feature_list_.InitAndEnableFeatureWithParameters(
-        blink::features::kPreloadingEagerHeuristics,
-        {{"hover_dwell_time", "50ms"}});
     PrerenderBrowserTest::SetUp();
 #else
     // TODO(crbug.com/40269669): Add the implementation of pointer interaction
@@ -10640,14 +10626,6 @@
     GTEST_SKIP();
 #endif  // BUILDFLAG(IS_ANDROID)
   }
-
-  void TearDown() override {
-    PrerenderBrowserTest::TearDown();
-    sub_feature_list_.Reset();
-  }
-
- private:
-  base::test::ScopedFeatureList sub_feature_list_;
 };
 
 namespace {
@@ -10675,9 +10653,7 @@
     OnEventCalled(Events::kUpdateSpeculationCandidates);
   }
 
-  void OnPointerHover(
-      const GURL& url,
-      blink::mojom::SpeculationEagerness target_eagerness) override {
+  void OnPointerHover(const GURL& url) override {
     OnEventCalled(Events::kOnPointerHover);
   }
 
@@ -10765,9 +10741,8 @@
 }
 
 // Tests speculation rules prerendering where the eagerness is "eager".
-// Unless `kPreloadingEagerHeuristics` is enabled, its behavior is the same as
-// that of "immediate"; otherwise, there are dedicated rules to activate
-// speculative loads.
+// Currently, its behavior is the same as that of "immediate".
+// TODO(crbug.com/40287486): Update this test after the behavior changes.
 IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest, kEager) {
   const GURL initial_url = GetUrl("/empty.html");
   const GURL prerendering_url = GetUrl("/empty.html?prerender");
@@ -10776,63 +10751,20 @@
   ASSERT_TRUE(NavigateToURL(shell(), initial_url));
   InsertAnchor(prerendering_url);
 
-  if (base::FeatureList::IsEnabled(
-          blink::features::kPreloadingEagerHeuristics)) {
-    const base::TimeDelta moderate_hover_time = base::Milliseconds(200);
-    const base::TimeDelta eager_hover_time =
-        blink::features::kPreloadingEagerHeuristicsHoverDwellTime.Get();
-    ASSERT_LE(eager_hover_time, moderate_hover_time);
-    // Use `eager_hover_time` + eps. The median time can cause flakiness.
-    const base::TimeDelta mid_hover_time =
-        eager_hover_time + (moderate_hover_time - eager_hover_time) / 10;
+  RenderFrameHostImpl* rfh = current_frame_host();
+  auto* preloading_decider =
+      PreloadingDecider::GetOrCreateForCurrentDocument(rfh);
 
-    RenderFrameHostImpl* rfh = current_frame_host();
-    PreloadingDeciderObserverForPrerenderTesting preloading_decider_observer(
-        rfh);
-    auto* preloading_decider =
-        PreloadingDecider::GetOrCreateForCurrentDocument(rfh);
-    // Add speculation rules with the "eager" eagerness.
-    // When the eagerness is not "immediate", speculation candidates will be
-    // kept in the |on_standby_candidates_| on |PreloadingDecider|.
-    // |PrerenderHost| will not be created at this time, waiting for user
-    // interaction(pointer hovering for the "eager").
-    AddPrerenderWithEagernessAsync(prerendering_url,
-                                   blink::mojom::SpeculationEagerness::kEager);
-    preloading_decider_observer.WaitUpdateSpeculationCandidates();
-    EXPECT_FALSE(HasHostForUrl(prerendering_url));
-    EXPECT_TRUE(preloading_decider->IsOnStandByForTesting(
-        prerendering_url, blink::mojom::SpeculationAction::kPrerender));
-    // Hover the anchor of the prerendering page. When eagerness is "eager" with
-    // `kPreloadingEagerHeuristics` enabled, this interaction invokes the
-    // creation of |PrerenderHost|.
-    ASSERT_GT(eager_hover_time, base::Milliseconds(0));
-    // Hover very briefly so that prerender is not triggered.
-    PointerHoverToAnchor(prerendering_url, eager_hover_time / 2);
-    EXPECT_TRUE(preloading_decider->IsOnStandByForTesting(
-        prerendering_url, blink::mojom::SpeculationAction::kPrerender));
-    // Hover enough time so that prerender is triggered for "eager".
-    PointerHoverToAnchor(prerendering_url, mid_hover_time);
-    preloading_decider_observer.WaitOnPointerHover();
-    WaitForPrerenderLoadCompletion(prerendering_url);
-    EXPECT_TRUE(HasHostForUrl(prerendering_url));
-    EXPECT_FALSE(preloading_decider->IsOnStandByForTesting(
-        prerendering_url, blink::mojom::SpeculationAction::kPrerender));
-  } else {
-    RenderFrameHostImpl* rfh = current_frame_host();
-    auto* preloading_decider =
-        PreloadingDecider::GetOrCreateForCurrentDocument(rfh);
-    // Add speculation rules with the "eager" eagerness.
-    // With `kPreloadingEagerHeuristics` disabled, the eagerness is the same as
-    // "immediate", speculation candidates will never be kept in the
-    // |on_standby_candidates_| on |PreloadingDecider|, and |PrerenderHost| will
-    // be created immediately.
-    AddPrerenderWithEagernessAsync(prerendering_url,
-                                   blink::mojom::SpeculationEagerness::kEager);
-    WaitForPrerenderLoadCompletion(prerendering_url);
-    EXPECT_TRUE(HasHostForUrl(prerendering_url));
-    EXPECT_FALSE(preloading_decider->IsOnStandByForTesting(
-        prerendering_url, blink::mojom::SpeculationAction::kPrerender));
-  }
+  // Add speculation rules with the eagerness.
+  // When the eagerness is "immediate", speculation candidates will never be
+  // kept in the |on_standby_candidates_| on |PreloadingDecider|, and
+  // |PrerenderHost| will be created immediately.
+  AddPrerenderWithEagernessAsync(prerendering_url,
+                                 blink::mojom::SpeculationEagerness::kEager);
+  WaitForPrerenderLoadCompletion(prerendering_url);
+  EXPECT_TRUE(HasHostForUrl(prerendering_url));
+  EXPECT_FALSE(preloading_decider->IsOnStandByForTesting(
+      prerendering_url, blink::mojom::SpeculationAction::kPrerender));
 
   // Activate the prerendered page by clicking the anchor.
   FrameTreeNodeId host_id = GetHostForUrl(prerendering_url);
@@ -10870,27 +10802,8 @@
   EXPECT_TRUE(preloading_decider->IsOnStandByForTesting(
       prerendering_url, blink::mojom::SpeculationAction::kPrerender));
 
-  // Hover the anchor of the prerendering page so briefly that only the hover
-  // event for "eager" is triggered but not triggered for "moderate".
-  if (base::FeatureList::IsEnabled(
-          blink::features::kPreloadingEagerHeuristics)) {
-    const base::TimeDelta moderate_hover_time = base::Milliseconds(200);
-    const base::TimeDelta eager_hover_time =
-        blink::features::kPreloadingEagerHeuristicsHoverDwellTime.Get();
-    // Use `eager_hover_time` + eps. The median time can cause flakiness.
-    const base::TimeDelta mid_hover_time =
-        eager_hover_time + (moderate_hover_time - eager_hover_time) / 10;
-    ASSERT_LT(mid_hover_time, moderate_hover_time);
-    PointerHoverToAnchor(prerendering_url, mid_hover_time);
-    preloading_decider_observer.WaitOnPointerHover();
-    EXPECT_FALSE(HasHostForUrl(prerendering_url));
-    EXPECT_TRUE(preloading_decider->IsOnStandByForTesting(
-        prerendering_url, blink::mojom::SpeculationAction::kPrerender));
-  }
-
-  // Hover the anchor of the prerendering page for a long enough time. When
-  // eagerness is "moderate", this interaction invokes the creation of
-  // |PrerenderHost|.
+  // Hover the anchor of the prerendering page. When eagerness is "moderate",
+  // this interaction invokes the creation of |PrerenderHost|.
   PointerHoverToAnchor(prerendering_url);
   preloading_decider_observer.WaitOnPointerHover();
   WaitForPrerenderLoadCompletion(prerendering_url);
@@ -11406,11 +11319,12 @@
 // Test whether speculation rules prerendering is processed again on pages
 // restored from BFCache via forward navigation.
 // When the eagerness is kImmediate(default), speculation rules prerendering
-// will no longer be processed after restoration. For non-immediate cases,
-// candidates are stored between restoration unless they were triggered by user
-// action (This test scenario reproduces only this case). However, once after
-// processed by user action, then they will not be processed again until they
-// are retriggered (crbug.com/1449163 for more information).
+// will no longer be processed after restoration. For non-immediate cases
+// (kModerate, kConservative), candidates are stored between restoration unless
+// they were triggered by user action (This test scenario reproduces only this
+// case). However, once after processed by user action, then they will not be
+// processed again until they are retriggered (crbug.com/1449163 for more
+// information).
 IN_PROC_BROWSER_TEST_P(PrerenderBackForwardCacheRestorationBrowserTest,
                        RestoredViaForwardNavigation) {
   const GURL initial_url = GetUrl("/empty.html");
diff --git a/content/browser/preloading/speculation_rules/speculation_host_impl_unittest.cc b/content/browser/preloading/speculation_rules/speculation_host_impl_unittest.cc
index 00f3525..f1d576b 100644
--- a/content/browser/preloading/speculation_rules/speculation_host_impl_unittest.cc
+++ b/content/browser/preloading/speculation_rules/speculation_host_impl_unittest.cc
@@ -112,9 +112,7 @@
     }
   }
   void OnPointerDown(const GURL& url) override {}
-  void OnPointerHover(
-      const GURL& url,
-      blink::mojom::SpeculationEagerness target_eagerness) override {}
+  void OnPointerHover(const GURL& url) override {}
 
   std::vector<blink::mojom::SpeculationCandidatePtr> candidates_;
 
diff --git a/content/browser/preloading/speculation_rules/speculation_rules_util.h b/content/browser/preloading/speculation_rules/speculation_rules_util.h
index 72e878d..bbaf9e2 100644
--- a/content/browser/preloading/speculation_rules/speculation_rules_util.h
+++ b/content/browser/preloading/speculation_rules/speculation_rules_util.h
@@ -5,8 +5,6 @@
 #ifndef CONTENT_BROWSER_PRELOADING_SPECULATION_RULES_SPECULATION_RULES_UTIL_H_
 #define CONTENT_BROWSER_PRELOADING_SPECULATION_RULES_SPECULATION_RULES_UTIL_H_
 
-#include "base/feature_list.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-shared.h"
 
 namespace content {
@@ -22,10 +20,8 @@
     // `kEager` trigger strategies.
     // TODO(crbug.com/40287486): Update this according to the latest situation.
     case blink::mojom::SpeculationEagerness::kImmediate:
-      return true;
     case blink::mojom::SpeculationEagerness::kEager:
-      return !base::FeatureList::IsEnabled(
-          blink::features::kPreloadingEagerHeuristics);
+      return true;
     case blink::mojom::SpeculationEagerness::kModerate:
     case blink::mojom::SpeculationEagerness::kConservative:
       return false;
diff --git a/content/browser/push_messaging/push_messaging_manager.cc b/content/browser/push_messaging/push_messaging_manager.cc
index 847b5ed..961c7a69 100644
--- a/content/browser/push_messaging/push_messaging_manager.cc
+++ b/content/browser/push_messaging/push_messaging_manager.cc
@@ -41,13 +41,6 @@
 
 namespace content {
 
-// Service Worker database keys. If a registration ID is stored, the stored
-// sender ID must be the one used to register. Unfortunately, this isn't always
-// true of pre-InstanceID registrations previously stored in the database, but
-// fortunately it's less important for their sender ID to be accurate.
-const char kPushSenderIdServiceWorkerKey[] = "push_sender_id";
-const char kPushRegistrationIdServiceWorkerKey[] = "push_registration_id";
-
 namespace {
 
 // Chrome currently does not support the Push API in incognito.
diff --git a/content/browser/push_messaging/push_messaging_manager.h b/content/browser/push_messaging/push_messaging_manager.h
index 85acac3..e3ef2001 100644
--- a/content/browser/push_messaging/push_messaging_manager.h
+++ b/content/browser/push_messaging/push_messaging_manager.h
@@ -21,12 +21,10 @@
 #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
 #include "url/gurl.h"
 
-namespace blink {
-namespace mojom {
+namespace blink::mojom {
 enum class PushRegistrationStatus;
 enum class PushUnregistrationStatus;
-}  // namespace mojom
-}  // namespace blink
+}  // namespace blink::mojom
 
 namespace url {
 class Origin;
@@ -38,9 +36,13 @@
 class RenderProcessHost;
 class ServiceWorkerContextWrapper;
 
-// Documented at definition.
-extern const char kPushSenderIdServiceWorkerKey[];
-extern const char kPushRegistrationIdServiceWorkerKey[];
+// Service Worker database keys. If a registration ID is stored, the stored
+// sender ID must be the one used to register. Unfortunately, this isn't always
+// true of pre-InstanceID registrations previously stored in the database, but
+// fortunately it's less important for their sender ID to be accurate.
+inline constexpr char kPushSenderIdServiceWorkerKey[] = "push_sender_id";
+inline constexpr char kPushRegistrationIdServiceWorkerKey[] =
+    "push_registration_id";
 
 // Owned by RenderFrameHostImpl (if `this` handles requests from a document) or
 // RenderProcessHostImpl (if `this` handles requests from a service worker).
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
index 2da8237..ce4a073b 100644
--- a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -24,6 +24,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
+#include "components/viz/common/resources/shared_image_format.h"
 #include "content/browser/renderer_host/media/video_capture_controller.h"
 #include "media/base/video_frame.h"
 #include "media/capture/video/video_capture_buffer_pool_impl.h"
@@ -457,8 +458,8 @@
 namespace {
 
 gfx::GpuMemoryBufferHandle CreateIOSurfaceHandle() {
-  return gfx::GpuMemoryBufferHandle(
-      gfx::CreateIOSurface(kDefaultTextureSize, gfx::BufferFormat::BGRA_8888));
+  return gfx::GpuMemoryBufferHandle(gfx::CreateIOSurface(
+      kDefaultTextureSize, viz::SinglePlaneFormat::kBGRA_8888));
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index dc244937..4b0319a 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2758,8 +2758,10 @@
   if (!data_url_as_string)
     return false;
 
-  if (data_url_as_string->size() > kMaxLengthOfDataURLString)
+  if (data_url_as_string->size() >
+      kMaxLengthOfDataURLString.InBytesUnsigned()) {
     return false;
+  }
 
   // The number of characters that is enough for validating a data: URI.
   // From the GURL's POV, the only important part here is scheme, it doesn't
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index ed90fa67..eb7c284 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -103,6 +103,7 @@
 #include "ui/events/blink/web_input_event_traits.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
+#include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/gfx/android/view_configuration.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/geometry/dip_util.h"
@@ -2476,10 +2477,42 @@
   host_->LostPointerLock();
 }
 
+bool RenderWidgetHostViewAndroid::LockKeyboard(
+    std::optional<base::flat_set<ui::DomCode>> codes) {
+  CHECK(!keyboard_locked_);
+
+  if (!base::FeatureList::IsEnabled(features::kKeyboardLockApiOnAndroid)) {
+    return false;
+  }
+
+  ui::WindowAndroid* window_android = view_.GetWindowAndroid();
+  if (!window_android) {
+    return false;
+  }
+
+  if (!window_android->SetHasKeyboardCapture(true)) {
+    return false;
+  }
+
+  keyboard_locked_ = true;
+  locked_keyboard_keys_ = codes;
+  return true;
+}
+
+void RenderWidgetHostViewAndroid::UnlockKeyboard() {
+  CHECK(keyboard_locked_);
+  CHECK(base::FeatureList::IsEnabled(features::kKeyboardLockApiOnAndroid));
+  keyboard_locked_ = false;
+  locked_keyboard_keys_.reset();
+  if (ui::WindowAndroid* window_android = view_.GetWindowAndroid()) {
+    window_android->SetHasKeyboardCapture(false);
+  }
+}
+
 // Methods called from the host to the render
 
 void RenderWidgetHostViewAndroid::SendKeyEvent(
-    const input::NativeWebKeyboardEvent& event) {
+    input::NativeWebKeyboardEvent& event) {
   if (!host())
     return;
 
@@ -2497,6 +2530,17 @@
   if (text_suggestion_host_)
     text_suggestion_host_->OnKeyEvent();
 
+  // If the key has been reserved as part of the active KeyboardLock request,
+  // then we want to mark it as such so it is not intercepted by the browser.
+  if (keyboard_locked_) {
+    ui::DomCode dom_code = static_cast<ui::DomCode>(event.dom_code);
+    if (dom_code != ui::DomCode::ESCAPE &&
+        (!locked_keyboard_keys_ ||
+         base::Contains(locked_keyboard_keys_.value(), dom_code))) {
+      event.skip_if_unhandled = true;
+    }
+  }
+
   ui::LatencyInfo latency_info;
   latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
   target_host->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 7ac6fc5..e1108858 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -215,6 +215,8 @@
       bool request_unadjusted_movement) override;
   bool IsPointerLocked() override;
   void UnlockPointer() override;
+  bool LockKeyboard(std::optional<base::flat_set<ui::DomCode>> codes) override;
+  void UnlockKeyboard() override;
   void InvalidateLocalSurfaceIdAndAllocationGroup() override;
   void ClearFallbackSurfaceForCommitPending() override;
   void ResetFallbackToFirstNavigationSurface() override;
@@ -320,7 +322,7 @@
   // Returns the temporary background color of the underlaying document, for
   // example, returns black during screen rotation.
   std::optional<SkColor> GetCachedBackgroundColor();
-  void SendKeyEvent(const input::NativeWebKeyboardEvent& event);
+  void SendKeyEvent(input::NativeWebKeyboardEvent& event);
   void SendMouseEvent(const blink::WebMouseEvent& event,
                       const ui::LatencyInfo& info);
   void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
@@ -807,6 +809,9 @@
 
   ScreenStateChangeHandler screen_state_change_handler_;
 
+  bool keyboard_locked_ = false;
+  std::optional<base::flat_set<ui::DomCode>> locked_keyboard_keys_;
+
   base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_{this};
 };
 
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 86da823..a6f89819 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -72,7 +72,6 @@
     "common_param_traits.cc",
     "common_param_traits.h",
     "common_param_traits_macros.h",
-    "content_constants_internal.cc",
     "content_constants_internal.h",
     "content_export.h",
     "content_navigation_policy.cc",
diff --git a/content/common/content_constants_internal.cc b/content/common/content_constants_internal.cc
deleted file mode 100644
index ae77550..0000000
--- a/content/common/content_constants_internal.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#include "content/common/content_constants_internal.h"
-
-#include "media/media_buildflags.h"
-
-namespace content {
-
-// 20MiB
-const size_t kMaxLengthOfDataURLString = 1024 * 1024 * 20;
-
-#if BUILDFLAG(ENABLE_AV1_DECODER)
-const char kFrameAcceptHeaderValue[] =
-    "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,"
-    "image/webp,image/apng,*/*;q=0.8";
-#else
-const char kFrameAcceptHeaderValue[] =
-    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
-    "image/apng,*/*;q=0.8";
-#endif
-
-const int kChildProcessReceiverAttachmentName = 0;
-const int kChildProcessHostRemoteAttachmentName = 1;
-const int kLegacyIpcBootstrapAttachmentName = 2;
-
-} // namespace content
diff --git a/content/common/content_constants_internal.h b/content/common/content_constants_internal.h
index f945ac0..88044bd 100644
--- a/content/common/content_constants_internal.h
+++ b/content/common/content_constants_internal.h
@@ -8,22 +8,32 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/byte_count.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
+#include "media/media_buildflags.h"
 
 namespace content {
 
 // The maximum length of string as data url.
-extern const size_t kMaxLengthOfDataURLString;
+inline constexpr base::ByteCount kMaxLengthOfDataURLString = base::MiB(20);
 
 // Accept header used for frame requests.
-CONTENT_EXPORT extern const char kFrameAcceptHeaderValue[];
+#if BUILDFLAG(ENABLE_AV1_DECODER)
+inline constexpr char kFrameAcceptHeaderValue[] =
+    "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,"
+    "image/webp,image/apng,*/*;q=0.8";
+#else
+inline constexpr char kFrameAcceptHeaderValue[] =
+    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
+    "image/apng,*/*;q=0.8";
+#endif
 
 // Constants for attaching message pipes to the mojo invitation used to
 // initialize child processes.
-extern const int kChildProcessReceiverAttachmentName;
-extern const int kChildProcessHostRemoteAttachmentName;
-extern const int kLegacyIpcBootstrapAttachmentName;
+inline constexpr int kChildProcessReceiverAttachmentName = 0;
+inline constexpr int kChildProcessHostRemoteAttachmentName = 1;
+inline constexpr int kLegacyIpcBootstrapAttachmentName = 2;
 
 } // namespace content
 
diff --git a/content/common/content_navigation_policy.cc b/content/common/content_navigation_policy.cc
index c1a0fbf5..b7f75c9 100644
--- a/content/common/content_navigation_policy.cc
+++ b/content/common/content_navigation_policy.cc
@@ -84,8 +84,6 @@
   return IsBackForwardCacheEnabled();
 }
 
-const char kRenderDocumentLevelParameterName[] = "level";
-
 constexpr base::FeatureParam<RenderDocumentLevel>::Option
     render_document_levels[] = {
         {RenderDocumentLevel::kCrashedFrame, "crashed-frame"},
diff --git a/content/common/content_navigation_policy.h b/content/common/content_navigation_policy.h
index 96b4a51..8f6b293 100644
--- a/content/common/content_navigation_policy.h
+++ b/content/common/content_navigation_policy.h
@@ -58,7 +58,7 @@
 CONTENT_EXPORT RenderDocumentLevel GetRenderDocumentLevel();
 CONTENT_EXPORT std::string GetRenderDocumentLevelName(
     RenderDocumentLevel level);
-CONTENT_EXPORT extern const char kRenderDocumentLevelParameterName[];
+inline constexpr char kRenderDocumentLevelParameterName[] = "level";
 
 // If this is false we continue the old behaviour of doing an early call to
 // RenderFrameHostManager::CommitPending when we are replacing a crashed
diff --git a/content/public/browser/navigation_ui_data.h b/content/public/browser/navigation_ui_data.h
index a873128..cadbed90 100644
--- a/content/public/browser/navigation_ui_data.h
+++ b/content/public/browser/navigation_ui_data.h
@@ -10,8 +10,7 @@
 namespace content {
 
 // Copyable interface for embedders to pass opaque data to content/. It is
-// expected to be created on the UI thread at the start of the navigation, and
-// content/ will transfer it to the IO thread as a clone.
+// expected to be created on the UI thread at the start of the navigation.
 class NavigationUIData {
  public:
   virtual ~NavigationUIData() {}
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 0fbf242..60bc8a8 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -1585,6 +1585,12 @@
              base::FEATURE_ENABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+BASE_FEATURE(kKeyboardLockApiOnAndroid,
+             "KeyboardLockApiOnAndroid",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 // Default amount of days after which the global navigation capturing IPH
 // guardrails are cleared from storage.
 const base::FeatureParam<int> kNavigationCapturingIPHGuardrailStorageDuration{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 8308746..11d4236 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -361,6 +361,10 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebauthnDisabledOnAuto);
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kKeyboardLockApiOnAndroid);
+#endif  // BUILDFLAG(IS_ANDROID)
+
 // Number of days to "store" IPH guardrails for navigation captured app launches
 // till they are cleared.
 CONTENT_EXPORT extern const base::FeatureParam<int>
diff --git a/content/services/auction_worklet/worklet_test_util.cc b/content/services/auction_worklet/worklet_test_util.cc
index 2355d89..31ba0c63 100644
--- a/content/services/auction_worklet/worklet_test_util.cc
+++ b/content/services/auction_worklet/worklet_test_util.cc
@@ -28,14 +28,6 @@
 
 namespace auction_worklet {
 
-const char kJavascriptMimeType[] = "application/javascript";
-const char kJsonMimeType[] = "application/json";
-const char kWasmMimeType[] = "application/wasm";
-const char kAdAuctionTrustedSignalsMimeType[] =
-    "message/ad-auction-trusted-signals-response";
-
-const char kAllowFledgeHeader[] = "Ad-Auction-Allowed: true";
-
 void AddResponse(network::TestURLLoaderFactory* url_loader_factory,
                  const GURL& url,
                  std::optional<std::string> mime_type,
diff --git a/content/services/auction_worklet/worklet_test_util.h b/content/services/auction_worklet/worklet_test_util.h
index c1ab954..6f6f8d5 100644
--- a/content/services/auction_worklet/worklet_test_util.h
+++ b/content/services/auction_worklet/worklet_test_util.h
@@ -31,13 +31,14 @@
 
 // The official Javascript, JSON, and WASM MIME types. For JS and JSON there are
 // also other supported MIME types.
-extern const char kJavascriptMimeType[];
-extern const char kJsonMimeType[];
-extern const char kWasmMimeType[];
-extern const char kAdAuctionTrustedSignalsMimeType[];
+inline constexpr char kJavascriptMimeType[] = "application/javascript";
+inline constexpr char kJsonMimeType[] = "application/json";
+inline constexpr char kWasmMimeType[] = "application/wasm";
+inline constexpr char kAdAuctionTrustedSignalsMimeType[] =
+    "message/ad-auction-trusted-signals-response";
 
 // "X-Allow-Fledge: true" header.
-extern const char kAllowFledgeHeader[];
+inline constexpr char kAllowFledgeHeader[] = "Ad-Auction-Allowed: true";
 
 // Enqueues a response to `url_loader_factory` using the specified values.
 //
diff --git a/content/shell/common/shell_switches.cc b/content/shell/common/shell_switches.cc
index 8a414d7..5b05ea2 100644
--- a/content/shell/common/shell_switches.cc
+++ b/content/shell/common/shell_switches.cc
@@ -8,47 +8,6 @@
 
 namespace switches {
 
-// Makes Content Shell use the given path for its data directory.
-// NOTE: "user-data-dir" is used to align with Chromedriver's behavior. Please
-// do NOT change this to another value.
-// NOTE: The same value is also used at Java-side in
-// ContentShellBrowserTestActivity.java#getUserDataDirectoryCommandLineSwitch().
-const char kContentShellUserDataDir[] = "user-data-dir";
-
-// The directory Crashpad should store minidumps in.
-// iOS and tvOS default to app's cache directory.
-const char kCrashDumpsDir[] = "crash-dumps-dir";
-
-// Disables the check for the system font when specified.
-const char kDisableSystemFontCheck[] = "disable-system-font-check";
-
-// Exposes the window.internals object to JavaScript for interactive development
-// and debugging of web tests that rely on it.
-const char kExposeInternalsForTesting[] = "expose-internals-for-testing";
-
-// Size for the content_shell's host window (i.e. "800x600").
-const char kContentShellHostWindowSize[] = "content-shell-host-window-size";
-
-// Hides toolbar from content_shell's host window.
-const char kContentShellHideToolbar[] = "content-shell-hide-toolbar";
-
-// Enables APIs guarded with the [IsolatedContext] IDL attribute for the given
-// comma-separated list of origins.
-const char kIsolatedContextOrigins[] = "isolated-context-origins";
-
-// Use the given address instead of the default loopback for accepting remote
-// debugging connections. Note that the remote debugging protocol does not
-// perform any authentication, so exposing it too widely can be a security
-// risk.
-const char kRemoteDebuggingAddress[] = "remote-debugging-address";
-
-// Runs Content Shell in web test mode, injecting test-only behaviour for
-// blink web tests.
-const char kRunWebTests[] = "run-web-tests";
-
-// Register the provided scheme as a standard scheme.
-const char kTestRegisterStandardScheme[] = "test-register-standard-scheme";
-
 bool IsRunWebTestsSwitchPresent() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kRunWebTests);
diff --git a/content/shell/common/shell_switches.h b/content/shell/common/shell_switches.h
index de53c1f..8757fa4 100644
--- a/content/shell/common/shell_switches.h
+++ b/content/shell/common/shell_switches.h
@@ -11,16 +11,52 @@
 
 namespace switches {
 
-extern const char kContentShellUserDataDir[];
-extern const char kCrashDumpsDir[];
-extern const char kDisableSystemFontCheck[];
-extern const char kExposeInternalsForTesting[];
-extern const char kContentShellHostWindowSize[];
-extern const char kContentShellHideToolbar[];
-extern const char kIsolatedContextOrigins[];
-extern const char kRemoteDebuggingAddress[];
-extern const char kRunWebTests[];
-extern const char kTestRegisterStandardScheme[];
+// Makes Content Shell use the given path for its data directory.
+//
+// NOTE: "user-data-dir" is used to align with Chromedriver's behavior. Please
+// do NOT change this to another value.
+//
+// NOTE: The same value is also used at Java-side in
+// ContentShellBrowserTestActivity.java#getUserDataDirectoryCommandLineSwitch().
+inline constexpr char kContentShellUserDataDir[] = "user-data-dir";
+
+// The directory Crashpad should store minidumps in.
+//
+// iOS and tvOS default to app's cache directory.
+inline constexpr char kCrashDumpsDir[] = "crash-dumps-dir";
+
+// Disables the check for the system font when specified.
+inline constexpr char kDisableSystemFontCheck[] = "disable-system-font-check";
+
+// Exposes the window.internals object to JavaScript for interactive development
+// and debugging of web tests that rely on it.
+inline constexpr char kExposeInternalsForTesting[] =
+    "expose-internals-for-testing";
+
+// Size for the content_shell's host window (i.e. "800x600").
+inline constexpr char kContentShellHostWindowSize[] =
+    "content-shell-host-window-size";
+
+// Hides toolbar from content_shell's host window.
+inline constexpr char kContentShellHideToolbar[] = "content-shell-hide-toolbar";
+
+// Enables APIs guarded with the [IsolatedContext] IDL attribute for the given
+// comma-separated list of origins.
+inline constexpr char kIsolatedContextOrigins[] = "isolated-context-origins";
+
+// Use the given address instead of the default loopback for accepting remote
+// debugging connections. Note that the remote debugging protocol does not
+// perform any authentication, so exposing it too widely can be a security
+// risk.
+inline constexpr char kRemoteDebuggingAddress[] = "remote-debugging-address";
+
+// Runs Content Shell in web test mode, injecting test-only behaviour for
+// blink web tests.
+inline constexpr char kRunWebTests[] = "run-web-tests";
+
+// Register the provided scheme as a standard scheme.
+inline constexpr char kTestRegisterStandardScheme[] =
+    "test-register-standard-scheme";
 
 // Helper that returns true if kRunWebTests is present in the command line,
 // meaning Content Shell is running in web test mode.
diff --git a/content/test/data/forms/form_controls_browsertest_meter_mac.png b/content/test/data/forms/form_controls_browsertest_meter_mac.png
index 22ae801..9918345 100644
--- a/content/test/data/forms/form_controls_browsertest_meter_mac.png
+++ b/content/test/data/forms/form_controls_browsertest_meter_mac.png
Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_progress_win.png b/content/test/data/forms/form_controls_browsertest_progress_win.png
index 29c7ae90..249061b 100644
--- a/content/test/data/forms/form_controls_browsertest_progress_win.png
+++ b/content/test/data/forms/form_controls_browsertest_progress_win.png
Binary files differ
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn
index 40c262f..ab961bcc 100644
--- a/content/web_test/BUILD.gn
+++ b/content/web_test/BUILD.gn
@@ -46,13 +46,11 @@
   sources = [
     "common/tracked_dictionary.cc",
     "common/tracked_dictionary.h",
-    "common/web_test_constants.cc",
     "common/web_test_constants.h",
     "common/web_test_runtime_flags.cc",
     "common/web_test_runtime_flags.h",
     "common/web_test_string_util.cc",
     "common/web_test_string_util.h",
-    "common/web_test_switches.cc",
     "common/web_test_switches.h",
   ]
   public_deps = [
diff --git a/content/web_test/common/web_test_constants.cc b/content/web_test/common/web_test_constants.cc
deleted file mode 100644
index 3178c22c..0000000
--- a/content/web_test/common/web_test_constants.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/web_test/common/web_test_constants.h"
-
-namespace content {
-
-// DictValue key to show if the work queue has something to do.
-const char kDictKeyWorkQueueHasItems[] = "has_items";
-
-}  // namespace content
diff --git a/content/web_test/common/web_test_constants.h b/content/web_test/common/web_test_constants.h
index 0719981c..eab7704 100644
--- a/content/web_test/common/web_test_constants.h
+++ b/content/web_test/common/web_test_constants.h
@@ -7,7 +7,8 @@
 
 namespace content {
 
-extern const char kDictKeyWorkQueueHasItems[];
+// DictValue key to show if the work queue has something to do.
+inline constexpr char kDictKeyWorkQueueHasItems[] = "has_items";
 
 }  // namespace content
 
diff --git a/content/web_test/common/web_test_string_util.cc b/content/web_test/common/web_test_string_util.cc
index 15f9073..b60c0816 100644
--- a/content/web_test/common/web_test_string_util.cc
+++ b/content/web_test/common/web_test_string_util.cc
@@ -21,19 +21,17 @@
 
 constexpr std::string_view kWebTestsPattern = "/web_tests/";
 constexpr std::string_view kFileURLPattern = "file://";
-const char* kFileTestPrefix = "(file test):";
-const char* kPolicyDownload = "download";
-const char* kPolicyCurrentTab = "current tab";
-const char* kPolicyNewBackgroundTab = "new background tab";
-const char* kPolicyNewForegroundTab = "new foreground tab";
-const char* kPolicyNewWindow = "new window";
-const char* kPolicyNewPopup = "new popup";
-const char* kPolicyPictureInPicture = "picture in picture";
+constexpr char kFileTestPrefix[] = "(file test):";
+constexpr char kPolicyDownload[] = "download";
+constexpr char kPolicyCurrentTab[] = "current tab";
+constexpr char kPolicyNewBackgroundTab[] = "new background tab";
+constexpr char kPolicyNewForegroundTab[] = "new foreground tab";
+constexpr char kPolicyNewWindow[] = "new window";
+constexpr char kPolicyNewPopup[] = "new popup";
+constexpr char kPolicyPictureInPicture[] = "picture in picture";
 
 }  // namespace
 
-const char* kIllegalString = "illegal value";
-
 std::string NormalizeWebTestURLForTextOutput(const std::string& url) {
   std::string result = url;
   if (base::StartsWith(url, kFileURLPattern)) {
diff --git a/content/web_test/common/web_test_string_util.h b/content/web_test/common/web_test_string_util.h
index 571fc81f..a7a4822 100644
--- a/content/web_test/common/web_test_string_util.h
+++ b/content/web_test/common/web_test_string_util.h
@@ -16,7 +16,7 @@
 
 namespace web_test_string_util {
 
-extern const char* kIllegalString;
+inline constexpr char kIllegalString[] = "illegal value";
 
 // Converts a web test url into a string that is invariant with the testing
 // environment (e.g. the absolute file path of the chrome repository), called
diff --git a/content/web_test/common/web_test_switches.cc b/content/web_test/common/web_test_switches.cc
deleted file mode 100644
index a4a917a9..0000000
--- a/content/web_test/common/web_test_switches.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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.
-
-#include "content/web_test/common/web_test_switches.h"
-
-namespace switches {
-
-// Allow access to external pages during web tests.
-const char kAllowExternalPages[] = "allow-external-pages";
-
-// When specified to "enable-leak-detection" command-line option,
-// causes the leak detector to cause immediate crash when found leak.
-const char kCrashOnFailure[] = "crash-on-failure";
-
-// Run devtools tests in debug mode (not bundled and minified)
-const char kDebugDevTools[] = "debug-devtools";
-
-// Enable accelerated 2D canvas.
-const char kEnableAccelerated2DCanvas[] = "enable-accelerated-2d-canvas";
-
-// Enable font antialiasing for pixel tests.
-const char kEnableFontAntialiasing[] = "enable-font-antialiasing";
-
-// Always use the complex text path for web tests.
-const char kAlwaysUseComplexText[] = "always-use-complex-text";
-
-// Enables the leak detection of loading webpages. This allows us to check
-// whether or not reloading a webpage releases web-related objects correctly.
-const char kEnableLeakDetection[] = "enable-leak-detection";
-
-// Specifies the path to a file containing a Chrome DevTools protocol log.
-// Each line in the log file is expected to be a protocol message in the JSON
-// format. The test runner will use this log file to script the backend for any
-// inspector-protocol tests that run. Usually you would want to run a single
-// test using the log to reproduce timeouts or crashes.
-const char kInspectorProtocolLog[] = "inspector-protocol-log";
-
-// Encode binary web test results (images, audio) using base64.
-const char kEncodeBinary[] = "encode-binary";
-
-// Disables the automatic origin isolation of web platform test domains.
-// We normally origin-isolate them for better test coverage, but tests of opt-in
-// origin isolation need to disable this.
-const char kDisableAutoWPTOriginIsolation[] =
-    "disable-auto-wpt-origin-isolation";
-
-// Forces each web test to be run in a new BrowsingInstance. Required for origin
-// isolation web tests where the BrowsingInstance retains state from origin
-// isolation requests, but this flag may benefit other web tests.
-const char kResetBrowsingInstanceBetweenTests[] =
-    "reset-browsing-instance-between-tests";
-
-// This makes us disable some web-platform runtime features so that we test
-// content_shell as if it was a stable release. It is only followed when
-// kRunWebTest is set. For the features' level, see
-// third_party/blink/renderer/platform/RuntimeEnabledFeatures.md
-const char kStableReleaseMode[] = "stable-release-mode";
-
-// Disables the shell from beginning in headless mode. Tests will then attempt
-// to use the hardware GPU for rendering. This is only followed when
-// kRunWebTests is set.
-const char kDisableHeadlessMode[] = "disable-headless-mode";
-
-}  // namespace switches
diff --git a/content/web_test/common/web_test_switches.h b/content/web_test/common/web_test_switches.h
index 03b3806..53e5f27 100644
--- a/content/web_test/common/web_test_switches.h
+++ b/content/web_test/common/web_test_switches.h
@@ -7,19 +7,62 @@
 
 namespace switches {
 
-extern const char kAllowExternalPages[];
-extern const char kCrashOnFailure[];
-extern const char kDebugDevTools[];
-extern const char kEnableAccelerated2DCanvas[];
-extern const char kEnableFontAntialiasing[];
-extern const char kAlwaysUseComplexText[];
-extern const char kEnableLeakDetection[];
-extern const char kInspectorProtocolLog[];
-extern const char kEncodeBinary[];
-extern const char kStableReleaseMode[];
-extern const char kDisableHeadlessMode[];
-extern const char kDisableAutoWPTOriginIsolation[];
-extern const char kResetBrowsingInstanceBetweenTests[];
+// Allow access to external pages during web tests.
+inline constexpr char kAllowExternalPages[] = "allow-external-pages";
+
+// When specified to "enable-leak-detection" command-line option,
+// causes the leak detector to cause immediate crash when found leak.
+inline constexpr char kCrashOnFailure[] = "crash-on-failure";
+
+// Run devtools tests in debug mode (not bundled and minified)
+inline constexpr char kDebugDevTools[] = "debug-devtools";
+
+// Enable accelerated 2D canvas.
+inline constexpr char kEnableAccelerated2DCanvas[] =
+    "enable-accelerated-2d-canvas";
+
+// Enable font antialiasing for pixel tests.
+inline constexpr char kEnableFontAntialiasing[] = "enable-font-antialiasing";
+
+// Always use the complex text path for web tests.
+inline constexpr char kAlwaysUseComplexText[] = "always-use-complex-text";
+
+// Enables the leak detection of loading webpages. This allows us to check
+// whether or not reloading a webpage releases web-related objects correctly.
+inline constexpr char kEnableLeakDetection[] = "enable-leak-detection";
+
+// Specifies the path to a file containing a Chrome DevTools protocol log.
+// Each line in the log file is expected to be a protocol message in the JSON
+// format. The test runner will use this log file to script the backend for any
+// inspector-protocol tests that run. Usually you would want to run a single
+// test using the log to reproduce timeouts or crashes.
+inline constexpr char kInspectorProtocolLog[] = "inspector-protocol-log";
+
+// Encode binary web test results (images, audio) using base64.
+inline constexpr char kEncodeBinary[] = "encode-binary";
+
+// Disables the automatic origin isolation of web platform test domains.
+// We normally origin-isolate them for better test coverage, but tests of opt-in
+// origin isolation need to disable this.
+inline constexpr char kDisableAutoWPTOriginIsolation[] =
+    "disable-auto-wpt-origin-isolation";
+
+// Forces each web test to be run in a new BrowsingInstance. Required for origin
+// isolation web tests where the BrowsingInstance retains state from origin
+// isolation requests, but this flag may benefit other web tests.
+inline constexpr char kResetBrowsingInstanceBetweenTests[] =
+    "reset-browsing-instance-between-tests";
+
+// This makes us disable some web-platform runtime features so that we test
+// content_shell as if it was a stable release. It is only followed when
+// kRunWebTest is set. For the features' level, see
+// third_party/blink/renderer/platform/RuntimeEnabledFeatures.md
+inline constexpr char kStableReleaseMode[] = "stable-release-mode";
+
+// Disables the shell from beginning in headless mode. Tests will then attempt
+// to use the hardware GPU for rendering. This is only followed when
+// kRunWebTests is set.
+inline constexpr char kDisableHeadlessMode[] = "disable-headless-mode";
 
 }  // namespace switches
 
diff --git a/docs/website b/docs/website
index c5d4064..a89f681 160000
--- a/docs/website
+++ b/docs/website
@@ -1 +1 @@
-Subproject commit c5d4064bbf9dc71893bfa60db578e8f92995bd57
+Subproject commit a89f6810f6a5b0e11e4ec00387e9f97e8f6c23ae
diff --git a/gpu/command_buffer/client/client_shared_image.h b/gpu/command_buffer/client/client_shared_image.h
index 9ee962f..23e6aba 100644
--- a/gpu/command_buffer/client/client_shared_image.h
+++ b/gpu/command_buffer/client/client_shared_image.h
@@ -19,7 +19,7 @@
 #include "gpu/command_buffer/common/shared_image_trace_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/common/sync_token.h"
-#include "gpu/ipc/common/exported_shared_image.mojom-shared.h"
+#include "gpu/ipc/common/exported_shared_image.mojom-forward.h"
 #include "gpu/ipc/common/gpu_memory_buffer_handle_info.h"
 #include "gpu/ipc/common/gpu_memory_buffer_impl.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
index 29f2561..36212a3 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -239,7 +239,6 @@
   gfx::ScopedIOSurface io_surface;
   {
     gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-    const gfx::BufferFormat buffer_format = ToBufferFormat(format);
     const bool should_clear = true;
     const bool override_rgba_to_bgra =
 #if BUILDFLAG(IS_IOS)
@@ -247,8 +246,8 @@
 #else
         gr_context_type_ == GrContextType::kGL;
 #endif
-    io_surface = gfx::CreateIOSurface(size, buffer_format, should_clear,
-                                      override_rgba_to_bgra);
+    io_surface =
+        gfx::CreateIOSurface(size, format, should_clear, override_rgba_to_bgra);
     if (!io_surface) {
       LOG(ERROR) << "CreateSharedImage: Failed to create bindable image";
       return nullptr;
@@ -350,7 +349,6 @@
   gfx::ScopedIOSurface io_surface;
   {
     gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_);
-    const gfx::BufferFormat buffer_format = ToBufferFormat(format);
     const bool should_clear = false;
     const bool override_rgba_to_bgra =
 #if BUILDFLAG(IS_IOS)
@@ -358,8 +356,8 @@
 #else
         gr_context_type_ == GrContextType::kGL;
 #endif
-    io_surface = gfx::CreateIOSurface(size, buffer_format, should_clear,
-                                      override_rgba_to_bgra);
+    io_surface =
+        gfx::CreateIOSurface(size, format, should_clear, override_rgba_to_bgra);
     if (!io_surface) {
       LOG(ERROR) << "CreateSharedImage: Failed to create bindable image";
       return nullptr;
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
index 9f9d2810..d24bc18b 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
@@ -1337,9 +1337,8 @@
     SkAlphaType alpha_type = kPremul_SkAlphaType;
     bool override_rgba_to_bgra = get_gr_context_type() == GrContextType::kGL;
 
-    gfx::BufferFormat buffer_format = gpu::ToBufferFormat(format);
     gfx::GpuMemoryBufferHandle handle(gfx::CreateIOSurface(
-        size, buffer_format, /*should_clear=*/true, override_rgba_to_bgra));
+        size, format, /*should_clear=*/true, override_rgba_to_bgra));
     DCHECK(handle.io_surface());
 
     auto backing = backing_factory_->CreateSharedImage(
diff --git a/gpu/ipc/common/DEPS b/gpu/ipc/common/DEPS
index 63a6283c..c364b91a 100644
--- a/gpu/ipc/common/DEPS
+++ b/gpu/ipc/common/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+base",
   "+components/viz/common/resources/shared_image_format.h",
+  "+components/viz/common/resources/shared_image_format_utils.h",
   "+ipc",
   "+mojo",
   "+ui/base",
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
index cfc7594..f91b154 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/notimplemented.h"
+#include "components/viz/common/resources/shared_image_format_utils.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/mac/io_surface.h"
 
@@ -71,7 +72,8 @@
     gfx::BufferFormat format,
     gfx::BufferUsage usage,
     gfx::GpuMemoryBufferHandle* handle) {
-  *handle = gfx::GpuMemoryBufferHandle(gfx::CreateIOSurface(size, format));
+  viz::SharedImageFormat si_format = viz::GetSharedImageFormat(format);
+  *handle = gfx::GpuMemoryBufferHandle(gfx::CreateIOSurface(size, si_format));
   return base::DoNothing();
 }
 
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
index 11278ba..31543b5b 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
@@ -146,6 +146,9 @@
     case gfx::BufferFormat::BGRX_8888:
       dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;
       break;
+    case gfx::BufferFormat::RGBA_F16:
+      dxgi_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
+      break;
     case gfx::BufferFormat::YUV_420_BIPLANAR:
       dxgi_format = DXGI_FORMAT_NV12;
       break;
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
index d62899fc..dd75356 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
@@ -12,6 +12,7 @@
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/unguessable_token.h"
+#include "components/viz/common/resources/shared_image_format_utils.h"
 #include "gpu/ipc/common/gpu_client_ids.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/mac/io_surface.h"
@@ -26,8 +27,9 @@
                                                        gfx::BufferFormat format,
                                                        gfx::BufferUsage usage) {
   bool should_clear = true;
+  viz::SharedImageFormat si_format = viz::GetSharedImageFormat(format);
   base::apple::ScopedCFTypeRef<IOSurfaceRef> io_surface =
-      gfx::CreateIOSurface(size, format, should_clear);
+      gfx::CreateIOSurface(size, si_format, should_clear);
   if (!io_surface) {
     LOG(ERROR) << "Failed to allocate IOSurface.";
     return {};
diff --git a/infra/config/generated/OWNERS b/infra/config/generated/OWNERS
index 68684dd..a1083a5 100644
--- a/infra/config/generated/OWNERS
+++ b/infra/config/generated/OWNERS
@@ -38,19 +38,10 @@
 
 # LINT.IfChange(chromium_tests)
 
-# For Weblayer skew tests related reviews
-per-file builders/*/*/targets/chromium.android.*=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-
 # For Android related reviews
 per-file builders/*/*/targets/chromium.android.*=zhiyuans@google.com
 per-file builders/*/*/targets/chromium.android.*=wnwen@chromium.org
 
-# TODO(crbug.com/40191809) Remove the following 3 lines when the conversion is done.
-per-file builders/*/*/targets/chromium.fyi.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file builders/*/*/targets/chromium.chromiumos.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file builders/*/*/targets/chromium.memory.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file builders/*/*/targets/chromium.coverage.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-
 # For Lacros skylab tests cros image roller related reviews
 per-file builders/*/*/targets/chromium.chromiumos.json=skylab-test-cros-roller@chops-service-accounts.iam.gserviceaccount.com
 per-file builders/*/*/targets/chromium.fyi.json=skylab-test-cros-roller@chops-service-accounts.iam.gserviceaccount.com
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index d6c3e493..c207e27 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -816,6 +816,7 @@
   * [`//media/mojo/.+`](https://cs.chromium.org/chromium/src/media/mojo/)
   * [`//media/renderers/.+`](https://cs.chromium.org/chromium/src/media/renderers/)
   * [`//media/video/.+`](https://cs.chromium.org/chromium/src/media/video/)
+  * [`//services/on_device_model/.+`](https://cs.chromium.org/chromium/src/services/on_device_model/)
   * [`//services/webnn/.+`](https://cs.chromium.org/chromium/src/services/webnn/)
   * [`//testing/buildbot/tryserver.chromium.win.json`](https://cs.chromium.org/search?q=+file:testing/buildbot/tryserver.chromium.win.json)
   * [`//testing/trigger_scripts/.+`](https://cs.chromium.org/chromium/src/testing/trigger_scripts/)
diff --git a/infra/config/generated/cq-usage/full.cfg b/infra/config/generated/cq-usage/full.cfg
index 42f7ecb..b459652 100644
--- a/infra/config/generated/cq-usage/full.cfg
+++ b/infra/config/generated/cq-usage/full.cfg
@@ -4765,6 +4765,12 @@
           gerrit_host_regexp: ".*"
           gerrit_project_regexp: ".*"
           gerrit_ref_regexp: ".*"
+          path_regexp: "services/on_device_model/.+"
+        }
+        location_filters {
+          gerrit_host_regexp: ".*"
+          gerrit_project_regexp: ".*"
+          gerrit_ref_regexp: ".*"
           path_regexp: "services/webnn/.+"
         }
         location_filters {
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 07314412c..53a3f6c 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -7822,6 +7822,12 @@
           gerrit_host_regexp: ".*"
           gerrit_project_regexp: ".*"
           gerrit_ref_regexp: ".*"
+          path_regexp: "services/on_device_model/.+"
+        }
+        location_filters {
+          gerrit_host_regexp: ".*"
+          gerrit_project_regexp: ".*"
+          gerrit_ref_regexp: ".*"
           path_regexp: "services/webnn/.+"
         }
         location_filters {
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index bc75c4e2..04723d53 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -55393,7 +55393,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "free_space:standard"
-      dimensions: "os:Ubuntu-20.04"
+      dimensions: "os:Ubuntu-22.04"
       dimensions: "pool:luci.chromium.ci"
       dimensions: "ssd:0"
       exe {
@@ -74334,6 +74334,13 @@
         '    {'
         '      "builder_id": {'
         '        "bucket": "ci",'
+        '        "builder": "android-14-x64-rel",'
+        '        "project": "chromium"'
+        '      }'
+        '    },'
+        '    {'
+        '      "builder_id": {'
+        '        "bucket": "ci",'
         '        "builder": "android-15-x64-rel",'
         '        "project": "chromium"'
         '      }'
@@ -74341,6 +74348,20 @@
         '    {'
         '      "builder_id": {'
         '        "bucket": "ci",'
+        '        "builder": "android-15-tablet-x64-rel",'
+        '        "project": "chromium"'
+        '      }'
+        '    },'
+        '    {'
+        '      "builder_id": {'
+        '        "bucket": "ci",'
+        '        "builder": "android-15-tablet-landscape-x64-rel",'
+        '        "project": "chromium"'
+        '      }'
+        '    },'
+        '    {'
+        '      "builder_id": {'
+        '        "bucket": "ci",'
         '        "builder": "android-16-x64-rel",'
         '        "project": "chromium"'
         '      }'
@@ -107633,7 +107654,7 @@
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "free_space:standard"
-      dimensions: "os:Ubuntu-20.04"
+      dimensions: "os:Ubuntu-22.04"
       dimensions: "pool:luci.chromium.try"
       dimensions: "ssd:0"
       exe {
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star
index 94a0e07..40c9358a 100644
--- a/infra/config/subprojects/chromium/ci/chromium.linux.star
+++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -1133,8 +1133,6 @@
             "empty_main",
         ],
     ),
-    # Focal is needed for better C++20 support. See crbug.com/1284275.
-    os = os.LINUX_FOCAL,
     console_view_entry = consoles.console_view_entry(
         category = "release",
         short_name = "gcc",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index 2611ef52..c83d29e2 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -305,8 +305,6 @@
         "ci/linux-gcc-rel",
     ],
     gn_args = "ci/linux-gcc-rel",
-    # Focal is needed for better C++20 support. See crbug.com/1284275.
-    os = os.LINUX_FOCAL,
 )
 
 try_.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
index ed7e6162..6460a1e 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
@@ -559,6 +559,7 @@
             cq.location_filter(path_regexp = "media/mojo/.+"),
             cq.location_filter(path_regexp = "media/renderers/.+"),
             cq.location_filter(path_regexp = "media/video/.+"),
+            cq.location_filter(path_regexp = "services/on_device_model/.+"),
             cq.location_filter(path_regexp = "services/webnn/.+"),
             cq.location_filter(path_regexp = "testing/buildbot/tryserver.chromium.win.json"),
             cq.location_filter(path_regexp = "testing/trigger_scripts/.+"),
diff --git a/infra/config/subprojects/reviver/reviver.star b/infra/config/subprojects/reviver/reviver.star
index e41644d..f69a679 100644
--- a/infra/config/subprojects/reviver/reviver.star
+++ b/infra/config/subprojects/reviver/reviver.star
@@ -56,7 +56,10 @@
         "ci/android-10-x86-rel",
         "ci/android-12-x64-rel",
         "ci/android-13-x64-rel",
+        "ci/android-14-x64-rel",
         "ci/android-15-x64-rel",
+        "ci/android-15-tablet-x64-rel",
+        "ci/android-15-tablet-landscape-x64-rel",
         "ci/android-16-x64-rel",
         "ci/android-16-x64-dbg-tests",
     ],
diff --git a/internal b/internal
index 2a2c52e..70b21a9 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 2a2c52e2447fbdd311a095769463448ba2dc317d
+Subproject commit 70b21a9e7529654dc682f591a19a27a5b999771a
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 152a87ae..f05f83bb 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -5114,13 +5114,13 @@
         Open Reading mode options
       </message>
       <message name="IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_DARK" desc="Label of a Reading mode options button which changes the Reading mode dark color scheme.">
-        Dark
+        Black background color
       </message>
       <message name="IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_LIGHT" desc="Label of a Reading mode options button which changes the Reading mode light color scheme.">
-        Light
+        White background color
       </message>
       <message name="IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_SEPIA" desc="Label of a Reading mode options button which changes the Reading mode sepia color scheme.">
-        Sepia
+        Sepia background color
       </message>
       <message name="IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_LABEL" desc="Label of a Reading mode options button which changes the Reading mode color scheme." meaning="Label of a Reading mode options button which changes the Reading mode color scheme. This should be one, at most two characters to preview the color scheme e.g. Aa in English.">
         Aa
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_DARK.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_DARK.png.sha1
index baa7dabb..8dbdaf6 100644
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_DARK.png.sha1
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_DARK.png.sha1
@@ -1 +1 @@
-8546ac7fb78102f3b0cee50a4d73a5a9f1d87116
\ No newline at end of file
+b5fe903501e1f054378a9fc44d32ed4f0540d782
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_LIGHT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_LIGHT.png.sha1
index baa7dabb..8dbdaf6 100644
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_LIGHT.png.sha1
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_LIGHT.png.sha1
@@ -1 +1 @@
-8546ac7fb78102f3b0cee50a4d73a5a9f1d87116
\ No newline at end of file
+b5fe903501e1f054378a9fc44d32ed4f0540d782
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_SEPIA.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_SEPIA.png.sha1
index baa7dabb..8dbdaf6 100644
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_SEPIA.png.sha1
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READER_MODE_OPTIONS_COLOR_THEME_BUTTON_ACCESSIBILITY_LABEL_SEPIA.png.sha1
@@ -1 +1 @@
-8546ac7fb78102f3b0cee50a4d73a5a9f1d87116
\ No newline at end of file
+b5fe903501e1f054378a9fc44d32ed4f0540d782
\ No newline at end of file
diff --git a/ios/chrome/browser/alert_view/ui_bundled/alert_view_controller.mm b/ios/chrome/browser/alert_view/ui_bundled/alert_view_controller.mm
index 724d189..455eb048 100644
--- a/ios/chrome/browser/alert_view/ui_bundled/alert_view_controller.mm
+++ b/ios/chrome/browser/alert_view/ui_bundled/alert_view_controller.mm
@@ -12,7 +12,6 @@
 #import "base/notreached.h"
 #import "ios/chrome/browser/alert_view/ui_bundled/alert_action.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/browser/shared/ui/elements/gray_highlight_button.h"
 #import "ios/chrome/browser/shared/ui/elements/text_field_configuration.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_coordinator.mm
index 35e732e41..c14a401 100644
--- a/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_coordinator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_coordinator.mm
@@ -101,6 +101,10 @@
 
 - (void)stop {
   [super stop];
+  self.identityChooserViewController.presentationDelegate = nil;
+  [self.identityChooserViewController dismissViewControllerAnimated:NO
+                                                         completion:nil];
+  self.identityChooserViewController = nil;
   base::RecordAction(base::UserMetricsAction("Signin_AccountPicker_Close"));
   [self.identityChooserMediator disconnect];
   self.identityChooserMediator = nil;
@@ -140,6 +144,8 @@
                               didSelectIdentity:self.selectedIdentity];
       break;
   }
+  self.identityChooserViewController.presentationDelegate = nil;
+  self.identityChooserViewController = nil;
   [self.delegate identityChooserCoordinatorDidClose:self];
 }
 
@@ -150,6 +156,10 @@
   self.state = IdentityChooserCoordinatorStateClosedByAddingAccount;
   [self.identityChooserViewController dismissViewControllerAnimated:YES
                                                          completion:nil];
+  // Note that, even if the user tapped on "add account", we do not display the
+  // add account view here. Instead, it’ll be displayed asynchronously once the
+  // identity chooser disappeared. The implementation is in
+  // `-identityChooserViewControllerDidDisappear:`.
 }
 
 - (void)identityChooserViewController:
@@ -165,6 +175,12 @@
   }
   [self.identityChooserViewController dismissViewControllerAnimated:YES
                                                          completion:nil];
+  // Note that, even if the user tapped on an identity, the delegate is not
+  // notified of the choice here. Instead, the notification is sent
+  // asynchronously, so that when the delegate is notified, the identity chooser
+  // view has already disappeared and the delegate is free to open whatever view
+  // immediately. The implementation is in
+  // `-identityChooserViewControllerDidDisappear:`.
 }
 
 @end
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
index 81b7027..9e2f347 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
@@ -195,6 +195,7 @@
     "//ios/chrome/browser/policy/model:eg_test_support+eg2",
     "//ios/chrome/browser/policy/model:policy_util",
     "//ios/chrome/browser/reading_list/ui_bundled:eg_test_support+eg2",
+    "//ios/chrome/browser/reading_list/ui_bundled:reading_list_constants",
     "//ios/chrome/browser/recent_tabs/ui_bundled:ui_constants",
     "//ios/chrome/browser/settings/ui_bundled:constants",
     "//ios/chrome/browser/settings/ui_bundled:eg_test_support+eg2",
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_coordinator.mm
index fea911a..de8e815 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_coordinator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_coordinator.mm
@@ -251,6 +251,13 @@
                    completionIdentity:_identity];
 }
 
+- (void)instantSigninMediatorSigninIsImpossible:
+    (InstantSigninMediator*)mediator {
+  CHECK_EQ(mediator, _mediator, base::NotFatalUntil::M144);
+  [self runCompletionWithSigninResult:SigninCoordinatorResultInterrupted
+                   completionIdentity:nil];
+}
+
 #pragma mark - Private
 
 // Starts the sign-in flow.
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.h b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.h
index fd7204a9..7cbc7fd 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.h
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.h
@@ -28,6 +28,10 @@
 // Called when the sign-in will be done in another profile.
 - (void)instantSigninMediatorWillSwitchProfile:(InstantSigninMediator*)mediator;
 
+// Called when sign-in is not available anymore.
+- (void)instantSigninMediatorSigninIsImpossible:
+    (InstantSigninMediator*)mediator;
+
 @end
 
 @interface InstantSigninMediator : NSObject
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.mm
index ba6f8fa..c1fa0b7 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/instant_signin/instant_signin_mediator.mm
@@ -63,8 +63,10 @@
 }
 
 - (void)disconnect {
+  _authenticationService = nullptr;
   _authServiceObserverBridge.reset();
   [_authenticationFlow interrupt];
+  _authenticationFlow = nil;
 }
 
 #pragma mark - AuthenticationFlowDelegate
@@ -88,10 +90,7 @@
   if (!_authenticationService->SigninEnabled()) {
     // Signin is now disabled, so the consistency default account must be
     // stopped.
-    [self.delegate
-        instantSigninMediator:self
-          didSigninWithResult:SigninCoordinatorResult::
-                                  SigninCoordinatorResultInterrupted];
+    [self.delegate instantSigninMediatorSigninIsImpossible:self];
   }
 }
 
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator_egtest.mm b/ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator_egtest.mm
index 79c3d09..e092c886 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator_egtest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator_egtest.mm
@@ -28,6 +28,7 @@
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
 #import "ios/chrome/browser/policy/model/policy_earl_grey_utils.h"
 #import "ios/chrome/browser/policy/model/policy_util.h"
+#import "ios/chrome/browser/reading_list/ui_bundled/reading_list_constants.h"
 #import "ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.h"
 #import "ios/chrome/browser/recent_tabs/ui_bundled/recent_tabs_constants.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_constants.h"
@@ -1068,4 +1069,46 @@
   [SigninEarlGrey verifySignedOut];
 }
 
+// Interrupt the instant sign-in from the reading list. The sign-in flow is
+// interrupted while the sign-in flow displays the managed identity dialog.
+- (void)testInterruptIdentityChooserInReadingList {
+  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
+  [SigninEarlGrey addFakeIdentity:fakeIdentity];
+  reading_list_test_utils::OpenReadingList();
+  [[EarlGrey
+      selectElementWithMatcher:grey_allOf(SecondarySignInButton(),
+                                          grey_sufficientlyVisible(), nil)]
+      performAction:grey_tap()];
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+  const GURL expectedURL = self.testServer->GetURL("/echo");
+  [ChromeEarlGrey
+      simulateExternalAppURLOpeningAndWaitUntilOpenedWithGURL:expectedURL];
+}
+
+// Tests that promo and account list disappear if the user get signed-in.
+- (void)testSignInDisabledDuringIdentiyList {
+  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
+  [SigninEarlGrey addFakeIdentity:fakeIdentity];
+  reading_list_test_utils::OpenReadingList();
+  [[EarlGrey
+      selectElementWithMatcher:grey_allOf(SecondarySignInButton(),
+                                          grey_sufficientlyVisible(), nil)]
+      performAction:grey_tap()];
+  // Checks that the identity list is displayed.
+  [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail(
+                                          fakeIdentity.userEmail)]
+      assertWithMatcher:grey_notNil()];
+  // Simulate disabling sign-in in another scene with anothe profile.
+  [ChromeEarlGrey setBoolValue:NO
+             forLocalStatePref:prefs::kSigninAllowedOnDevice];
+  // Checks that the identity list and the promo are gone.
+  [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail(
+                                          fakeIdentity.userEmail)]
+      assertWithMatcher:grey_nil()];
+  [SigninEarlGreyUI verifySigninPromoNotVisible];
+  // But the reading list is still open.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
+      assertWithMatcher:grey_notNil()];
+}
+
 @end
diff --git a/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_ios.mm b/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_ios.mm
index c01bdbc4..8909f35 100644
--- a/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_ios.mm
+++ b/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_ios.mm
@@ -74,6 +74,7 @@
   user_provided_details.cardholder_name = cardholder_name;
   user_provided_details.expiration_date_month = expiration_date_month;
   user_provided_details.expiration_date_year = expiration_date_year;
+  user_provided_details.cvc = u"";
   delegate()->OnUiUpdatedAndAccepted(user_provided_details);
   return true;
 }
diff --git a/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_unittest.mm b/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_unittest.mm
index 90f9f65..cef3926 100644
--- a/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_unittest.mm
+++ b/ios/chrome/browser/autofill/model/credit_card/autofill_save_card_infobar_delegate_unittest.mm
@@ -145,7 +145,8 @@
       *last_user_provided_card_details_,
       ::testing::FieldsAre(/*cardholder_name=*/cardholder_name,
                            /*expiration_date_month=*/expiration_date_month,
-                           /*expiration_date_year=*/expiration_date_year));
+                           /*expiration_date_year=*/expiration_date_year,
+                           /*cvc=*/u""));
 }
 
 // Tests that CreditCardUploadCompleted() runs
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_account_storage_promo_egtest.mm b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_account_storage_promo_egtest.mm
index f85e4c5..c8d7b77 100644
--- a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_account_storage_promo_egtest.mm
+++ b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_account_storage_promo_egtest.mm
@@ -33,7 +33,6 @@
 using chrome_test_util::BookmarksNavigationBarBackButton;
 using chrome_test_util::IdentityCellMatcherForEmail;
 using chrome_test_util::PrimarySignInButton;
-using chrome_test_util::SecondarySignInButton;
 
 // Bookmark promo integration tests.
 @interface BookmarksAccountStoragePromoTestCase : WebHttpServerChromeTestCase
diff --git a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
index 857a0ff..6ae2fda 100644
--- a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
+++ b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
@@ -3081,6 +3081,12 @@
   self.defaultBrowserGenericPromoCoordinator.promosUIHandler =
       self.promosManagerCoordinator;
   self.defaultBrowserGenericPromoCoordinator.handler = self;
+
+  if (IsDefaultBrowserOffCyclePromoEnabled()) {
+    self.defaultBrowserGenericPromoCoordinator.promoWasFromOffCycleTrigger =
+        YES;
+  }
+
   [self.defaultBrowserGenericPromoCoordinator start];
 }
 
diff --git a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.h b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.h
index 453668a..ad7380b 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.h
+++ b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.h
@@ -25,6 +25,7 @@
 // If `titleText` is nil, default title will be used.
 - (instancetype)initWithDismissButton:(BOOL)hasDismissButton
                      hasRemindMeLater:(BOOL)hasRemindMeLater
+            useDefaultAppsDestination:(BOOL)useDefaultAppsDestination
                              hasSteps:(BOOL)hasSteps
                         actionHandler:
                             (id<ConfirmationAlertActionHandler>)actionHandler
diff --git a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.mm b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.mm
index 714d3a7..d3588dab 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.mm
+++ b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.mm
@@ -25,6 +25,14 @@
     @"default_browser_animation_darkmode";
 NSString* const kDefaultBrowserAnimationRtlDarkmode =
     @"default_browser_animation_rtl_darkmode";
+NSString* const kDefaultBrowserDefaultAppsAnimation =
+    @"default_browser_default_apps_animation";
+NSString* const kDefaultBrowserDefaultAppsAnimationRtl =
+    @"default_browser_default_apps_animation_rtl";
+NSString* const kDefaultBrowserDefaultAppsAnimationDarkmode =
+    @"default_browser_default_apps_animation_darkmode";
+NSString* const kDefaultBrowserDefaultAppsAnimationRtlDarkmode =
+    @"default_browser_default_apps_animation_rtl_darkmode";
 
 // Keys in the lottie assets.
 NSString* const kDefaultBrowserAppKeypath = @"IDS_DEFAULT_BROWSER_APP";
@@ -60,12 +68,13 @@
 
 - (instancetype)initWithDismissButton:(BOOL)hasDismissButton
                      hasRemindMeLater:(BOOL)hasRemindMeLater
+            useDefaultAppsDestination:(BOOL)useDefaultAppsDestination
                              hasSteps:(BOOL)hasSteps
                         actionHandler:
                             (id<ConfirmationAlertActionHandler>)actionHandler
                             titleText:(NSString*)titleText {
   if ((self = [super init])) {
-    [self addVideoSection];
+    [self addVideoSection:useDefaultAppsDestination];
     [self addInformationSectionWithDismissButton:hasDismissButton
                                 hasRemindMeLater:hasRemindMeLater
                                         hasSteps:hasSteps
@@ -99,18 +108,27 @@
 #pragma mark - Private
 
 // Adds the top part of the view which contains the video animation.
-- (void)addVideoSection {
+- (void)addVideoSection:(BOOL)useDefaultAppsDestination {
   NSString* animationAssetName;
   NSString* animationAssetNameDarkMode;
 
-  // TODO(crbug.com/40948842): Handle the case when the promo is displayed and
-  // the user switches between LTR and RLT.
-  if (base::i18n::IsRTL()) {
-    animationAssetName = kDefaultBrowserAnimationRtl;
-    animationAssetNameDarkMode = kDefaultBrowserAnimationRtlDarkmode;
+  if (useDefaultAppsDestination) {
+    if (base::i18n::IsRTL()) {
+      animationAssetName = kDefaultBrowserDefaultAppsAnimationRtl;
+      animationAssetNameDarkMode =
+          kDefaultBrowserDefaultAppsAnimationRtlDarkmode;
+    } else {
+      animationAssetName = kDefaultBrowserDefaultAppsAnimation;
+      animationAssetNameDarkMode = kDefaultBrowserDefaultAppsAnimationDarkmode;
+    }
   } else {
-    animationAssetName = kDefaultBrowserAnimation;
-    animationAssetNameDarkMode = kDefaultBrowserAnimationDarkmode;
+    if (base::i18n::IsRTL()) {
+      animationAssetName = kDefaultBrowserAnimationRtl;
+      animationAssetNameDarkMode = kDefaultBrowserAnimationRtlDarkmode;
+    } else {
+      animationAssetName = kDefaultBrowserAnimation;
+      animationAssetNameDarkMode = kDefaultBrowserAnimationDarkmode;
+    }
   }
 
   self.animationViewWrapper = [self createAnimation:animationAssetName];
diff --git a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller_unittest.mm b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller_unittest.mm
index 4ece772e..55ae627b 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller_unittest.mm
+++ b/ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller_unittest.mm
@@ -74,11 +74,12 @@
        CreateViewWithSubtitleTest) {
   DefaultBrowserInstructionsViewController* instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:NO
-               hasRemindMeLater:NO
-                       hasSteps:NO
-                  actionHandler:nil
-                      titleText:nil];
+              initWithDismissButton:NO
+                   hasRemindMeLater:NO
+          useDefaultAppsDestination:NO
+                           hasSteps:NO
+                      actionHandler:nil
+                          titleText:nil];
   UIView* view = instructionsViewController.view;
   ASSERT_NE(instructionsViewController, nil);
   EXPECT_TRUE(HasTitle(view));
@@ -93,11 +94,12 @@
 TEST_F(DefaultBrowserInstructionsViewControllerTest, CreateViewWithStepsTest) {
   DefaultBrowserInstructionsViewController* instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:NO
-               hasRemindMeLater:NO
-                       hasSteps:YES
-                  actionHandler:nil
-                      titleText:nil];
+              initWithDismissButton:NO
+                   hasRemindMeLater:NO
+          useDefaultAppsDestination:NO
+                           hasSteps:YES
+                      actionHandler:nil
+                          titleText:nil];
   UIView* view = instructionsViewController.view;
   ASSERT_NE(instructionsViewController, nil);
   EXPECT_TRUE(HasTitle(view));
@@ -113,11 +115,12 @@
        CreateViewWithSecondaryButtonTest) {
   DefaultBrowserInstructionsViewController* instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:YES
-               hasRemindMeLater:NO
-                       hasSteps:NO
-                  actionHandler:nil
-                      titleText:nil];
+              initWithDismissButton:YES
+                   hasRemindMeLater:NO
+          useDefaultAppsDestination:NO
+                           hasSteps:NO
+                      actionHandler:nil
+                          titleText:nil];
   UIView* view = instructionsViewController.view;
   ASSERT_NE(instructionsViewController, nil);
   EXPECT_TRUE(HasTitle(view));
@@ -133,11 +136,12 @@
        CreateViewWithTertiaryButtonTest) {
   DefaultBrowserInstructionsViewController* instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:NO
-               hasRemindMeLater:YES
-                       hasSteps:NO
-                  actionHandler:nil
-                      titleText:nil];
+              initWithDismissButton:NO
+                   hasRemindMeLater:YES
+          useDefaultAppsDestination:NO
+                           hasSteps:NO
+                      actionHandler:nil
+                          titleText:nil];
   UIView* view = instructionsViewController.view;
   ASSERT_NE(instructionsViewController, nil);
   EXPECT_TRUE(HasTitle(view));
@@ -152,11 +156,12 @@
 TEST_F(DefaultBrowserInstructionsViewControllerTest, AnimationViewTest) {
   DefaultBrowserInstructionsViewController* instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:YES
-               hasRemindMeLater:NO
-                       hasSteps:NO
-                  actionHandler:nil
-                      titleText:nil];
+              initWithDismissButton:YES
+                   hasRemindMeLater:NO
+          useDefaultAppsDestination:NO
+                           hasSteps:NO
+                      actionHandler:nil
+                          titleText:nil];
   UIView* view = instructionsViewController.view;
   ASSERT_NE(instructionsViewController, nil);
 
diff --git a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.h b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.h
index 16bc7013..888eedfd 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.h
+++ b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.h
@@ -25,6 +25,10 @@
 // Whether or not the current showing came from a past Remind Me Later.
 @property(nonatomic, assign) BOOL promoWasFromRemindMeLater;
 
+// Whether or not this showing is from the off-cycle promo. If so, the promo
+// will use the Default Apps iOS Settings page, if available (iOS 18.3+).
+@property(nonatomic, assign) BOOL promoWasFromOffCycleTrigger;
+
 // The promos manager ui handler to alert for promo UI changes. Should only be
 // set if this coordinator was a promo presented by the PromosManager.
 @property(nonatomic, weak) id<PromosManagerUIHandler> promosUIHandler;
diff --git a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.mm b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.mm
index 6e72c90..c6178fe 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.mm
+++ b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.mm
@@ -62,6 +62,11 @@
         feature_engagement::kIPHiOSPromoDefaultBrowserReminderFeature);
   }
 
+  if (_promoWasFromOffCycleTrigger && _tracker) {
+    _tracker->Dismissed(
+        feature_engagement::kIPHiOSDefaultBrowserOffCyclePromoFeature);
+  }
+
   [self.promosUIHandler promoWasDismissed];
   self.promosUIHandler = nil;
 
@@ -76,7 +81,8 @@
 #pragma mark - ConfirmationAlertActionHandler
 
 - (void)confirmationAlertPrimaryAction {
-  [_mediator didTapPrimaryActionButton];
+  [_mediator didTapPrimaryActionButton:
+                 /*useDefaultAppsDestination=*/_promoWasFromOffCycleTrigger];
   RecordDefaultBrowserPromoLastAction(
       IOSDefaultBrowserPromoAction::kActionButton);
   base::UmaHistogramEnumeration(
@@ -158,11 +164,12 @@
           feature_engagement::kIPHiOSPromoDefaultBrowserReminderFeature) &&
       !_promoWasFromRemindMeLater;
   _viewController = [[DefaultBrowserInstructionsViewController alloc]
-      initWithDismissButton:YES
-           hasRemindMeLater:hasRemindMeLater
-                   hasSteps:NO
-              actionHandler:self
-                  titleText:nil];
+          initWithDismissButton:YES
+               hasRemindMeLater:hasRemindMeLater
+      useDefaultAppsDestination:_promoWasFromOffCycleTrigger
+                       hasSteps:NO
+                  actionHandler:self
+                      titleText:nil];
 
   CHECK(_viewController);
   RecordAction(
diff --git a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.h b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.h
index 0feef97..e7d1b06 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.h
+++ b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.h
@@ -10,9 +10,15 @@
 // The mediator for the generic default browser promo.
 @interface DefaultBrowserGenericPromoMediator : NSObject
 
-// Handles user tap on primary action. Allows the user to open the iOS settings.
+// Handles user tap on primary action. Sends the user to the iOS settings.
 - (void)didTapPrimaryActionButton;
 
+// Handles user tap on primary action. Sends the user to the iOS settings. If
+// `useDefaultAppsDestination` is set to YES, the user is sent to the Default
+// Apps settings page. If set to NO, or the device is running iOS 18.2 or older,
+// then the user is sent to the current app's iOS settings page.
+- (void)didTapPrimaryActionButton:(BOOL)useDefaultAppsDestination;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_DEFAULT_PROMO_UI_BUNDLED_GENERIC_DEFAULT_BROWSER_GENERIC_PROMO_MEDIATOR_H_
diff --git a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.mm b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.mm
index 0a1d58c..92189a0 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.mm
+++ b/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_mediator.h"
 
+#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ui/base/l10n/l10n_util_mac.h"
 
 @implementation DefaultBrowserGenericPromoMediator
@@ -11,10 +12,22 @@
 #pragma mark - Public
 
 - (void)didTapPrimaryActionButton {
-  [[UIApplication sharedApplication]
-                openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]
-                options:{}
-      completionHandler:nil];
+  [self didTapPrimaryActionButton:/*useDefaultAppsDestination=*/NO];
+}
+
+- (void)didTapPrimaryActionButton:(BOOL)useDefaultAppsDestination {
+  NSURL* url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
+#if defined(__IPHONE_18_3) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_3
+  if (@available(iOS 18.3, *)) {
+    if (useDefaultAppsDestination) {
+      url = [NSURL
+          URLWithString:UIApplicationOpenDefaultApplicationsSettingsURLString];
+    }
+  }
+#endif
+  [[UIApplication sharedApplication] openURL:url
+                                     options:{}
+                           completionHandler:nil];
 }
 
 @end
diff --git a/ios/chrome/browser/default_promo/ui_bundled/resources/BUILD.gn b/ios/chrome/browser/default_promo/ui_bundled/resources/BUILD.gn
index c2028c3..a931a131 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/resources/BUILD.gn
+++ b/ios/chrome/browser/default_promo/ui_bundled/resources/BUILD.gn
@@ -26,6 +26,10 @@
     "default_browser_animation_darkmode.json",
     "default_browser_animation_rtl.json",
     "default_browser_animation_rtl_darkmode.json",
+    "default_browser_default_apps_animation.json",
+    "default_browser_default_apps_animation_darkmode.json",
+    "default_browser_default_apps_animation_rtl.json",
+    "default_browser_default_apps_animation_rtl_darkmode.json",
   ]
   outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 }
diff --git a/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation.json b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation.json
new file mode 100644
index 0000000..f86d10e
--- /dev/null
+++ b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":360,"w":375,"h":408,"nm":"animation 3","ddd":0,"assets":[{"id":"image_0","w":29,"h":29,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAYAAABWk2cPAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFpElEQVRIia2Wf4wVVxXHP+fO+7W7bx+7FFJhwVoaYK0sTWNp+UNM8UdbW4RQk8aGpFCLRkJiYlJ/pNWljWk1BKuxxmi0toJJa6xAC9RCsW0QI9Y2GBdkkbbEAgsLu77dnfdj5r2Ze/xjZt++t2+XYtKTTO7cuWfO937Pr3uFOikWizcZk9iMI/NFmS8QggiiXJGoWpEEihW1NghVz4P+vjWT2S4ilSb9Usn7ehAE5621+kFKEIZaKnuH8/l8RxNgNQg/ULDJ4vl+n+u6swFkpFi8KZtO73Uc5+rLec66LqVDr1I91U/l1ElEBNPeTmpRNy2fWEly4eL39X7Jq/ymrSW9Qcpl/+l0OrlBRKZUDAbOkf/Vzyjs3Y2YSMcYE48Tc2fOXHJf2kTL7aumBa1Wg6FSqbhcypXKwUwy+emplNw9uxj+0Q+wBRcRqXtomCOCEQGB9I3L6PzeNiTb3mQvDC2+7601onx4KsDBLd/m4qMPEY6NIQAaZ7AqIA1TAVQVQagcfZPhr6wjvDDQZFMEjEncYIxIdfLi2Is7cffuRlFEQMf/qI0T3+vXlWgH4YUBRnu/gRbcSaCCxZoE0UYn/D5wjks//D6KYjCogolwQCJG6UXdmGwO0RJowHg+1GIuBgjx//RbMms2TebkJJTGwn/8zC7WtbYgBTdmKjVGHQ9sInfvfZi6eOnQPuzpx9HCP+OdKaiNx13g3QmZa2r6xiTU1DN1q0X2nH6N3939sVqMYo9x9daf4H7hq2x8PqTrwUG6HhzklseGeOrESpwbX0I6ViASmRNxAANisO89ObFBwFob534sr599A4Cd2UG85R+vxbRj42aGe27ltieG2X/Mr+mfzYdsecGld5/B6XkWTXSAOCgGxAEx6PC+ye6lAfTf+dNYa1FVtt6cQOIsnXHvffS+4DLmTd2Dn/pziWMX2zCzPw+YBsZaPgPB6PSg/f99Nw6J0pcY453Vn4ySpr2dA8d9Lif7+zzkqrsidjFTxYAxcbynAVWlxlStZds1efjQZbtjoyQ6IqbGqWPckDbNoNlkawyuqMJ5LfPHhWkAujobVJtk3kwHLR6LXIo0MCYxY3rQxZ3XNjBFlR+n36b/vT6+vKJtWsCuTsMdSzLoxedRTJS9Eo8Iku2ZHnTl/FvQOKYKWFVQ5aG3fsEXlysPrGidEvDX93fi5l9GiyeQmOE4YzPrrqZ/EvWT7pkLmNM6i4HCJVQtANYq/UPvsHn/o/z0c73cs+wq9vd5NZfesSTDwf8c4FMjj8VANu7FISIOMuvOJlDxK5XjqWTy+vEPu08d5OFDT0SMNeow0aBkU23cveg2bp67lFw6y78uvc0rp//C4rTHw7mXo7pGUbUICum5OMuO1MBUoVz2HhHfrx5PpRLX1+9k/b5v8sa5KM1tfJyojUe1gEQxR2hLZnh96SDtdgSRccBIz+l5DpmxvGbXWkvJqzxiFG1Kyyc/20s21VaLaQQQGayVFWDV8rWF88ipW1cmUSydBVsaAAEUIZUwalBtOtpyqSzbV22le+a1WKsxkNaSjBi4u7OL9S2HwYyXSdQQnAXfRebe3xRLUELVUROqXphilY/Ouo4dq7exfunauG41ZqhYtaDwnY+EteYu4kC6C2fJDmTOhqlMgkLVt0dkrFjc2JrJ/NIx0xf/2bELPP2PP3Dg3cOcGT2PIHxm3iJ+Pv/vqLWYmbcinSuR2WumtQHgVap/y6SSt6OqqbJXOXylV8lRz9W/njmqI/mjaosnr/gKWg2CwljRn9hVPp/vKHv+sSu/xf5/Ug2CQqHkf6uJuuu6s4tl/5lKpToUBKGGYajWWrXWahja2vv7PWEYahBaDcJQgyDUsl850sCQye0fGBkZuS6ZTPYYk7jBYuMrQHSRu2zAALVULGjCGFXRkapvj+RyLf0i0nCg/g+snU9aOyl25wAAAABJRU5ErkJggg==","e":1},{"id":"comp_0","nm":"part 01 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"back_icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[79.754,75.483,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":804,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"chevron","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[284.118,348.127,0],"ix":2,"l":2},"a":{"a":0,"k":[3,5.127,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.444,0],[-0.153,0.147],[0,0],[-0.005,0.244],[0.199,0.188],[0,0],[0.216,0],[0,-0.438],[-0.16,-0.16],[0,0],[0,0],[0,-0.217]],"o":[[0.222,0],[0,0],[0.193,-0.193],[0,-0.245],[0,0],[-0.153,-0.148],[-0.444,0],[0,0.216],[0,0],[0,0],[-0.16,0.159],[0,0.438]],"v":[[0.796,10.255],[1.348,10.027],[5.71,5.767],[6,5.131],[5.71,4.493],[1.348,0.227],[0.796,0],[0,0.791],[0.25,1.371],[4.117,5.131],[0.25,8.884],[0,9.464]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"chevron","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,174.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,154.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"square","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,126.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":6,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"square","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.980392156863,0.980392156863,0.980392156863,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"divider_0202","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.980392156863,0.980392156863,0.980392156863,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":492,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.75,348.25,0],"ix":2,"l":2},"a":{"a":0,"k":[115.5,24,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":65,"s":[1,1,1,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[0.929932598039,0.929932598039,0.929932598039,1]},{"t":85,"s":[1,1,1,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":133,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"content_bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,146.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"content_bg 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","nm":"part 02 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"chrome_logo","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[97.5,178,0],"ix":2,"l":2},"a":{"a":0,"k":[14.5,14.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1227,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"checkmark","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.63],"y":[1]},"o":{"x":[0.168],"y":[0]},"t":135,"s":[0]},{"i":{"x":[0.669],"y":[1]},"o":{"x":[0.336],"y":[0]},"t":226,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":245,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[269.997,176.886,0],"ix":2,"l":2},"a":{"a":0,"k":[5.3,5.151,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.334,0],[-0.193,0.287],[0,0],[0,0.182],[0.492,0],[0.205,-0.328],[0,0],[0,0],[0.293,0],[0,-0.486],[-0.181,-0.211],[0,0]],"o":[[0.352,0],[0,0],[0.14,-0.21],[0,-0.48],[-0.34,0],[0,0],[0,0],[-0.199,-0.241],[-0.498,0],[0,0.211],[0,0],[0.228,0.275]],"v":[[4.096,10.301],[4.916,9.873],[10.401,1.412],[10.6,0.826],[9.756,0],[9.006,0.446],[4.073,8.25],[1.553,5.075],[0.856,4.723],[0,5.561],[0.252,6.182],[3.282,9.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960784314,0.450980392157,0.909803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"checkmark","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":135,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"back_icon 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[79.509,76.003,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0204","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"bar_0209","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,124.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"bar_0205","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,231.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0205","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"bar_0207","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,284.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0207","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"bar_0208","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,284,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0208","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"bar_0206","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,231,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0206","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"divider_0201","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,151.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.980392156863,0.980392156863,0.980392156863,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0201","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"divider_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.980392156863,0.980392156863,0.980392156863,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,257.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.980392156863,0.980392156863,0.980392156863,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,212],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","nm":"bg","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[147,305,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[294,602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"frame","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.5,-7,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[271,588],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":36,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"frame","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"shadow","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.5,11,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[263,580],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980392157,0.850980392157,0.850980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"shadow","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Bold","fName":"SFProText-Bold","ascent":74.31640625},{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Regular","fName":"SFProText-Regular","ascent":73.53515625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"mask 4","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-130.5,-293.264],[-130.5,293.264],[130.5,293.264],[130.5,-293.264]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":5,"nm":"IDS_CHROME","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[36.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-253.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.541,0.541,0.557]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"mask 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-130.5,-293.264],[-130.5,293.264],[130.5,293.264],[130.5,-293.264]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":3,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":109,"s":[-99.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-299.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"pointer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[268,187,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":28,"s":[195,347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":163,"s":[195,347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":184,"s":[195,177,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":62,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":71,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":80,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":217,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":227,"s":[90,90,100]},{"t":237,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.654901960784,0.78431372549,1,1],"ix":3},"o":{"a":0,"k":54.118,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":1,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.878431372549,0.925490196078,1,1],"ix":4},"o":{"a":0,"k":41.961,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"mask","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-130.5,-293.264],[-130.5,293.264],[130.5,293.264],[130.5,-293.264]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"part 01 new","parent":6,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[0,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-260,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"mask 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[299.5,-255,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-58.5,-255,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"mask 2","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":5,"nm":"IDS_CHROME","parent":10,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[267.5,-152.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-62.5,-152.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"mask 6","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"part 02 new","parent":12,"tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[310,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[0,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"bg","refId":"comp_2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177.333,335.583,0],"ix":2,"l":2},"a":{"a":0,"k":[149,303,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":298,"h":606,"ip":0,"op":334,"st":0,"bm":0}],"markers":[]}
diff --git a/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_darkmode.json b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_darkmode.json
new file mode 100644
index 0000000..aeaf636
--- /dev/null
+++ b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_darkmode.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":360,"w":375,"h":408,"nm":"animation 3","ddd":0,"assets":[{"id":"image_0","w":29,"h":29,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAYAAABWk2cPAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFpElEQVRIia2Wf4wVVxXHP+fO+7W7bx+7FFJhwVoaYK0sTWNp+UNM8UdbW4RQk8aGpFCLRkJiYlJ/pNWljWk1BKuxxmi0toJJa6xAC9RCsW0QI9Y2GBdkkbbEAgsLu77dnfdj5r2Ze/xjZt++t2+XYtKTTO7cuWfO937Pr3uFOikWizcZk9iMI/NFmS8QggiiXJGoWpEEihW1NghVz4P+vjWT2S4ilSb9Usn7ehAE5621+kFKEIZaKnuH8/l8RxNgNQg/ULDJ4vl+n+u6swFkpFi8KZtO73Uc5+rLec66LqVDr1I91U/l1ElEBNPeTmpRNy2fWEly4eL39X7Jq/ymrSW9Qcpl/+l0OrlBRKZUDAbOkf/Vzyjs3Y2YSMcYE48Tc2fOXHJf2kTL7aumBa1Wg6FSqbhcypXKwUwy+emplNw9uxj+0Q+wBRcRqXtomCOCEQGB9I3L6PzeNiTb3mQvDC2+7601onx4KsDBLd/m4qMPEY6NIQAaZ7AqIA1TAVQVQagcfZPhr6wjvDDQZFMEjEncYIxIdfLi2Is7cffuRlFEQMf/qI0T3+vXlWgH4YUBRnu/gRbcSaCCxZoE0UYn/D5wjks//D6KYjCogolwQCJG6UXdmGwO0RJowHg+1GIuBgjx//RbMms2TebkJJTGwn/8zC7WtbYgBTdmKjVGHQ9sInfvfZi6eOnQPuzpx9HCP+OdKaiNx13g3QmZa2r6xiTU1DN1q0X2nH6N3939sVqMYo9x9daf4H7hq2x8PqTrwUG6HhzklseGeOrESpwbX0I6ViASmRNxAANisO89ObFBwFob534sr599A4Cd2UG85R+vxbRj42aGe27ltieG2X/Mr+mfzYdsecGld5/B6XkWTXSAOCgGxAEx6PC+ye6lAfTf+dNYa1FVtt6cQOIsnXHvffS+4DLmTd2Dn/pziWMX2zCzPw+YBsZaPgPB6PSg/f99Nw6J0pcY453Vn4ySpr2dA8d9Lif7+zzkqrsidjFTxYAxcbynAVWlxlStZds1efjQZbtjoyQ6IqbGqWPckDbNoNlkawyuqMJ5LfPHhWkAujobVJtk3kwHLR6LXIo0MCYxY3rQxZ3XNjBFlR+n36b/vT6+vKJtWsCuTsMdSzLoxedRTJS9Eo8Iku2ZHnTl/FvQOKYKWFVQ5aG3fsEXlysPrGidEvDX93fi5l9GiyeQmOE4YzPrrqZ/EvWT7pkLmNM6i4HCJVQtANYq/UPvsHn/o/z0c73cs+wq9vd5NZfesSTDwf8c4FMjj8VANu7FISIOMuvOJlDxK5XjqWTy+vEPu08d5OFDT0SMNeow0aBkU23cveg2bp67lFw6y78uvc0rp//C4rTHw7mXo7pGUbUICum5OMuO1MBUoVz2HhHfrx5PpRLX1+9k/b5v8sa5KM1tfJyojUe1gEQxR2hLZnh96SDtdgSRccBIz+l5DpmxvGbXWkvJqzxiFG1Kyyc/20s21VaLaQQQGayVFWDV8rWF88ipW1cmUSydBVsaAAEUIZUwalBtOtpyqSzbV22le+a1WKsxkNaSjBi4u7OL9S2HwYyXSdQQnAXfRebe3xRLUELVUROqXphilY/Ouo4dq7exfunauG41ZqhYtaDwnY+EteYu4kC6C2fJDmTOhqlMgkLVt0dkrFjc2JrJ/NIx0xf/2bELPP2PP3Dg3cOcGT2PIHxm3iJ+Pv/vqLWYmbcinSuR2WumtQHgVap/y6SSt6OqqbJXOXylV8lRz9W/njmqI/mjaosnr/gKWg2CwljRn9hVPp/vKHv+sSu/xf5/Ug2CQqHkf6uJuuu6s4tl/5lKpToUBKGGYajWWrXWahja2vv7PWEYahBaDcJQgyDUsl850sCQye0fGBkZuS6ZTPYYk7jBYuMrQHSRu2zAALVULGjCGFXRkapvj+RyLf0i0nCg/g+snU9aOyl25wAAAABJRU5ErkJggg==","e":1},{"id":"comp_0","nm":"part 01 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"back_icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[79.754,75.483,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":804,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"chevron","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[284.118,348.127,0],"ix":2,"l":2},"a":{"a":0,"k":[3,5.127,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.444,0],[-0.153,0.147],[0,0],[-0.005,0.244],[0.199,0.188],[0,0],[0.216,0],[0,-0.438],[-0.16,-0.16],[0,0],[0,0],[0,-0.217]],"o":[[0.222,0],[0,0],[0.193,-0.193],[0,-0.245],[0,0],[-0.153,-0.148],[-0.444,0],[0,0.216],[0,0],[0,0],[-0.16,0.159],[0,0.438]],"v":[[0.796,10.255],[1.348,10.027],[5.71,5.767],[6,5.131],[5.71,4.493],[1.348,0.227],[0.796,0],[0,0.791],[0.25,1.371],[4.117,5.131],[0.25,8.884],[0,9.464]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.321568627451,0.317647058824,0.325490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"chevron","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,174.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,154.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"square","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,126.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":6,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"square","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.164705882353,0.160784313725,0.16862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"divider_0202","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.164705882353,0.160784313725,0.16862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":492,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.75,348.25,0],"ix":2,"l":2},"a":{"a":0,"k":[115.5,24,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":65,"s":[0.109803922474,0.109803922474,0.117647059262,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[0.29675245285,0.29675245285,0.29675245285,1]},{"t":85,"s":[0.109803922474,0.109803922474,0.117647059262,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":486,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"content_bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,146.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"content_bg 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","nm":"part 02 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"chrome_logo","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[97.5,178,0],"ix":2,"l":2},"a":{"a":0,"k":[14.5,14.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1164,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"checkmark","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.63],"y":[1]},"o":{"x":[0.168],"y":[0]},"t":135,"s":[0]},{"i":{"x":[0.669],"y":[1]},"o":{"x":[0.336],"y":[0]},"t":226,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":245,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[279.997,176.886,0],"ix":2,"l":2},"a":{"a":0,"k":[5.3,5.151,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.334,0],[-0.193,0.287],[0,0],[0,0.182],[0.492,0],[0.205,-0.328],[0,0],[0,0],[0.293,0],[0,-0.486],[-0.181,-0.211],[0,0]],"o":[[0.352,0],[0,0],[0.14,-0.21],[0,-0.48],[-0.34,0],[0,0],[0,0],[-0.199,-0.241],[-0.498,0],[0,0.211],[0,0],[0.228,0.275]],"v":[[4.096,10.301],[4.916,9.873],[10.401,1.412],[10.6,0.826],[9.756,0],[9.006,0.446],[4.073,8.25],[1.553,5.075],[0.856,4.723],[0,5.561],[0.252,6.182],[3.282,9.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960784314,0.450980392157,0.909803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"checkmark","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":135,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"back_icon 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[79.509,76.003,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0204","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"bar_0209","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,124.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"bar_0205","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,231.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0205","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"bar_0207","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,284.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0207","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"bar_0208","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,284,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0208","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"bar_0206","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[98,231,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0206","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"divider_0201","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,151.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0201","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"divider_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,257.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,212],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","nm":"bg","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[147,305,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[294,602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"frame","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.5,-7,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[271,588],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":36,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"frame","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"shadow","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.5,11,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[263,580],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980392157,0.850980392157,0.850980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"shadow","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Bold","fName":"SFProText-Bold","ascent":74.31640625},{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Regular","fName":"SFProText-Regular","ascent":73.53515625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"mask 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":5,"nm":"IDS_CHROME","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[36.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-253.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.541,0.541,0.557]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"mask 4","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":109,"s":[-99.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-299.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.996,0.996,0.996]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"pointer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[268,187,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":28,"s":[195,347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":163,"s":[195,347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":184,"s":[195,177,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":62,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":71,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":80,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":217,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":227,"s":[90,90,100]},{"t":237,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.254963205375,0.534352022059,1,1],"ix":3},"o":{"a":0,"k":54.118,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":1,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.444776348039,0.659701657763,1,1],"ix":4},"o":{"a":0,"k":41.961,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"mask","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"part 01 new","parent":6,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[0,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[-260,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"mask 2","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[299.5,-255,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-58.5,-255,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"mask 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":5,"nm":"IDS_CHROME","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[267.5,-152.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-62.5,-152.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.98,0.98,0.98]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"mask 6","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"part 02 new","parent":8,"tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[310,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[0,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"bg","refId":"comp_2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177.333,335.583,0],"ix":2,"l":2},"a":{"a":0,"k":[149,303,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":298,"h":606,"ip":0,"op":334,"st":0,"bm":0}],"markers":[]}
diff --git a/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl.json b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl.json
new file mode 100644
index 0000000..205a66f
--- /dev/null
+++ b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":360,"w":375,"h":408,"nm":"animation 3","ddd":0,"assets":[{"id":"image_0","w":29,"h":29,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAYAAABWk2cPAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFpElEQVRIia2Wf4wVVxXHP+fO+7W7bx+7FFJhwVoaYK0sTWNp+UNM8UdbW4RQk8aGpFCLRkJiYlJ/pNWljWk1BKuxxmi0toJJa6xAC9RCsW0QI9Y2GBdkkbbEAgsLu77dnfdj5r2Ze/xjZt++t2+XYtKTTO7cuWfO937Pr3uFOikWizcZk9iMI/NFmS8QggiiXJGoWpEEihW1NghVz4P+vjWT2S4ilSb9Usn7ehAE5621+kFKEIZaKnuH8/l8RxNgNQg/ULDJ4vl+n+u6swFkpFi8KZtO73Uc5+rLec66LqVDr1I91U/l1ElEBNPeTmpRNy2fWEly4eL39X7Jq/ymrSW9Qcpl/+l0OrlBRKZUDAbOkf/Vzyjs3Y2YSMcYE48Tc2fOXHJf2kTL7aumBa1Wg6FSqbhcypXKwUwy+emplNw9uxj+0Q+wBRcRqXtomCOCEQGB9I3L6PzeNiTb3mQvDC2+7601onx4KsDBLd/m4qMPEY6NIQAaZ7AqIA1TAVQVQagcfZPhr6wjvDDQZFMEjEncYIxIdfLi2Is7cffuRlFEQMf/qI0T3+vXlWgH4YUBRnu/gRbcSaCCxZoE0UYn/D5wjks//D6KYjCogolwQCJG6UXdmGwO0RJowHg+1GIuBgjx//RbMms2TebkJJTGwn/8zC7WtbYgBTdmKjVGHQ9sInfvfZi6eOnQPuzpx9HCP+OdKaiNx13g3QmZa2r6xiTU1DN1q0X2nH6N3939sVqMYo9x9daf4H7hq2x8PqTrwUG6HhzklseGeOrESpwbX0I6ViASmRNxAANisO89ObFBwFob534sr599A4Cd2UG85R+vxbRj42aGe27ltieG2X/Mr+mfzYdsecGld5/B6XkWTXSAOCgGxAEx6PC+ye6lAfTf+dNYa1FVtt6cQOIsnXHvffS+4DLmTd2Dn/pziWMX2zCzPw+YBsZaPgPB6PSg/f99Nw6J0pcY453Vn4ySpr2dA8d9Lif7+zzkqrsidjFTxYAxcbynAVWlxlStZds1efjQZbtjoyQ6IqbGqWPckDbNoNlkawyuqMJ5LfPHhWkAujobVJtk3kwHLR6LXIo0MCYxY3rQxZ3XNjBFlR+n36b/vT6+vKJtWsCuTsMdSzLoxedRTJS9Eo8Iku2ZHnTl/FvQOKYKWFVQ5aG3fsEXlysPrGidEvDX93fi5l9GiyeQmOE4YzPrrqZ/EvWT7pkLmNM6i4HCJVQtANYq/UPvsHn/o/z0c73cs+wq9vd5NZfesSTDwf8c4FMjj8VANu7FISIOMuvOJlDxK5XjqWTy+vEPu08d5OFDT0SMNeow0aBkU23cveg2bp67lFw6y78uvc0rp//C4rTHw7mXo7pGUbUICum5OMuO1MBUoVz2HhHfrx5PpRLX1+9k/b5v8sa5KM1tfJyojUe1gEQxR2hLZnh96SDtdgSRccBIz+l5DpmxvGbXWkvJqzxiFG1Kyyc/20s21VaLaQQQGayVFWDV8rWF88ipW1cmUSydBVsaAAEUIZUwalBtOtpyqSzbV22le+a1WKsxkNaSjBi4u7OL9S2HwYyXSdQQnAXfRebe3xRLUELVUROqXphilY/Ouo4dq7exfunauG41ZqhYtaDwnY+EteYu4kC6C2fJDmTOhqlMgkLVt0dkrFjc2JrJ/NIx0xf/2bELPP2PP3Dg3cOcGT2PIHxm3iJ+Pv/vqLWYmbcinSuR2WumtQHgVap/y6SSt6OqqbJXOXylV8lRz9W/njmqI/mjaosnr/gKWg2CwljRn9hVPp/vKHv+sSu/xf5/Ug2CQqHkf6uJuuu6s4tl/5lKpToUBKGGYajWWrXWahja2vv7PWEYahBaDcJQgyDUsl850sCQye0fGBkZuS6ZTPYYk7jBYuMrQHSRu2zAALVULGjCGFXRkapvj+RyLf0i0nCg/g+snU9aOyl25wAAAABJRU5ErkJggg==","e":1},{"id":"comp_0","nm":"part 01 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"back_icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":181.545,"ix":10},"p":{"a":0,"k":[293.754,75.483,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":804,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"chevron","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-180,"ix":10},"p":{"a":0,"k":[91.118,348.127,0],"ix":2,"l":2},"a":{"a":0,"k":[3,5.127,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.444,0],[-0.153,0.147],[0,0],[-0.005,0.244],[0.199,0.188],[0,0],[0.216,0],[0,-0.438],[-0.16,-0.16],[0,0],[0,0],[0,-0.217]],"o":[[0.222,0],[0,0],[0.193,-0.193],[0,-0.245],[0,0],[-0.153,-0.148],[-0.444,0],[0,0.216],[0,0],[0,0],[-0.16,0.159],[0,0.438]],"v":[[0.796,10.255],[1.348,10.027],[5.71,5.767],[6,5.131],[5.71,4.493],[1.348,0.227],[0.796,0],[0,0.791],[0.25,1.371],[4.117,5.131],[0.25,8.884],[0,9.464]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.741176470588,0.741176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"chevron","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,174.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,154.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"square","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,126.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":6,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"square","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.866666666667,0.866666666667,0.874509803922,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"divider_0202","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.866666666667,0.866666666667,0.874509803922,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":492,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.75,348.25,0],"ix":2,"l":2},"a":{"a":0,"k":[115.5,24,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":65,"s":[1,1,1,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[0.866666674614,0.866666674614,0.874509811401,1]},{"t":85,"s":[1,1,1,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":486,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"content_bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,146.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"content_bg 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","nm":"part 02 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"chrome_logo","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.5,178,0],"ix":2,"l":2},"a":{"a":0,"k":[14.5,14.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1164,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"checkmark","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.63],"y":[1]},"o":{"x":[0.168],"y":[0]},"t":135,"s":[0]},{"i":{"x":[0.669],"y":[1]},"o":{"x":[0.336],"y":[0]},"t":226,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":245,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[95.997,176.886,0],"ix":2,"l":2},"a":{"a":0,"k":[5.3,5.151,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.334,0],[-0.193,0.287],[0,0],[0,0.182],[0.492,0],[0.205,-0.328],[0,0],[0,0],[0.293,0],[0,-0.486],[-0.181,-0.211],[0,0]],"o":[[0.352,0],[0,0],[0.14,-0.21],[0,-0.48],[-0.34,0],[0,0],[0,0],[-0.199,-0.241],[-0.498,0],[0,0.211],[0,0],[0.228,0.275]],"v":[[4.096,10.301],[4.916,9.873],[10.401,1.412],[10.6,0.826],[9.756,0],[9.006,0.446],[4.073,8.25],[1.553,5.075],[0.856,4.723],[0,5.561],[0.252,6.182],[3.282,9.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960784314,0.450980392157,0.909803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"checkmark","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":135,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"back_icon 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[289.509,76.003,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0204","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"bar_0209","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[189.584,124.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"bar_0205","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,231.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0205","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"bar_0207","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,284.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0207","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"bar_0208","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,284,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0208","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"bar_0206","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,231,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0206","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"divider_0201","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,151.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.905882352941,0.905882352941,0.909803921569,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0201","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"divider_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.905882352941,0.905882352941,0.909803921569,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,257.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.905882352941,0.905882352941,0.909803921569,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,212],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","nm":"bg","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[147,305,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[294,602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"frame","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.5,-7,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[271,588],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":36,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"frame","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"shadow","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.5,11,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[263,580],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980392157,0.850980392157,0.850980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"shadow","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Bold","fName":"SFProText-Bold","ascent":74.31640625},{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Regular","fName":"SFProText-Regular","ascent":73.53515625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"mask 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":5,"nm":"IDS_CHROME","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[-85.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[299.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.541,0.541,0.557]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"mask 4","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[13.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[266.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"pointer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[138,187,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":29,"s":[174,347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":161,"s":[172,347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":189,"s":[172,177,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":62,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":71,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":80,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":217,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":227,"s":[90,90,100]},{"t":237,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.654901960784,0.78431372549,1,1],"ix":3},"o":{"a":0,"k":54.118,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":1,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.878431372549,0.925490196078,1,1],"ix":4},"o":{"a":0,"k":41.961,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"mask","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"part 01 new","parent":6,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[0,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[270,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"mask 2","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[-320.5,-255,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-58.5,-255,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"mask 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":5,"nm":"IDS_CHROME","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[-252.5,-152.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[16.5,-152.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"mask 6","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"part 02 new","parent":8,"tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":121,"s":[-270,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[0,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"bg","refId":"comp_2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177.333,335.583,0],"ix":2,"l":2},"a":{"a":0,"k":[149,303,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":298,"h":606,"ip":0,"op":334,"st":0,"bm":0}],"markers":[]}
diff --git a/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl_darkmode.json b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl_darkmode.json
new file mode 100644
index 0000000..b822af38
--- /dev/null
+++ b/ios/chrome/browser/default_promo/ui_bundled/resources/default_browser_default_apps_animation_rtl_darkmode.json
@@ -0,0 +1 @@
+{"v":"5.9.0","fr":60,"ip":0,"op":360,"w":375,"h":408,"nm":"animation 3","ddd":0,"assets":[{"id":"image_0","w":29,"h":29,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAYAAABWk2cPAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFpElEQVRIia2Wf4wVVxXHP+fO+7W7bx+7FFJhwVoaYK0sTWNp+UNM8UdbW4RQk8aGpFCLRkJiYlJ/pNWljWk1BKuxxmi0toJJa6xAC9RCsW0QI9Y2GBdkkbbEAgsLu77dnfdj5r2Ze/xjZt++t2+XYtKTTO7cuWfO937Pr3uFOikWizcZk9iMI/NFmS8QggiiXJGoWpEEihW1NghVz4P+vjWT2S4ilSb9Usn7ehAE5621+kFKEIZaKnuH8/l8RxNgNQg/ULDJ4vl+n+u6swFkpFi8KZtO73Uc5+rLec66LqVDr1I91U/l1ElEBNPeTmpRNy2fWEly4eL39X7Jq/ymrSW9Qcpl/+l0OrlBRKZUDAbOkf/Vzyjs3Y2YSMcYE48Tc2fOXHJf2kTL7aumBa1Wg6FSqbhcypXKwUwy+emplNw9uxj+0Q+wBRcRqXtomCOCEQGB9I3L6PzeNiTb3mQvDC2+7601onx4KsDBLd/m4qMPEY6NIQAaZ7AqIA1TAVQVQagcfZPhr6wjvDDQZFMEjEncYIxIdfLi2Is7cffuRlFEQMf/qI0T3+vXlWgH4YUBRnu/gRbcSaCCxZoE0UYn/D5wjks//D6KYjCogolwQCJG6UXdmGwO0RJowHg+1GIuBgjx//RbMms2TebkJJTGwn/8zC7WtbYgBTdmKjVGHQ9sInfvfZi6eOnQPuzpx9HCP+OdKaiNx13g3QmZa2r6xiTU1DN1q0X2nH6N3939sVqMYo9x9daf4H7hq2x8PqTrwUG6HhzklseGeOrESpwbX0I6ViASmRNxAANisO89ObFBwFob534sr599A4Cd2UG85R+vxbRj42aGe27ltieG2X/Mr+mfzYdsecGld5/B6XkWTXSAOCgGxAEx6PC+ye6lAfTf+dNYa1FVtt6cQOIsnXHvffS+4DLmTd2Dn/pziWMX2zCzPw+YBsZaPgPB6PSg/f99Nw6J0pcY453Vn4ySpr2dA8d9Lif7+zzkqrsidjFTxYAxcbynAVWlxlStZds1efjQZbtjoyQ6IqbGqWPckDbNoNlkawyuqMJ5LfPHhWkAujobVJtk3kwHLR6LXIo0MCYxY3rQxZ3XNjBFlR+n36b/vT6+vKJtWsCuTsMdSzLoxedRTJS9Eo8Iku2ZHnTl/FvQOKYKWFVQ5aG3fsEXlysPrGidEvDX93fi5l9GiyeQmOE4YzPrrqZ/EvWT7pkLmNM6i4HCJVQtANYq/UPvsHn/o/z0c73cs+wq9vd5NZfesSTDwf8c4FMjj8VANu7FISIOMuvOJlDxK5XjqWTy+vEPu08d5OFDT0SMNeow0aBkU23cveg2bp67lFw6y78uvc0rp//C4rTHw7mXo7pGUbUICum5OMuO1MBUoVz2HhHfrx5PpRLX1+9k/b5v8sa5KM1tfJyojUe1gEQxR2hLZnh96SDtdgSRccBIz+l5DpmxvGbXWkvJqzxiFG1Kyyc/20s21VaLaQQQGayVFWDV8rWF88ipW1cmUSydBVsaAAEUIZUwalBtOtpyqSzbV22le+a1WKsxkNaSjBi4u7OL9S2HwYyXSdQQnAXfRebe3xRLUELVUROqXphilY/Ouo4dq7exfunauG41ZqhYtaDwnY+EteYu4kC6C2fJDmTOhqlMgkLVt0dkrFjc2JrJ/NIx0xf/2bELPP2PP3Dg3cOcGT2PIHxm3iJ+Pv/vqLWYmbcinSuR2WumtQHgVap/y6SSt6OqqbJXOXylV8lRz9W/njmqI/mjaosnr/gKWg2CwljRn9hVPp/vKHv+sSu/xf5/Ug2CQqHkf6uJuuu6s4tl/5lKpToUBKGGYajWWrXWahja2vv7PWEYahBaDcJQgyDUsl850sCQye0fGBkZuS6ZTPYYk7jBYuMrQHSRu2zAALVULGjCGFXRkapvj+RyLf0i0nCg/g+snU9aOyl25wAAAABJRU5ErkJggg==","e":1},{"id":"comp_0","nm":"part 01 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"back_icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":181.545,"ix":10},"p":{"a":0,"k":[293.754,75.483,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":804,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"chevron","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-180,"ix":10},"p":{"a":0,"k":[91.118,348.127,0],"ix":2,"l":2},"a":{"a":0,"k":[3,5.127,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.444,0],[-0.153,0.147],[0,0],[-0.005,0.244],[0.199,0.188],[0,0],[0.216,0],[0,-0.438],[-0.16,-0.16],[0,0],[0,0],[0,-0.217]],"o":[[0.222,0],[0,0],[0.193,-0.193],[0,-0.245],[0,0],[-0.153,-0.148],[-0.444,0],[0,0.216],[0,0],[0,0],[-0.16,0.159],[0,0.438]],"v":[[0.796,10.255],[1.348,10.027],[5.71,5.767],[6,5.131],[5.71,4.493],[1.348,0.227],[0.796,0],[0,0.791],[0.25,1.371],[4.117,5.131],[0.25,8.884],[0,9.464]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.321568627451,0.317647058824,0.325490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"chevron","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,174.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.917,154.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[198,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"square","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,126.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":6,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"square","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.164705882353,0.160784313725,0.16862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"divider_0202","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.164705882353,0.160784313725,0.16862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":492,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.75,348.25,0],"ix":2,"l":2},"a":{"a":0,"k":[115.5,24,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-4.418,0],[0,0],[0,-4.418],[0,0],[0,0],[0,0],[0,0]],"o":[[0,-4.418],[0,0],[4.418,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0,8],[8,0],[223,0],[231,8],[231,48],[231,48],[0,48],[0,48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":65,"s":[0.109803922474,0.109803922474,0.117647059262,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[0.29675245285,0.29675245285,0.29675245285,1]},{"t":85,"s":[0.109803922474,0.109803922474,0.117647059262,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":486,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,372.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"content_bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,146.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"content_bg 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,259.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,97],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","nm":"part 02 new","fr":60,"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"chrome_logo","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.5,178,0],"ix":2,"l":2},"a":{"a":0,"k":[14.5,14.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1164,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"checkmark","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.63],"y":[1]},"o":{"x":[0.168],"y":[0]},"t":135,"s":[0]},{"i":{"x":[0.669],"y":[1]},"o":{"x":[0.336],"y":[0]},"t":226,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":245,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[95.997,176.886,0],"ix":2,"l":2},"a":{"a":0,"k":[5.3,5.151,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.334,0],[-0.193,0.287],[0,0],[0,0.182],[0.492,0],[0.205,-0.328],[0,0],[0,0],[0.293,0],[0,-0.486],[-0.181,-0.211],[0,0]],"o":[[0.352,0],[0,0],[0.14,-0.21],[0,-0.48],[-0.34,0],[0,0],[0,0],[-0.199,-0.241],[-0.498,0],[0,0.211],[0,0],[0.228,0.275]],"v":[[4.096,10.301],[4.916,9.873],[10.401,1.412],[10.6,0.826],[9.756,0],[9.006,0.446],[4.073,8.25],[1.553,5.075],[0.856,4.723],[0,5.561],[0.252,6.182],[3.282,9.903]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960784314,0.450980392157,0.909803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"checkmark","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":135,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"back_icon 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[289.509,76.003,0],"ix":2,"l":2},"a":{"a":0,"k":[4.379,7.483,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.647,0],[0.224,-0.216],[0,0],[0.008,-0.357],[-0.29,-0.274],[0,0],[-0.315,0],[0,0.639],[0.232,0.232],[0,0],[0,0],[0,0.315]],"o":[[-0.324,0],[0,0],[-0.282,0.282],[0,0.357],[0,0],[0.224,0.216],[0.647,0],[0,-0.316],[0,0],[0,0],[0.232,-0.232],[0,-0.639]],"v":[[7.595,0],[6.79,0.332],[0.423,6.549],[0,7.479],[0.423,8.409],[6.79,14.634],[7.595,14.966],[8.757,13.812],[8.392,12.966],[2.748,7.479],[8.392,2],[8.757,1.154]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215686275,0.525490196078,0.992156862745,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"back_icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1216,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"bar_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0204","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"bar_0209","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[189.584,124.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"bar_0205","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,231.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0205","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"bar_0207","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[188.584,284.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[133.167,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0207","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"bar_0208","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,284,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0208","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"bar_0206","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278,231,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[28,28],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.560784313725,0.556862745098,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bar_0206","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"divider_0201","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,151.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0201","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"divider_0204","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0202","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"divider_0203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,257.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,1],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.152941176471,0.149019607843,0.156862745098,1],"ix":4},"o":{"a":0,"k":94.902,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"divider_0203","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":4482,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"content_bg 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[231,212],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803921569,0.109803921569,0.117647058824,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"content_bg","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","nm":"bg","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[147,305,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[294,602],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"frame","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.5,-7,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[271,588],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":36,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"frame","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"shadow","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.5,11,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[263,580],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980392157,0.850980392157,0.850980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"shadow","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Bold","fName":"SFProText-Bold","ascent":74.31640625},{"origin":0,"fPath":"","fClass":"","fFamily":"SF Pro Text","fWeight":"","fStyle":"Regular","fName":"SFProText-Regular","ascent":73.53515625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"mask 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":5,"nm":"IDS_CHROME","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[-85.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[299.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.541,0.541,0.557]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"mask 4","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[13.5,18,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[266.5,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.996,0.996,0.996]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"pointer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[138,187,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":29,"s":[174,347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":161,"s":[172,347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":189,"s":[172,177,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":62,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":71,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":80,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":217,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":227,"s":[90,90,100]},{"t":237,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.254963205375,0.534352022059,1,1],"ix":3},"o":{"a":0,"k":54.118,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":1,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[38,38],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.444776348039,0.659701657763,1,1],"ix":4},"o":{"a":0,"k":41.961,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"pointer Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"mask","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"part 01 new","parent":6,"tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109,"s":[0,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":129,"s":[270,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"mask 2","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":5,"nm":"IDS_DEFAULT_BROWSER_APP","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[-320.5,-255,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[-58.5,-255,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Regular","t":"Default Browser App","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"mask 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":5,"nm":"IDS_CHROME","parent":8,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":121,"s":[-252.5,-152.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[16.5,-152.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"t":{"d":{"k":[{"s":{"s":13,"f":"SFProText-Bold","t":"Chrome","ca":0,"j":0,"tr":-32,"lh":22,"ls":0,"fc":[0.98,0.98,0.98]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"mask 6","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,334,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[261,586.529],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":334,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"part 02 new","parent":8,"tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":121,"s":[-270,-130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":141,"s":[0,-130,0]}],"ix":2,"l":2},"a":{"a":0,"k":[187.5,204,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":375,"h":408,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"bg","refId":"comp_2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":308,"s":[100]},{"t":329,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177.333,335.583,0],"ix":2,"l":2},"a":{"a":0,"k":[149,303,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":298,"h":606,"ip":0,"op":334,"st":0,"bm":0}],"markers":[]}
diff --git a/ios/chrome/browser/first_run/ui_bundled/first_run_post_action_provider.mm b/ios/chrome/browser/first_run/ui_bundled/first_run_post_action_provider.mm
index 8be9cbf..98990869 100644
--- a/ios/chrome/browser/first_run/ui_bundled/first_run_post_action_provider.mm
+++ b/ios/chrome/browser/first_run/ui_bundled/first_run_post_action_provider.mm
@@ -15,7 +15,7 @@
   if (IsBestOfAppGuidedTourEnabled()) {
     [screens addObject:@(kGuidedTour)];
   }
-  if (base::FeatureList::IsEnabled(kImportPasswordsFromSafari)) {
+  if (ShouldShowSafariImportWorkflow()) {
     [screens addObject:@(kSafariImport)];
   }
   [screens addObject:@(kStepsCompleted)];
diff --git a/ios/chrome/browser/first_run/ui_bundled/first_run_without_search_engine_choice_egtest.mm b/ios/chrome/browser/first_run/ui_bundled/first_run_without_search_engine_choice_egtest.mm
index fc564835..2564b35 100644
--- a/ios/chrome/browser/first_run/ui_bundled/first_run_without_search_engine_choice_egtest.mm
+++ b/ios/chrome/browser/first_run/ui_bundled/first_run_without_search_engine_choice_egtest.mm
@@ -547,7 +547,7 @@
   [self verifyEnterpriseWelcomeScreenIsDisplayedWithFRESigninIntent:
             FRESigninIntentSigninWithPolicy];
 
-  // Add the identity list.
+  // Show the identity list.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           kIdentityButtonControlIdentifier)]
       performAction:grey_tap()];
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index c95b7db..6d681a2 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -2862,6 +2862,9 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          password_manager::features::kApplyClientsideModelPredictionsForOtps)},
+    {"page-context-anchor-tags", flag_descriptions::kPageContextAnchorTagsName,
+     flag_descriptions::kPageContextAnchorTagsDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kPageContextAnchorTags)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 619cc99..88a20b33 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -1318,6 +1318,10 @@
     "Enables annotating the page visibility model for each page load "
     "on-device.";
 
+const char kPageContextAnchorTagsName[] = "Page Context anchor tags";
+const char kPageContextAnchorTagsDescription[] =
+    "Include the retrieval of anchor tags (links) as part of Page Context.";
+
 const char kPasswordFormClientsideClassifierName[] =
     "Clientside password form classifier.";
 const char kPasswordFormClientsideClassifierDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index e2e1d3d..d83e19f8 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -762,6 +762,9 @@
 extern const char kPageContentAnnotationsRemotePageMetadataName[];
 extern const char kPageContentAnnotationsRemotePageMetadataDescription[];
 
+extern const char kPageContextAnchorTagsName[];
+extern const char kPageContextAnchorTagsDescription[];
+
 extern const char kPageImageServiceSalientImageName[];
 extern const char kPageImageServiceSalientImageDescription[];
 
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.h b/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.h
index 479541c5..510f5272 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.h
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.h
@@ -9,6 +9,7 @@
 
 #import "ios/chrome/browser/home_customization/ui/home_customization_background_color_picker_mutator.h"
 @protocol HomeCustomizationBackgroundColorPickerConsumer;
+class HomeBackgroundCustomizationService;
 
 // A mediator that generates and configures background color palettes
 // for the Home customization screen, and communicates them to a consumer.
@@ -19,6 +20,9 @@
 @property(nonatomic, weak) id<HomeCustomizationBackgroundColorPickerConsumer>
     consumer;
 
+- (instancetype)initWithBackgroundCustomizationService:
+    (HomeBackgroundCustomizationService*)backgroundCustomizationService;
+
 // Generates a predefined set of color palettes and provides them to the
 // consumer.
 - (void)configureColorPalettes;
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.mm
index 549618f..d5b5c80 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.mm
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_color_picker_mediator.mm
@@ -6,6 +6,7 @@
 
 #import <Foundation/Foundation.h>
 
+#import "ios/chrome/browser/home_customization/model/home_background_customization_service.h"
 #import "ios/chrome/browser/home_customization/ui/home_customization_background_color_picker_consumer.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_color_palette.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_color_palette_util.h"
@@ -21,18 +22,18 @@
   ui::ColorProviderKey::SchemeVariant variant;
 };
 
-// Array of seed colors (in RGB integer format) and variants used to generate
+// Array of seed colors (in ARGB integer format) and variants used to generate
 // background color palette configurations in the color picker.
 const SeedColor kSeedColors[] = {
-    {0x8cabe4, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Blue
-    {0x26a69a, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Aqua
-    {0x00ff00, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Green
-    {0x87ba81, ui::ColorProviderKey::SchemeVariant::kNeutral},    // Viridian
-    {0xfadf73, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Citron
-    {0xff8000, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Orange
-    {0xf3b2be, ui::ColorProviderKey::SchemeVariant::kNeutral},    // Rose
-    {0xff00ff, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Fuchsia
-    {0xe5d5fc, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Violet
+    {0xff8cabe4, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Blue
+    {0xff26a69a, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Aqua
+    {0xff00ff00, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Green
+    {0xff87ba81, ui::ColorProviderKey::SchemeVariant::kNeutral},    // Viridian
+    {0xfffadf73, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Citron
+    {0xffff8000, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Orange
+    {0xfff3b2be, ui::ColorProviderKey::SchemeVariant::kNeutral},    // Rose
+    {0xffff00ff, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Fuchsia
+    {0xffe5d5fc, ui::ColorProviderKey::SchemeVariant::kTonalSpot},  // Violet
 };
 
 // Returns a dynamic UIColor using two named color assets for light and dark
@@ -47,10 +48,25 @@
 
 }  // namespace
 
-@implementation HomeCustomizationBackgroundColorPickerMediator
+@implementation HomeCustomizationBackgroundColorPickerMediator {
+  // Used to get and observe the background state.
+  raw_ptr<HomeBackgroundCustomizationService> _backgroundCustomizationService;
+}
 
+- (instancetype)initWithBackgroundCustomizationService:
+    (HomeBackgroundCustomizationService*)backgroundCustomizationService {
+  self = [super init];
+  if (self) {
+    _backgroundCustomizationService = backgroundCustomizationService;
+  }
+
+  return self;
+}
 - (void)configureColorPalettes {
   NSMutableArray* colorPalettes = [NSMutableArray array];
+  std::optional<sync_pb::UserColorTheme> colorTheme =
+      _backgroundCustomizationService->GetCurrentColorTheme();
+  NSNumber* selectedColorIndex = nil;
 
   NewTabPageColorPalette* defaultColorPalette =
       [[NewTabPageColorPalette alloc] init];
@@ -70,11 +86,26 @@
     [colorPalettes
         addObject:CreateColorPaletteFromSeedColor(
                       UIColorFromRGB(seedColor.color), seedColor.variant)];
+
+    if (colorTheme && colorTheme->color() &&
+        seedColor.color == colorTheme->color()) {
+      selectedColorIndex = @(colorPalettes.count - 1);
+    }
   }
 
-  // TODO(crbug.com/408243803): Pass the current selection ID if the background
-  // is a color; pass 0 if the background is set to "no background".
-  [_consumer setColorPalettes:colorPalettes selectedColorIndex:@(0)];
+  // If no color is currently selected, set selectedColorIndex to nil
+  // when a background image is active, or to 0 when there is no background.
+  if (!selectedColorIndex) {
+    selectedColorIndex =
+        _backgroundCustomizationService->GetCurrentCustomBackground() ||
+                _backgroundCustomizationService
+                    ->GetCurrentUserUploadedBackground()
+            ? nil
+            : @(0);
+  }
+
+  [_consumer setColorPalettes:colorPalettes
+           selectedColorIndex:selectedColorIndex];
 }
 
 @end
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm
index 01eb87fe3..998219d0 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm
@@ -92,11 +92,14 @@
       initWithHomeBackgroundCustomizationService:
           homeBackgroundCustomizationService];
   _backgroundColorPickerMediator =
-      [[HomeCustomizationBackgroundColorPickerMediator alloc] init];
+      [[HomeCustomizationBackgroundColorPickerMediator alloc]
+          initWithBackgroundCustomizationService:
+              homeBackgroundCustomizationService];
   _backgroundPresetGalleryPickerMediator =
       [[HomeCustomizationBackgroundPresetGalleryPickerMediator alloc]
-          initWithImageFetcherService:imageFetcherService
-           homeBackgroundImageService:homeBackgroundImageService];
+             initWithImageFetcherService:imageFetcherService
+              homeBackgroundImageService:homeBackgroundImageService
+          backgroundCustomizationService:homeBackgroundCustomizationService];
 
   [self
       addItemWithTitle:
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.h b/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.h
index daa47c3..79dfe47a 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.h
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.h
@@ -15,6 +15,7 @@
 
 @protocol HomeCustomizationBackgroundPresetGalleryPickerConsumer;
 class HomeBackgroundImageService;
+class HomeBackgroundCustomizationService;
 
 // A mediator that generates and configures background presets for the Home
 // customization screen, and communicates them to a consumer.
@@ -27,7 +28,9 @@
                     (image_fetcher::ImageFetcherService*)imageFetcherService
                  homeBackgroundImageService:
                      (HomeBackgroundImageService*)homeBackgroundImageService
-    NS_DESIGNATED_INITIALIZER;
+             backgroundCustomizationService:
+                 (HomeBackgroundCustomizationService*)
+                     backgroundCustomizationService NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.mm
index 9f6ede9..3122213f4 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.mm
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_preset_gallery_picker_mediator.mm
@@ -13,6 +13,7 @@
 #import "components/image_fetcher/core/image_fetcher_service.h"
 #import "ios/chrome/browser/home_customization/model/background_collection_configuration.h"
 #import "ios/chrome/browser/home_customization/model/background_customization_configuration_item.h"
+#import "ios/chrome/browser/home_customization/model/home_background_customization_service.h"
 #import "ios/chrome/browser/home_customization/model/home_background_image_service.h"
 #import "ios/chrome/browser/home_customization/ui/home_customization_background_preset_gallery_picker_consumer.h"
 #import "ui/gfx/image/image.h"
@@ -23,6 +24,8 @@
   raw_ptr<image_fetcher::ImageFetcher> _imageFetcher;
   // The service that provides the background images.
   raw_ptr<HomeBackgroundImageService> _homeBackgroundImageService;
+  // Used to get and observe the background state.
+  raw_ptr<HomeBackgroundCustomizationService> _backgroundCustomizationService;
 }
 
 @end
@@ -32,12 +35,16 @@
 - (instancetype)initWithImageFetcherService:
                     (image_fetcher::ImageFetcherService*)imageFetcherService
                  homeBackgroundImageService:
-                     (HomeBackgroundImageService*)homeBackgroundImageService {
+                     (HomeBackgroundImageService*)homeBackgroundImageService
+             backgroundCustomizationService:
+                 (HomeBackgroundCustomizationService*)
+                     backgroundCustomizationService {
   self = [super init];
   if (self) {
     _imageFetcher = imageFetcherService->GetImageFetcher(
         image_fetcher::ImageFetcherConfig::kDiskCacheOnly);
     _homeBackgroundImageService = homeBackgroundImageService;
+    _backgroundCustomizationService = backgroundCustomizationService;
   }
   return self;
 }
@@ -87,6 +94,11 @@
   NSMutableArray<BackgroundCollectionConfiguration*>* collectionConfigurations =
       [NSMutableArray array];
 
+  std::optional<sync_pb::NtpCustomBackground> background =
+      _backgroundCustomizationService->GetCurrentCustomBackground();
+
+  NSString* selectedBackgroundId = nil;
+
   for (const auto& [collectionName, collectionImages] : collectionMap) {
     // Create a new section for the collection.
     BackgroundCollectionConfiguration* section =
@@ -99,15 +111,17 @@
           [[BackgroundCustomizationConfigurationItem alloc]
               initWithCollectionImage:image];
       [imageConfigurations addObject:config];
+
+      if (background && image.image_url == background->url()) {
+        selectedBackgroundId = config.configurationID;
+      }
     }
     section.configurations = [NSArray arrayWithArray:imageConfigurations];
     [collectionConfigurations addObject:section];
   }
 
-  // TODO(crbug.com/418005063): Fetch the selected background ID from local
-  // storage.
   [_consumer setBackgroundCollectionConfigurations:collectionConfigurations
-                              selectedBackgroundId:nil];
+                              selectedBackgroundId:selectedBackgroundId];
 }
 
 @end
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
index 576a9898..bf7c3932 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
+++ b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h
@@ -5,6 +5,10 @@
 #ifndef IOS_CHROME_BROWSER_INTELLIGENCE_BWG_METRICS_BWG_METRICS_H_
 #define IOS_CHROME_BROWSER_INTELLIGENCE_BWG_METRICS_BWG_METRICS_H_
 
+namespace base {
+class TimeDelta;
+}  // namespace base
+
 // UMA histogram key for IOS.Gemini.Eligibility.
 extern const char kEligibilityHistogram[];
 
@@ -42,4 +46,10 @@
 // UMA histogram key for IOS.Gemini.StartupTime.NotFirstRun.
 extern const char kStartupTimeNoFREHistogram[];
 
+// UMA histogram key for IOS.Gemini.Session.Time.
+extern const char kBWGSessionTimeHistogram[];
+
+// Records the duration of a Gemini session.
+void RecordBWGSessionTime(base::TimeDelta session_duration);
+
 #endif  // IOS_CHROME_BROWSER_INTELLIGENCE_BWG_METRICS_BWG_METRICS_H_
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
index 31252f4..49bceb45 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
+++ b/ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h"
 
 #import "base/metrics/histogram_functions.h"
+#import "base/time/time.h"
 
 const char kEligibilityHistogram[] = "IOS.Gemini.Eligibility";
 
@@ -20,6 +21,8 @@
 
 const char kStartupTimeNoFREHistogram[] = "IOS.Gemini.StartupTime.NotFirstRun";
 
+const char kBWGSessionTimeHistogram[] = "IOS.Gemini.Session.Time";
+
 void RecordFREPromoAction(IOSGeminiFREAction action) {
   base::UmaHistogramEnumeration(kPromoActionHistogram, action);
 }
@@ -27,3 +30,7 @@
 void RecordFREConsentAction(IOSGeminiFREAction action) {
   base::UmaHistogramEnumeration(kPromoActionHistogram, action);
 }
+
+void RecordBWGSessionTime(base::TimeDelta session_duration) {
+  base::UmaHistogramTimes(kBWGSessionTimeHistogram, session_duration);
+}
diff --git a/ios/chrome/browser/intelligence/bwg/model/BUILD.gn b/ios/chrome/browser/intelligence/bwg/model/BUILD.gn
index 9209a35..623eaf7f 100644
--- a/ios/chrome/browser/intelligence/bwg/model/BUILD.gn
+++ b/ios/chrome/browser/intelligence/bwg/model/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     ":tab_helper",
     "//ios/chrome/app/strings:ios_strings",
+    "//ios/chrome/browser/intelligence/bwg/metrics",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/web_state_list",
@@ -43,6 +44,7 @@
     "//ios/chrome/browser/intelligence/proto_wrappers",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser",
+    "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_browser_agent.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_browser_agent.mm
index 8c4b3e74..8fc9223 100644
--- a/ios/chrome/browser/intelligence/bwg/model/bwg_browser_agent.mm
+++ b/ios/chrome/browser/intelligence/bwg/model/bwg_browser_agent.mm
@@ -7,6 +7,7 @@
 #import "base/strings/sys_string_conversions.h"
 #import "components/favicon/ios/web_favicon_driver.h"
 #import "components/optimization_guide/proto/features/common_quality_data.pb.h"
+#import "components/prefs/pref_service.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_configuration.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_link_opening_delegate.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_link_opening_handler.h"
@@ -17,6 +18,7 @@
 #import "ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
+#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/shared/public/commands/bwg_commands.h"
@@ -31,14 +33,15 @@
 
 namespace {
 
-// Helper to convert PageContextWrapperError to BWGPageContextState.
-ios::provider::BWGPageContextState BWGPageContextFromPageContextWrapperError(
+// Helper to convert PageContextWrapperError to BWGPageContextComputationState.
+ios::provider::BWGPageContextComputationState
+BWGPageContextComputationStateFromPageContextWrapperError(
     PageContextWrapperError error) {
   switch (error) {
     case PageContextWrapperError::kForceDetachError:
-      return ios::provider::BWGPageContextState::kProtected;
+      return ios::provider::BWGPageContextComputationState::kProtected;
     default:
-      return ios::provider::BWGPageContextState::kError;
+      return ios::provider::BWGPageContextComputationState::kError;
   }
 }
 
@@ -99,19 +102,30 @@
   config.BWGLocationPermissionState =
       ios::provider::BWGLocationPermissionState::kUnknown;
 
-  // Set the page context and page state for the current web state. If the page
-  // context is unavailable, the page state represents the error.
+  // Set the page context itself and page context computation state for the
+  // current web state.
   std::unique_ptr<optimization_guide::proto::PageContext> pageContext = nullptr;
   if (expected_page_context.has_value()) {
     pageContext = std::move(expected_page_context.value());
-    config.BWGPageContextState =
-        ios::provider::BWGPageContextState::kSuccessfullyAttached;
+    config.BWGPageContextComputationState =
+        ios::provider::BWGPageContextComputationState::kSuccess;
   } else {
-    config.BWGPageContextState = BWGPageContextFromPageContextWrapperError(
-        expected_page_context.error());
+    config.BWGPageContextComputationState =
+        BWGPageContextComputationStateFromPageContextWrapperError(
+            expected_page_context.error());
   }
   config.uniquePageContext = std::move(pageContext);
 
+  // Set the page context attachment state.
+  PrefService* pref_service = browser_->GetProfile()->GetPrefs();
+  if (!pref_service->GetBoolean(prefs::kIOSBWGPageContentSetting)) {
+    config.BWGPageContextAttachmentState =
+        ios::provider::BWGPageContextAttachmentState::kUserDisabled;
+  } else {
+    config.BWGPageContextAttachmentState =
+        ios::provider::BWGPageContextAttachmentState::kAttached;
+  }
+
   // Use the cached favicon of the web state. If it's not available, use a
   // default favicon instead.
   gfx::Image cached_favicon =
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
index 8f286383..8e0351c 100644
--- a/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
+++ b/ios/chrome/browser/intelligence/bwg/model/bwg_session_handler.mm
@@ -6,6 +6,7 @@
 
 #import "base/strings/string_number_conversions.h"
 #import "base/strings/sys_string_conversions.h"
+#import "ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_session_delegate.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_tab_helper.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
@@ -15,6 +16,8 @@
 @implementation BWGSessionHandler {
   // The associated WebStateList.
   raw_ptr<WebStateList> _webStateList;
+  // Session start time for duration tracking.
+  base::TimeTicks _sessionStartTime;
 }
 
 - (instancetype)initWithWebStateList:(WebStateList*)webStateList {
@@ -36,12 +39,21 @@
                        serverID:(NSString*)serverID {
   [self updateSessionWithClientID:clientID serverID:serverID];
   [self setSessionActive:YES clientID:clientID];
+  // Start session timer.
+  _sessionStartTime = base::TimeTicks::Now();
 }
 
 - (void)UIDidDisappearWithClientID:(NSString*)clientID
                           serverID:(NSString*)serverID {
   [_BWGHandler dismissBWGFlowFromSession];
   [self setSessionActive:NO clientID:clientID];
+  // Record session duration.
+  if (!_sessionStartTime.is_null()) {
+    base::TimeDelta session_duration =
+        base::TimeTicks::Now() - _sessionStartTime;
+    RecordBWGSessionTime(session_duration);
+    _sessionStartTime = base::TimeTicks();
+  }
 }
 
 - (void)responseReceivedWithClientID:(NSString*)clientID
diff --git a/ios/chrome/browser/intelligence/features/features.h b/ios/chrome/browser/intelligence/features/features.h
index d1e94fd..166fba0 100644
--- a/ios/chrome/browser/intelligence/features/features.h
+++ b/ios/chrome/browser/intelligence/features/features.h
@@ -78,4 +78,11 @@
 // Returns true if the precise location setting is enabled.
 bool IsBWGPreciseLocationEnabled();
 
+// Feature flag controlling the inclusion of anchor tags (links) in Page
+// Context.
+BASE_DECLARE_FEATURE(kPageContextAnchorTags);
+
+// Returns true if the anchor tags are enabled in Page Context.
+bool IsPageContextAnchorTagsEnabled();
+
 #endif  // IOS_CHROME_BROWSER_INTELLIGENCE_FEATURES_FEATURES_H_
diff --git a/ios/chrome/browser/intelligence/features/features.mm b/ios/chrome/browser/intelligence/features/features.mm
index 7eb04f0..4f187510 100644
--- a/ios/chrome/browser/intelligence/features/features.mm
+++ b/ios/chrome/browser/intelligence/features/features.mm
@@ -113,3 +113,11 @@
   CHECK(IsPageActionMenuEnabled());
   return base::FeatureList::IsEnabled(kBWGPreciseLocation);
 }
+
+BASE_FEATURE(kPageContextAnchorTags,
+             "PageContextAnchorTags",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+bool IsPageContextAnchorTagsEnabled() {
+  return base::FeatureList::IsEnabled(kPageContextAnchorTags);
+}
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
index c78407e..5f47715 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
@@ -11,6 +11,8 @@
   ]
   deps = [
     "//components/prefs",
+    "//components/search",
+    "//components/search_engines",
     "//components/signin/public/identity_manager",
     "//ios/chrome/browser/dom_distiller/model",
     "//ios/chrome/browser/intelligence/bwg/coordinator",
@@ -25,6 +27,7 @@
     "//ios/chrome/browser/reader_mode/model",
     "//ios/chrome/browser/reader_mode/model:features",
     "//ios/chrome/browser/reader_mode/ui:options",
+    "//ios/chrome/browser/search_engines/model:template_url_service_factory",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/DEPS b/ios/chrome/browser/intelligence/page_action_menu/coordinator/DEPS
index 124efda..ea729e7 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/DEPS
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/DEPS
@@ -2,4 +2,5 @@
   "+ios/chrome/browser/dom_distiller/model/distiller_service_factory.h",
   "+ios/chrome/browser/lens_overlay/coordinator/lens_overlay_availability.h",
   "+ios/chrome/browser/reader_mode",
-]
\ No newline at end of file
+  "+ios/chrome/browser/search_engines/model/template_url_service_factory.h",
+]
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
index 919420bd..768ccba 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.h"
 
+#import "components/search/search.h"
+#import "components/search_engines/template_url_service.h"
 #import "ios/chrome/browser/dom_distiller/model/distiller_service_factory.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_service.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.h"
@@ -18,6 +20,7 @@
 #import "ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.h"
 #import "ios/chrome/browser/reader_mode/ui/reader_mode_options_controls_view.h"
 #import "ios/chrome/browser/reader_mode/ui/reader_mode_options_view_controller.h"
+#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
@@ -92,7 +95,9 @@
         HandlerForProtocol(self.browser->GetCommandDispatcher(), BWGCommands);
   }
 
-  if (IsLensOverlayAvailable(self.profile->GetPrefs())) {
+  if (IsLensOverlayAvailable(self.profile->GetPrefs()) &&
+      search::DefaultSearchProviderIsGoogle(
+          ios::TemplateURLServiceFactory::GetForProfile(self.profile))) {
     _viewController.lensOverlayHandler = HandlerForProtocol(
         self.browser->GetCommandDispatcher(), LensOverlayCommands);
   }
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
index bcf4a1f..029e930f 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
+++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
@@ -500,7 +500,7 @@
   UIBackgroundConfiguration* backgroundConfig =
       [UIBackgroundConfiguration clearConfiguration];
   backgroundConfig.backgroundColor =
-      [[UIColor colorNamed:kPrimaryBackgroundColor]
+      [[UIColor colorNamed:kGroupedSecondaryBackgroundColor]
           colorWithAlphaComponent:kSmallButtonOpacity];
   backgroundConfig.cornerRadius = kButtonsCornerRadius;
 
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/BUILD.gn b/ios/chrome/browser/intelligence/proto_wrappers/BUILD.gn
index d397d2c6..4a82254d 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/BUILD.gn
+++ b/ios/chrome/browser/intelligence/proto_wrappers/BUILD.gn
@@ -16,6 +16,7 @@
     "//components/optimization_guide:optimization_guide_buildflags",
     "//components/optimization_guide/core:page_content",
     "//components/optimization_guide/proto:optimization_guide_proto",
+    "//ios/chrome/browser/intelligence/features",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/snapshots/model",
     "//ios/public/provider/chrome/browser/bwg:bwg_api",
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm
index e2f67d8..09026f390 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm
+++ b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm
@@ -22,6 +22,7 @@
 #import "base/token.h"
 #import "components/optimization_guide/core/page_content_proto_serializer.h"
 #import "components/optimization_guide/proto/features/common_quality_data.pb.h"
+#import "ios/chrome/browser/intelligence/features/features.h"
 #import "ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper_metrics.h"
 #import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h"
 #import "ios/public/provider/chrome/browser/bwg/bwg_api.h"
@@ -52,6 +53,18 @@
 // string.
 constexpr const char kFrameTitleDictKey[] = "title";
 
+// The key for the links of the frame in the JavaScript object. The value is an
+// array of objects.
+constexpr const char kFrameLinksDictKey[] = "links";
+
+// The key for a link's HREF/URL field in the JavaScript object. The value is a
+// string.
+constexpr const char kLinkHREFDictKey[] = "href";
+
+// The key for a link's innerText in the JavaScript object. The value is a
+// string.
+constexpr const char kLinkTextDictKey[] = "linkText";
+
 // The JavaScript to be executed on each WebState's WebFrames, which retrieves
 // the innerText of the document body, and recursively traverses through
 // same-origin nested iframes to retrieve their innerTexts as well, constructing
@@ -65,7 +78,8 @@
 (() => {
     // Checks whether the PageContext should be detached.
     const shouldDetachPageContext = () => {
-        $1
+      // PageContext detachment logic injected below.
+      $1
     };
 
     // If the PageContext should be detached, early return.
@@ -112,17 +126,41 @@
                 nonceAttributeValue) : null;
         });
 
-        return {
+        const result = {
             currentNodeInnerText: node.innerText,
             children: childNodeInnerTexts.filter(item => item !== null),
             sourceURL: frameURL,
             title: frameTitle,
         };
+
+        // Anchor tag retrieval logic injected below.
+        $2
+
+        return result;
     };
 
-    return constructSameOriginInnerTextTree(document.body, window.location.href, document.title, "$2");
+    return constructSameOriginInnerTextTree(document.body, window.location.href, document.title, "$3");
 })();
   )DELIM";
+
+// The JavaScript to be executed in each WebFrame which gets all of a frame's
+// anchor tags and adds them to an array with their corresponding URL and
+// innerText. Injected into the main script.
+constexpr const char16_t* kAnchorTagsJavaScript = uR"DELIM(
+// Add all the frame's anchor tags to a links array with their HREF/URL and
+// innerText.
+const linksArray = [];
+const anchorElements = node.querySelectorAll('a[href]');
+anchorElements.forEach((anchor) => {
+    linksArray.push({
+        href: anchor.href,
+        linkText: anchor.innerText
+    });
+});
+
+result.links = linksArray;
+  )DELIM";
+
 }  // namespace
 
 // TODO(crbug.com/424258248): Add a timeout for the execution of the async tasks
@@ -368,10 +406,13 @@
   // random token as nonce to differentiate between runs/executions.
   base::Token nonce = base::Token::CreateRandom();
   std::u16string nonceString = base::UTF8ToUTF16(nonce.ToString());
+  std::u16string maybeAnchorTagsJavaScript =
+      IsPageContextAnchorTagsEnabled() ? kAnchorTagsJavaScript : u"";
   std::u16string script = base::ReplaceStringPlaceholders(
       kInnerTextTreeJavaScript,
       base::span<const std::u16string>(
-          {ios::provider::GetPageContextShouldDetachScript(), nonceString}),
+          {ios::provider::GetPageContextShouldDetachScript(),
+           maybeAnchorTagsJavaScript, nonceString}),
       nullptr);
 
   // Execute the JavaScript on the main WebFrame first and pass in the callback
@@ -590,6 +631,13 @@
   [self populateTextInfoNodeWithValue:value
                                origin:origin
                            parentNode:_rootAPCNode->mutable_root_node()];
+
+  // Set its children anchor nodes.
+  if (IsPageContextAnchorTagsEnabled()) {
+    [self
+        populateAnchorNodeChildrenWithValue:value
+                                 parentNode:_rootAPCNode->mutable_root_node()];
+  }
 }
 
 //  Populate a FrameData node with the correct values.
@@ -680,6 +728,11 @@
                                origin:origin
                            parentNode:childRootNode];
 
+  // Create the children anchor nodes.
+  if (IsPageContextAnchorTagsEnabled()) {
+    [self populateAnchorNodeChildrenWithValue:value parentNode:childRootNode];
+  }
+
   // Recursively populate the ContentNode subtree for any children iframes.
   const base::Value::List* childrenFrames =
       value->GetDict().FindList(kChildrenFramesDictKey);
@@ -694,6 +747,69 @@
   }
 }
 
+// Populate all anchor tags as AnchorData nodes which are direct children of
+// `parentNode`.
+- (void)populateAnchorNodeChildrenWithValue:(const base::Value*)value
+                                 parentNode:
+                                     (optimization_guide::proto::ContentNode*)
+                                         parentNode {
+  if (!value || !value->is_dict() || !parentNode) {
+    return;
+  }
+
+  const base::Value::List* links =
+      value->GetDict().FindList(kFrameLinksDictKey);
+  if (!links || links->empty()) {
+    return;
+  }
+
+  for (const auto& linkValue : *links) {
+    [self populateAnchorNodeWithValue:&linkValue parentNode:parentNode];
+  }
+}
+
+// Creates an AnchorData node (with the corresponding URL) with one child
+// TextInfo node (with the corresponding innerText). Set the AnchorData node as
+// direct child of `parentNode`.
+- (void)populateAnchorNodeWithValue:(const base::Value*)linkData
+                         parentNode:(optimization_guide::proto::ContentNode*)
+                                        parentNode {
+  if (!linkData || !linkData->is_dict() || !parentNode) {
+    return;
+  }
+
+  const std::string* href = linkData->GetDict().FindString(kLinkHREFDictKey);
+  if (!href || href->empty()) {
+    return;
+  }
+
+  // Create the anchor node.
+  optimization_guide::proto::ContentNode* anchorNode =
+      parentNode->add_children_nodes();
+  anchorNode->mutable_content_attributes()->set_attribute_type(
+      optimization_guide::proto::CONTENT_ATTRIBUTE_ANCHOR);
+
+  // Set the anchor data (the HREF).
+  anchorNode->mutable_content_attributes()->mutable_anchor_data()->set_url(
+      *href);
+
+  // Create a child text node for the anchor's innerText.
+  const std::string* linkText =
+      linkData->GetDict().FindString(kLinkTextDictKey);
+  if (!linkText || linkText->empty() ||
+      base::TrimWhitespaceASCII(*linkText, base::TRIM_ALL).empty()) {
+    return;
+  }
+
+  // Set the child text node's text value.
+  optimization_guide::proto::ContentNode* textNode =
+      anchorNode->add_children_nodes();
+  textNode->mutable_content_attributes()->set_attribute_type(
+      optimization_guide::proto::CONTENT_ATTRIBUTE_TEXT);
+  textNode->mutable_content_attributes()->mutable_text_data()->set_text_content(
+      *linkText);
+}
+
 // Stop the highlighting of text.
 - (void)stopTextHighlighting {
   if (!_webState) {
diff --git a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent.mm b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent.mm
index eba59ee..1d28130 100644
--- a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent.mm
+++ b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent.mm
@@ -130,6 +130,8 @@
 - (void)updateOffCyclePromoRegistration {
   if (IsDefaultBrowserOffCyclePromoEnabled() &&
       !IsChromeLikelyDefaultBrowser()) {
+    // The off-cycle promo replaces the generic one.
+    self.promosManager->DeregisterPromo(promos_manager::Promo::DefaultBrowser);
     self.promosManager->RegisterPromoForSingleDisplay(
         promos_manager::Promo::DefaultBrowserOffCycle);
   } else {
@@ -300,7 +302,6 @@
     return;
   }
 
-  [self updateOffCyclePromoRegistration];
   [self updatePostRestorePromoRegistration];
   [self updatePostDefaultAbandonmentPromoRegistration];
   [self updateAllTabsPromoRegistration];
@@ -311,6 +312,9 @@
   } else {
     [self updateGenericPromoRegistration];
   }
+  // The off-cycle promo registration must be checked after the generic promo
+  // because the off-cycle promo can deregister the generic one.
+  [self updateOffCyclePromoRegistration];
 
   [self notifyFETSigninStatus];
   [self maybeSetTriggerCriteriaExperimentStartTimestamp];
diff --git a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm
index 7a9a762..12867ce 100644
--- a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm
+++ b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm
@@ -552,7 +552,14 @@
        TestDefaultBrowserOffCyclePromoRegistration) {
   scoped_feature_list_.InitWithFeatures({kIOSDefaultBrowserOffCyclePromo},
                                         {kEnableReaderModeDefaultBrowserPromo});
-  VerifyPromoRegistration({promos_manager::Promo::DefaultBrowserOffCycle});
+  if (@available(iOS 18.3, *)) {
+    VerifyPromoRegistration({promos_manager::Promo::DefaultBrowserOffCycle});
+    EXPECT_CALL(*promos_manager_.get(),
+                DeregisterPromo(promos_manager::Promo::DefaultBrowser))
+        .Times(1);
+  } else {
+    VerifyPromoDeregistration({promos_manager::Promo::DefaultBrowserOffCycle});
+  }
 
   scene_state_.activationLevel = SceneActivationLevelForegroundActive;
   Mock::VerifyAndClearExpectations(promos_manager_.get());
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm
index 1ed3634..517066b 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm
@@ -962,6 +962,7 @@
 
     _voiceAndLensDivider.backgroundColor = colorPalette.omniboxIconDividerColor;
     _miaAndVoiceDivider.backgroundColor = colorPalette.omniboxIconDividerColor;
+    _miaAnimationView.alpha = 0;
   } else {
     [_fakeLocationBar setStartColor:FakeboxTopColor()
                            endColor:FakeboxBottomColor()];
@@ -983,6 +984,8 @@
 
     _voiceAndLensDivider.backgroundColor = [UIColor colorNamed:kGrey600Color];
     _miaAndVoiceDivider.backgroundColor = [UIColor colorNamed:kGrey600Color];
+    _miaAnimationView.alpha =
+        MIAAnimationOpacityForScrollProgress(_lastAnimationPercent);
   }
 }
 
diff --git a/ios/chrome/browser/passwords/model/features.h b/ios/chrome/browser/passwords/model/features.h
index 1669e67..1adb447 100644
--- a/ios/chrome/browser/passwords/model/features.h
+++ b/ios/chrome/browser/passwords/model/features.h
@@ -14,4 +14,7 @@
 // enabled by default.
 BASE_DECLARE_FEATURE(kPasswordManagerEnableCrowdsourcingUploads);
 
+// Whether the user should see the import from Safari workflow.
+bool ShouldShowSafariImportWorkflow();
+
 #endif  // IOS_CHROME_BROWSER_PASSWORDS_MODEL_FEATURES_H_
diff --git a/ios/chrome/browser/passwords/model/features.mm b/ios/chrome/browser/passwords/model/features.mm
index 332431c..452c60e 100644
--- a/ios/chrome/browser/passwords/model/features.mm
+++ b/ios/chrome/browser/passwords/model/features.mm
@@ -13,3 +13,11 @@
 BASE_FEATURE(kPasswordManagerEnableCrowdsourcingUploads,
              "PasswordManagerEnableCrowdsourcingUploads",
              base::FEATURE_DISABLED_BY_DEFAULT);
+
+bool ShouldShowSafariImportWorkflow() {
+  // Safari export is not available on iOS versions earlier than 18.2.
+  if (@available(iOS 18.2, *)) {
+    return base::FeatureList::IsEnabled(kImportPasswordsFromSafari);
+  }
+  return false;
+}
diff --git a/ios/chrome/browser/promos_manager/ui_bundled/promos_manager_coordinator.mm b/ios/chrome/browser/promos_manager/ui_bundled/promos_manager_coordinator.mm
index 5d6badb..92abd34 100644
--- a/ios/chrome/browser/promos_manager/ui_bundled/promos_manager_coordinator.mm
+++ b/ios/chrome/browser/promos_manager/ui_bundled/promos_manager_coordinator.mm
@@ -645,7 +645,7 @@
   }
 
   // Safari Import remind me later handler.
-  if (base::FeatureList::IsEnabled(kImportPasswordsFromSafari)) {
+  if (ShouldShowSafariImportWorkflow()) {
     _displayHandlerPromos[promos_manager::Promo::SafariImportRemindMeLater] =
         [[SafariDataImportReminderPromoDisplayHandler alloc]
             initWithApplicationCommandsHandler:_applicationCommandHandler
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_browser_agent.mm b/ios/chrome/browser/reader_mode/model/reader_mode_browser_agent.mm
index 8b335d8..07b09a9 100644
--- a/ios/chrome/browser/reader_mode/model/reader_mode_browser_agent.mm
+++ b/ios/chrome/browser/reader_mode/model/reader_mode_browser_agent.mm
@@ -45,6 +45,7 @@
 }
 
 void ReaderModeBrowserAgent::ShowReaderModeUI(BOOL animated) {
+  crash_keys::SetCurrentlyInReaderMode(true);
   [delegate_ readerModeBrowserAgent:this showContentAnimated:animated];
 
   __weak id<ReaderModeChipCommands> weak_reader_mode_chip_handler =
@@ -65,6 +66,7 @@
 }
 
 void ReaderModeBrowserAgent::HideReaderModeUI(BOOL animated) {
+  crash_keys::SetCurrentlyInReaderMode(false);
   id<ReaderModeChipCommands> reader_mode_chip_handler = HandlerForProtocol(
       browser_->GetCommandDispatcher(), ReaderModeChipCommands);
   [reader_mode_chip_handler hideReaderModeChip];
@@ -139,7 +141,6 @@
   // If Reader mode becomes active in the active WebState, show the Reader mode
   // UI.
   ShowReaderModeUI(/* animated= */ YES);
-  crash_keys::SetCurrentlyInReaderMode(true);
 }
 
 void ReaderModeBrowserAgent::ReaderModeWebStateWillBecomeUnavailable(
@@ -151,7 +152,6 @@
   const bool animated =
       reason == ReaderModeDeactivationReason::kUserDeactivated;
   HideReaderModeUI(animated);
-  crash_keys::SetCurrentlyInReaderMode(false);
 }
 
 void ReaderModeBrowserAgent::ReaderModeDistillationFailed(
diff --git a/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm b/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm
index cb150495..d6e52803 100644
--- a/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm
+++ b/ios/chrome/browser/reader_mode/ui/reader_mode_egtest.mm
@@ -32,6 +32,17 @@
 // components/dom_distiller/core/javascript/dom_distiller_viewer.js.
 constexpr double kReaderModeBaseFontSize = 16.0;
 
+// Return the number of links on the page.
+double CountNumLinks() {
+  NSString* js =
+      @"(function() { return document.querySelectorAll('a').length; })();";
+  base::Value result = [ChromeEarlGrey evaluateJavaScript:js];
+  GREYAssertTrue(result.is_double(),
+                 @"The javascript result should be a double");
+
+  return result.GetDouble();
+}
+
 // Verifies that the theme and font have been set as expected in the document
 // body.
 void ExpectBodyHasThemeAndFont(const std::string& theme,
@@ -834,4 +845,25 @@
   [ChromeEarlGrey waitForSufficientlyVisibleElementWithMatcher:snackbarMatcher];
 }
 
+// Tests that non-http links are removed from Reading mode.
+- (void)testNonHttpsLinksRemovedFromReadingMode {
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/article.html")];
+  [ChromeEarlGrey waitForPageToFinishLoading];
+
+  EXPECT_EQ(4, CountNumLinks());
+
+  // Wait for the contextual panel entrypoint to appear.
+  id<GREYMatcher> entrypoint = chrome_test_util::ButtonWithAccessibilityLabelId(
+      IDS_IOS_CONTEXTUAL_PANEL_READER_MODE_MODEL_ENTRYPOINT_MESSAGE);
+  [ChromeEarlGrey waitForSufficientlyVisibleElementWithMatcher:entrypoint];
+
+  // Tap the entrypoint to trigger distillation.
+  [[EarlGrey selectElementWithMatcher:entrypoint] performAction:grey_tap()];
+
+  [ChromeEarlGrey
+      waitForSufficientlyVisibleElementWithMatcher:
+          grey_accessibilityID(kReaderModeViewAccessibilityIdentifier)];
+  EXPECT_EQ(1, CountNumLinks());
+}
+
 @end
diff --git a/ios/chrome/browser/safari_data_import/coordinator/BUILD.gn b/ios/chrome/browser/safari_data_import/coordinator/BUILD.gn
index d2b9ccf2..d6252c9 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/BUILD.gn
+++ b/ios/chrome/browser/safari_data_import/coordinator/BUILD.gn
@@ -68,6 +68,7 @@
     "//ios/chrome/browser/affiliations/model",
     "//ios/chrome/browser/autofill/model",
     "//ios/chrome/browser/bookmarks/model",
+    "//ios/chrome/browser/favicon/model",
     "//ios/chrome/browser/first_run/ui_bundled:constants",
     "//ios/chrome/browser/history/model",
     "//ios/chrome/browser/passwords/model:store_factory",
diff --git a/ios/chrome/browser/safari_data_import/coordinator/DEPS b/ios/chrome/browser/safari_data_import/coordinator/DEPS
index 7c57ebb..63f5459 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/DEPS
+++ b/ios/chrome/browser/safari_data_import/coordinator/DEPS
@@ -2,6 +2,7 @@
   "+ios/chrome/browser/affiliations/model",
   "+ios/chrome/browser/autofill/model",
   "+ios/chrome/browser/bookmarks/model",
+  "+ios/chrome/browser/favicon/model",
   "+ios/chrome/browser/feature_engagement/model",
   "+ios/chrome/browser/first_run/ui_bundled/first_run_constants.h",
   "+ios/chrome/browser/history/model",
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
index c4b37c736..699256d 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h"
 #import "ios/chrome/browser/autofill/model/personal_data_manager_factory.h"
 #import "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h"
+#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h"
 #import "ios/chrome/browser/history/model/history_service_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_account_password_store_factory.h"
 #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h"
@@ -133,6 +134,8 @@
         ReadingListModelFactory::GetForProfile(profile);
     syncer::SyncService* syncService =
         SyncServiceFactory::GetForProfile(profile);
+    FaviconLoader* faviconLoader =
+        IOSChromeFaviconLoaderFactory::GetForProfile(profile);
     /// Initialize mediator.
     _mediator = [[SafariDataImportImportMediator alloc]
         initWithSavedPasswordsPresenter:std::move(savedPasswordsPresenter)
@@ -141,7 +144,8 @@
                          historyService:historyService
                           bookmarkModel:bookmarkModel
                        readingListModel:readingListModel
-                            syncService:syncService];
+                            syncService:syncService
+                          faviconLoader:faviconLoader];
     _mediator.importStageTransitionHandler = self;
     _mediator.itemConsumer = _tableView;
   }
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h
index e04074c..3f81f6b 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h
@@ -18,6 +18,7 @@
 namespace bookmarks {
 class BookmarkModel;
 }
+class FaviconLoader;
 namespace history {
 class HistoryService;
 }
@@ -55,6 +56,7 @@
                       bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
                    readingListModel:(ReadingListModel*)readingListModel
                         syncService:(syncer::SyncService*)syncService
+                      faviconLoader:(FaviconLoader*)faviconLoader
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm
index d53c714..176efd2fc 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm
@@ -6,15 +6,26 @@
 
 #import "base/apple/foundation_util.h"
 #import "base/check.h"
+#import "base/strings/sys_string_conversions.h"
 #import "components/application_locale_storage/application_locale_storage.h"
 #import "components/user_data_importer/ios/ios_bookmark_parser.h"
 #import "components/user_data_importer/utility/safari_data_importer.h"
+#import "ios/chrome/browser/favicon/model/favicon_loader.h"
 #import "ios/chrome/browser/safari_data_import/model/ios_safari_data_import_client.h"
+#import "ios/chrome/browser/safari_data_import/public/password_import_item.h"
+#import "ios/chrome/browser/safari_data_import/public/password_import_item_favicon_data_source.h"
 #import "ios/chrome/browser/safari_data_import/public/safari_data_import_stage.h"
 #import "ios/chrome/browser/safari_data_import/public/safari_data_item.h"
 #import "ios/chrome/browser/safari_data_import/public/safari_data_item_consumer.h"
 #import "ios/chrome/browser/safari_data_import/ui/safari_data_import_import_stage_transition_handler.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ui/gfx/favicon_size.h"
+#import "url/gurl.h"
+
+@interface SafariDataImportImportMediator () <
+    PasswordImportItemFaviconDataSource>
+
+@end
 
 @implementation SafariDataImportImportMediator {
   /// The importer instance and the client.
@@ -23,6 +34,8 @@
   /// If `YES`, the import client is configured; otherwise it needs to be
   /// configured.
   BOOL _importClientReady;
+  /// Favicon loader for password items.
+  raw_ptr<FaviconLoader> _faviconLoader;
   /// The `SavedPasswordsPresenter` instance being used by the imported. Needs
   /// to be kept alive in the duration of the importer.
   std::unique_ptr<password_manager::SavedPasswordsPresenter>
@@ -43,9 +56,11 @@
                      historyService:(history::HistoryService*)historyService
                       bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
                    readingListModel:(ReadingListModel*)readingListModel
-                        syncService:(syncer::SyncService*)syncService {
+                        syncService:(syncer::SyncService*)syncService
+                      faviconLoader:(FaviconLoader*)faviconLoader {
   self = [super init];
   if (self) {
+    CHECK(faviconLoader);
     _importClient = std::make_unique<IOSSafariDataImportClient>();
     _savedPasswordsPresenter = std::move(savedPasswordsPresenter);
     _savedPasswordsPresenter->Init();
@@ -57,6 +72,7 @@
         _importClient.get(), _savedPasswordsPresenter.get(),
         paymentsDataManager, historyService, bookmarkModel, readingListModel,
         syncService, std::move(bookmarkParser), locale);
+    _faviconLoader = faviconLoader;
   }
   return self;
 }
@@ -74,11 +90,14 @@
 }
 
 - (NSArray<PasswordImportItem*>*)conflictingPasswords {
-  return _importClient->GetConflictingPasswords();
+  return
+      [self passwordItemsWithFaviconDataSource:_importClient
+                                                   ->GetConflictingPasswords()];
 }
 
 - (NSArray<PasswordImportItem*>*)invalidPasswords {
-  return _importClient->GetInvalidPasswords();
+  return [self
+      passwordItemsWithFaviconDataSource:_importClient->GetInvalidPasswords()];
 }
 
 - (void)disconnect {
@@ -89,6 +108,20 @@
   _disconnected = YES;
 }
 
+#pragma mark - PasswordImportItemFaviconDataSource
+
+- (BOOL)passwordImportItem:(PasswordImportItem*)item
+    loadFaviconAttributesWithCompletion:(ProceduralBlock)completion {
+  GURL url(base::SysNSStringToUTF8(item.url));
+  auto faviconLoadedBlock = ^(FaviconAttributes* attributes) {
+    item.faviconAttributes = attributes;
+    completion();
+  };
+  _faviconLoader->FaviconForPageUrlOrHost(url, gfx::kFaviconSize,
+                                          faviconLoadedBlock);
+  return YES;
+}
+
 #pragma mark - SafariDataImportPasswordConflictMutator
 
 - (void)continueToImportPasswords:(NSArray<NSNumber*>*)passwordIdentifiers {
@@ -122,17 +155,31 @@
 
 #pragma mark - Private
 
+/// Registers protcols and callbacks to the import client. Only after this
+/// method has been called will the import client work as expected.
 - (void)setUpImportClient {
   if (_importClientReady) {
     return;
   }
   _importClient->SetSafariDataItemConsumer(self.itemConsumer);
-  __weak __typeof(self) weakSelf = self;
+  __weak SafariDataImportImportMediator* weakSelf = self;
   _importClient->RegisterCallbackOnImportFailure(base::BindOnce(^{
-    [weakSelf reset];
-    [weakSelf.importStageTransitionHandler resetToInitialImportStage:NO];
+    __strong SafariDataImportImportMediator* strongSelf = weakSelf;
+    [strongSelf reset];
+    [strongSelf.importStageTransitionHandler resetToInitialImportStage:NO];
   }));
   _importClientReady = YES;
 }
 
+/// Attach favicon loader to each element in `passwords`.
+- (NSArray<PasswordImportItem*>*)passwordItemsWithFaviconDataSource:
+    (NSArray<PasswordImportItem*>*)passwords {
+  NSArray<PasswordImportItem*>* newPasswords =
+      [NSArray arrayWithArray:passwords];
+  for (PasswordImportItem* password in newPasswords) {
+    password.faviconDataSource = self;
+  }
+  return newPasswords;
+}
+
 @end
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
index 7943fa2..b059bdfa 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
@@ -38,7 +38,7 @@
 }
 
 - (void)start {
-  CHECK(base::FeatureList::IsEnabled(kImportPasswordsFromSafari));
+  CHECK(ShouldShowSafariImportWorkflow());
   _viewController = [[SafariDataImportEntryPointViewController alloc] init];
   _viewController.modalInPresentation = YES;
   _viewController.actionHandler = self;
diff --git a/ios/chrome/browser/safari_data_import/public/BUILD.gn b/ios/chrome/browser/safari_data_import/public/BUILD.gn
index 97f40f5..4767c59f 100644
--- a/ios/chrome/browser/safari_data_import/public/BUILD.gn
+++ b/ios/chrome/browser/safari_data_import/public/BUILD.gn
@@ -6,6 +6,7 @@
   sources = [
     "password_import_item.h",
     "password_import_item.mm",
+    "password_import_item_favicon_data_source.h",
     "safari_data_import_stage.h",
     "safari_data_item.h",
     "safari_data_item.mm",
diff --git a/ios/chrome/browser/safari_data_import/public/password_import_item.h b/ios/chrome/browser/safari_data_import/public/password_import_item.h
index ae0cdbb..f0c398a 100644
--- a/ios/chrome/browser/safari_data_import/public/password_import_item.h
+++ b/ios/chrome/browser/safari_data_import/public/password_import_item.h
@@ -7,7 +7,10 @@
 
 #import <UIKit/UIKit.h>
 
+#import "base/ios/block_types.h"
+
 @class FaviconAttributes;
+@protocol PasswordImportItemFaviconDataSource;
 
 /// Matches password_manager::ImportEntry::Status.
 /// Needs to be kept in sync with PasswordManagerImportEntryStatus in
@@ -46,9 +49,6 @@
 /// The website URL.
 @property(nonatomic, readonly, strong) NSString* url;
 
-/// Favicon attributes for the URL.
-@property(nonatomic, readonly, strong) FaviconAttributes* faviconAttributes;
-
 /// The username for the password.
 @property(nonatomic, readonly, strong) NSString* username;
 
@@ -58,7 +58,17 @@
 /// Import status.
 @property(nonatomic, readonly, assign) PasswordImportStatus status;
 
-/// Initialization
+/// Data source for favicon loading. Should be set before
+/// `-loadFaviconWithCompletionHandler` is invoked.
+@property(nonatomic, weak) id<PasswordImportItemFaviconDataSource>
+    faviconDataSource;
+
+/// Favicon attributes for the URL. If current value is `nil`, call
+/// `-loadFaviconWithCompletionHandler` and retrieve the value in the completion
+/// handler.
+@property(nonatomic, strong) FaviconAttributes* faviconAttributes;
+
+/// Initialization.
 - (instancetype)initWithURL:(NSString*)url
                    username:(NSString*)username
                    password:(NSString*)password
@@ -66,9 +76,9 @@
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
-/// Load the favicon with completion handler. Does nothing if a load of the
-/// favicon is already in progress.
-- (void)loadFaviconWithCompletionHandler:(UIAction*)handler;
+/// Loads the favicon with completion handler on the first call to this method.
+/// Does nothing on subsequent calls.
+- (void)loadFaviconWithCompletionHandler:(ProceduralBlock)handler;
 
 @end
 
diff --git a/ios/chrome/browser/safari_data_import/public/password_import_item.mm b/ios/chrome/browser/safari_data_import/public/password_import_item.mm
index 4063c0f..345a795d 100644
--- a/ios/chrome/browser/safari_data_import/public/password_import_item.mm
+++ b/ios/chrome/browser/safari_data_import/public/password_import_item.mm
@@ -4,9 +4,11 @@
 
 #import "ios/chrome/browser/safari_data_import/public/password_import_item.h"
 
+#import "ios/chrome/browser/safari_data_import/public/password_import_item_favicon_data_source.h"
+
 @implementation PasswordImportItem {
-  /// Indicates whether favicon loading is in progress.
-  BOOL _loadingFavicon;
+  /// Indicates whether favicon loading is initiated.
+  BOOL _faviconLoadingInitiated;
 }
 - (instancetype)initWithURL:(NSString*)url
                    username:(NSString*)username
@@ -22,12 +24,13 @@
   return self;
 }
 
-- (void)loadFaviconWithCompletionHandler:(UIAction*)handler {
-  if (_loadingFavicon) {
+- (void)loadFaviconWithCompletionHandler:(ProceduralBlock)handler {
+  if (_faviconLoadingInitiated) {
     return;
   }
-  _loadingFavicon = YES;
-  /// TODO(crbug.com/420703283): Implement favicon attribute loading.
+  _faviconLoadingInitiated =
+      [self.faviconDataSource passwordImportItem:self
+             loadFaviconAttributesWithCompletion:handler];
 }
 
 @end
diff --git a/ios/chrome/browser/safari_data_import/public/password_import_item_favicon_data_source.h b/ios/chrome/browser/safari_data_import/public/password_import_item_favicon_data_source.h
new file mode 100644
index 0000000..e87f61c
--- /dev/null
+++ b/ios/chrome/browser/safari_data_import/public/password_import_item_favicon_data_source.h
@@ -0,0 +1,21 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SAFARI_DATA_IMPORT_PUBLIC_PASSWORD_IMPORT_ITEM_FAVICON_DATA_SOURCE_H_
+#define IOS_CHROME_BROWSER_SAFARI_DATA_IMPORT_PUBLIC_PASSWORD_IMPORT_ITEM_FAVICON_DATA_SOURCE_H_
+
+#import "base/ios/block_types.h"
+
+@class PasswordImportItem;
+
+/// A data source for a password import item's favicon.
+@protocol PasswordImportItemFaviconDataSource
+
+/// Loads `item.faviconAttributes`.
+- (BOOL)passwordImportItem:(PasswordImportItem*)item
+    loadFaviconAttributesWithCompletion:(ProceduralBlock)completion;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_SAFARI_DATA_IMPORT_PUBLIC_PASSWORD_IMPORT_ITEM_FAVICON_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/safari_data_import/ui/safari_data_import_password_conflict_resolution_view_controller.mm b/ios/chrome/browser/safari_data_import/ui/safari_data_import_password_conflict_resolution_view_controller.mm
index 98e4948..fafec528 100644
--- a/ios/chrome/browser/safari_data_import/ui/safari_data_import_password_conflict_resolution_view_controller.mm
+++ b/ios/chrome/browser/safari_data_import/ui/safari_data_import_password_conflict_resolution_view_controller.mm
@@ -183,11 +183,9 @@
     [cell.faviconView configureWithAttributes:item.faviconAttributes];
   } else {
     __weak __typeof(self) weakSelf = self;
-    UIAction* completionHandler =
-        [UIAction actionWithHandler:^(UIAction* action) {
-          [weakSelf updateItemWithIdentifier:identifier];
-        }];
-    [item loadFaviconWithCompletionHandler:completionHandler];
+    [item loadFaviconWithCompletionHandler:^{
+      [weakSelf updateItemWithIdentifier:identifier];
+    }];
   }
   BOOL shouldUnmaskPassword =
       _shouldUnmaskPasswordAtIndex[identifier.intValue].boolValue;
@@ -254,11 +252,11 @@
   [self updateSelectionButton];
 }
 
-/// Sets `_dataSource` and fill the table with data from `_passwordConflicts`.
+/// Sets `_dataSource` and fills the table with data from `_passwordConflicts`.
 - (void)initializeDataSourceAndTable {
   /// Set up data source.
   __weak __typeof(self) weakSelf = self;
-  UITableViewDiffableDataSourceCellProvider cellProvier = ^UITableViewCell*(
+  UITableViewDiffableDataSourceCellProvider cellProvider = ^UITableViewCell*(
       UITableView* tableView, NSIndexPath* indexPath,
       NSNumber* itemIdentifier) {
     CHECK_EQ(tableView, weakSelf.tableView);
@@ -266,7 +264,7 @@
   };
   _dataSource =
       [[UITableViewDiffableDataSource alloc] initWithTableView:self.tableView
-                                                  cellProvider:cellProvier];
+                                                  cellProvider:cellProvider];
   /// Initialize table.
   NSDiffableDataSourceSnapshot* snapshot =
       [[NSDiffableDataSourceSnapshot alloc] init];
diff --git a/ios/chrome/browser/safari_data_import/ui/safari_data_invalid_passwords_view_controller.mm b/ios/chrome/browser/safari_data_import/ui/safari_data_invalid_passwords_view_controller.mm
index b4503f9..5d11dede 100644
--- a/ios/chrome/browser/safari_data_import/ui/safari_data_invalid_passwords_view_controller.mm
+++ b/ios/chrome/browser/safari_data_import/ui/safari_data_invalid_passwords_view_controller.mm
@@ -160,11 +160,9 @@
     [cell.faviconView configureWithAttributes:item.faviconAttributes];
   } else {
     __weak __typeof(self) weakSelf = self;
-    UIAction* completionHandler =
-        [UIAction actionWithHandler:^(UIAction* action) {
-          [weakSelf updateItemWithIdentifier:identifier];
-        }];
-    [item loadFaviconWithCompletionHandler:completionHandler];
+    [item loadFaviconWithCompletionHandler:^{
+      [weakSelf updateItemWithIdentifier:identifier];
+    }];
   }
   [cell configureUILayout];
   return cell;
diff --git a/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm
index 4ff18c6..12e6ba86 100644
--- a/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm
@@ -126,11 +126,12 @@
 - (void)addDefaultBrowserVideoInstructionsView {
   _instructionsViewController =
       [[DefaultBrowserInstructionsViewController alloc]
-          initWithDismissButton:NO
-               hasRemindMeLater:NO
-                       hasSteps:YES
-                  actionHandler:self
-                      titleText:nil];
+              initWithDismissButton:NO
+                   hasRemindMeLater:NO
+          useDefaultAppsDestination:NO
+                           hasSteps:YES
+                      actionHandler:self
+                          titleText:nil];
   [self addChildViewController:_instructionsViewController];
 
   self.tableView.backgroundView = [[UIView alloc] init];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn
index fbec80d..246967d8 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn
+++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn
@@ -73,7 +73,6 @@
     "//ios/chrome/app:tests_hook",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/credential_provider/model:features",
-    "//ios/chrome/browser/passwords/model:features",
     "//ios/chrome/browser/settings/ui_bundled/password:features",
     "//ios/chrome/browser/shared/coordinator/utils",
     "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_constants.h b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_constants.h
index dcc318b..cdd5a1bc 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_constants.h
+++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_constants.h
@@ -18,7 +18,6 @@
   SectionIdentifierGooglePasswordManagerPin,
   SectionIdentifierOnDeviceEncryption,
   SectionIdentifierExportPasswordsButton,
-  SectionIdentifierImportPasswordsButton,
   SectionIdentifierDeleteCredentialsButton,
 };
 
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm
index a014cfd2..0a5cc07a07 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm
@@ -21,7 +21,6 @@
 #import "components/strings/grit/components_strings.h"
 #import "ios/chrome/app/tests_hook.h"
 #import "ios/chrome/browser/credential_provider/model/features.h"
-#import "ios/chrome/browser/passwords/model/features.h"
 #import "ios/chrome/browser/settings/ui_bundled/password/password_manager_ui_features.h"
 #import "ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_constants.h"
 #import "ios/chrome/browser/shared/coordinator/utils/credential_provider_settings_utils.h"
@@ -68,7 +67,6 @@
   ItemTypeOnDeviceEncryptionOptedInLearnMore,
   ItemTypeOnDeviceEncryptionSetUp,
   ItemTypeExportPasswordsButton,
-  ItemTypeImportPasswordsButton,
   ItemTypeDeleteCredentialsButton,
   ItemTypeFooter,
 };
@@ -208,9 +206,6 @@
 
   // The item related to the button for exporting passwords.
   TableViewTextItem* _exportPasswordsItem;
-
-  // The item related to the button for importing passwords.
-  TableViewTextItem* _importPasswordsItem;
 }
 
 - (instancetype)init {
@@ -306,25 +301,17 @@
   [model addItem:_exportPasswordsItem
       toSectionWithIdentifier:SectionIdentifierExportPasswordsButton];
 
-  // Import passwords button.
-  if (base::FeatureList::IsEnabled(kImportPasswordsFromSafari)) {
-    [model addSectionWithIdentifier:SectionIdentifierImportPasswordsButton];
-    _importPasswordsItem = [self createImportPasswordsItem];
-    [model addItem:_importPasswordsItem
-        toSectionWithIdentifier:SectionIdentifierImportPasswordsButton];
-  }
+  // Delete credentials button.
+  [model addSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
+  _deleteCredentialsItem = [self createDeleteCredentialsItem];
+  _deleteCredentialsFooterItem = [self createCredentialDeletionFooterItem];
+  [self updateDeleteAllCredentialsSection];
+  [model addItem:_deleteCredentialsItem
+      toSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
 
-    // Delete credentials button.
-    [model addSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
-    _deleteCredentialsItem = [self createDeleteCredentialsItem];
-    _deleteCredentialsFooterItem = [self createCredentialDeletionFooterItem];
-    [self updateDeleteAllCredentialsSection];
-    [model addItem:_deleteCredentialsItem
-        toSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
-
-    // Add footer for the delete credential section.
-    [model setFooter:_deleteCredentialsFooterItem
-        forSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
+  // Add footer for the delete credential section.
+  [model setFooter:_deleteCredentialsFooterItem
+      forSectionWithIdentifier:SectionIdentifierDeleteCredentialsButton];
 
   if (_canBulkMoveLocalPasswordsToAccount) {
     [self updateBulkMovePasswordsToAccountSection];
@@ -427,10 +414,6 @@
       }
       break;
     }
-    case ItemTypeImportPasswordsButton: {
-      // TODO(crbug.com/407587751): Start import flow.
-      break;
-    }
     case ItemTypeOnDeviceEncryptionSetUp: {
       [self.presentationDelegate showOnDeviceEncryptionSetUp];
       break;
@@ -672,16 +655,6 @@
   return exportPasswordsItem;
 }
 
-// Creates the "Import Passwords..." button.
-- (TableViewTextItem*)createImportPasswordsItem {
-  TableViewTextItem* importPasswordsItem =
-      [[TableViewTextItem alloc] initWithType:ItemTypeImportPasswordsButton];
-  importPasswordsItem.text = l10n_util::GetNSString(IDS_IOS_IMPORT_PASSWORDS);
-  importPasswordsItem.accessibilityTraits = UIAccessibilityTraitButton;
-  importPasswordsItem.textColor = [UIColor colorNamed:kBlueColor];
-  return importPasswordsItem;
-}
-
 // Creates the "Delete all data" button.
 - (TableViewTextItem*)createDeleteCredentialsItem {
   TableViewTextItem* deleteCredentialsItem =
diff --git a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm
index d62b9d4b..21e6e54 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_view_controller.mm
@@ -6,7 +6,6 @@
 
 #import "base/check.h"
 #import "base/metrics/histogram_macros.h"
-#import "base/metrics/user_metrics.h"
 #import "ios/chrome/browser/settings/ui_bundled/password/create_password_manager_title_view.h"
 #import "ios/chrome/browser/settings/ui_bundled/password/reauthentication/reauthentication_constants.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
@@ -124,9 +123,6 @@
 - (void)recordAuthenticationEvent:(ReauthenticationEvent)event {
   UMA_HISTOGRAM_ENUMERATION(password_manager::kReauthenticationUIEventHistogram,
                             event);
-  base::RecordAction(base::UserMetricsAction(
-      event == ReauthenticationEvent::kSuccess ? "MobileReauthSuccessful"
-                                               : "MobileReauthFailed"));
 }
 
 // Starts the native UI for Local Authentication.
diff --git a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
index 10acf90..65d9f5bd 100644
--- a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
@@ -563,7 +563,7 @@
     [model addItem:[self downloadsSettingsDetailItem]
         toSectionWithIdentifier:SettingsSectionIdentifierInfo];
   }
-  if (base::FeatureList::IsEnabled(kImportPasswordsFromSafari)) {
+  if (ShouldShowSafariImportWorkflow()) {
     [model addItem:[self safariDataImportSettingsDetailItem]
         toSectionWithIdentifier:SettingsSectionIdentifierInfo];
   }
@@ -1378,7 +1378,7 @@
       [self showTabsSettings];
       break;
     case SettingsItemTypeSafariDataImport: {
-      CHECK(base::FeatureList::IsEnabled(kImportPasswordsFromSafari));
+      CHECK(ShouldShowSafariImportWorkflow());
       base::RecordAction(base::UserMetricsAction("Settings.SafariImport"));
       id<ApplicationCommands> handler = HandlerForProtocol(
           _browser->GetCommandDispatcher(), ApplicationCommands);
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index aac3570..3fe9730 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -2489,7 +2489,7 @@
     // Currently displaying.
     return;
   }
-  CHECK(base::FeatureList::IsEnabled(kImportPasswordsFromSafari));
+  CHECK(ShouldShowSafariImportWorkflow());
   SafariDataImportMainCoordinator* safariDataImportCoordinator =
       [[SafariDataImportMainCoordinator alloc]
           initWithBaseViewController:self.activeViewController
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index e8a588e..571e2ef9 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -1314,5 +1314,10 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 
 bool IsDefaultBrowserOffCyclePromoEnabled() {
-  return base::FeatureList::IsEnabled(kIOSDefaultBrowserOffCyclePromo);
+#if defined(__IPHONE_18_3) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_3
+  if (@available(iOS 18.3, *)) {
+    return base::FeatureList::IsEnabled(kIOSDefaultBrowserOffCyclePromo);
+  }
+#endif
+  return false;
 }
diff --git a/ios/chrome/browser/shared/ui/elements/BUILD.gn b/ios/chrome/browser/shared/ui/elements/BUILD.gn
index f9df65d..4e7e10a 100644
--- a/ios/chrome/browser/shared/ui/elements/BUILD.gn
+++ b/ios/chrome/browser/shared/ui/elements/BUILD.gn
@@ -11,8 +11,6 @@
     "fade_truncating_label+Testing.h",
     "fade_truncating_label.h",
     "fade_truncating_label.mm",
-    "gray_highlight_button.h",
-    "gray_highlight_button.mm",
     "home_waiting_view.h",
     "home_waiting_view.mm",
     "new_feature_badge_view.h",
diff --git a/ios/chrome/browser/shared/ui/elements/gray_highlight_button.h b/ios/chrome/browser/shared/ui/elements/gray_highlight_button.h
deleted file mode 100644
index c32d1f8..0000000
--- a/ios/chrome/browser/shared/ui/elements/gray_highlight_button.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_SHARED_UI_ELEMENTS_GRAY_HIGHLIGHT_BUTTON_H_
-#define IOS_CHROME_BROWSER_SHARED_UI_ELEMENTS_GRAY_HIGHLIGHT_BUTTON_H_
-
-#import <UIKit/UIKit.h>
-
-// A button that makes its background light gray when highlighted and clear
-// when not. Also its text is not dimmed.
-@interface GrayHighlightButton : UIButton
-@end
-
-#endif  // IOS_CHROME_BROWSER_SHARED_UI_ELEMENTS_GRAY_HIGHLIGHT_BUTTON_H_
diff --git a/ios/chrome/browser/shared/ui/elements/gray_highlight_button.mm b/ios/chrome/browser/shared/ui/elements/gray_highlight_button.mm
deleted file mode 100644
index 7bf38f9..0000000
--- a/ios/chrome/browser/shared/ui/elements/gray_highlight_button.mm
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/shared/ui/elements/gray_highlight_button.h"
-
-#import "ios/chrome/common/ui/colors/semantic_color_names.h"
-
-@implementation GrayHighlightButton
-
-- (void)setHighlighted:(BOOL)highlighted {
-  [super setHighlighted:highlighted];
-  if (highlighted) {
-    self.backgroundColor = [UIColor colorNamed:kTableViewRowHighlightColor];
-  } else {
-    self.backgroundColor = [UIColor clearColor];
-  }
-}
-
-@end
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
index 7d5508c..52b8a01 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-2b3dc2b44013d2d234e77f05f663b484906b97be
\ No newline at end of file
+3f648145bac0ea4bdffac53ef0f5345dc536a106
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
index fa8edb9..72972121 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-8cf779f7ee30e59eceee038d866f82a0115de601
\ No newline at end of file
+c60140003e852c734e5e98767651d16f28f8ea4f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index 9c8467f7..5059703 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-ef33ad6339246865037fd26306436058dc036f31
\ No newline at end of file
+c4f03325f380962bd5a57e673f156ab3f0180e46
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
index 9d0b8a5a..5f47b694e 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-d86275b9d51d47fb77c914d68c75cb9f8bee9308
\ No newline at end of file
+da939f40adf36bc69118e4963bdadc12d2971b27
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index 7e33a7f..0bd187bf 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-4e586af022b5a66cd068ce9eaed10b46554d9028
\ No newline at end of file
+d4326d1b262c3b23e3ec3aec81971c1a26c137de
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
index 611309d..868d074b 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-7d7a5ab1f02783d45e815dd4391a3adccfa06c37
\ No newline at end of file
+a422e39865a822096bf17dc335dd024bdc23e4f9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
index 8098376..d4601ac 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ec8b6c78e731b0dae82a5d9ef2fe940787a1d023
\ No newline at end of file
+8e21d8939ab53e6e6c907d4fc1479aeae65ce839
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
index b7969d04..27795ee 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-20d3a3c5eb8e52be0115643ae2888d323214bb22
\ No newline at end of file
+8575d0f12eb2147433ee0284856bdd403aa90d7f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
index dafc206..b119bd3 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-84ac9069ccd68b51ed8d9fcc56cccf7accca8bce
\ No newline at end of file
+672054b9527c45bf0e36f43fe13e0be9a8a5fa4d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 91050c09..1a56cb0 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-f1a1b81f1bbfa57d7e2c2e68abc4e8761978aef9
\ No newline at end of file
+7c3958f3159c132b464a3b374df5de0ad4e0fcf3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 7129b07..26315c5 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-c35ae31be3825661d9a175cace09339b96427a1b
\ No newline at end of file
+97600b7ed30e8da4ccbce5fd7e0ae146f94f8084
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
index c9665ccd..4f71fb0 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-34c7a93856259ea302886989c0c35601ac05b927
\ No newline at end of file
+0f9e847624d6acc56218df1afccefac0176e1929
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 044255c..c67e2fe 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-757d75db5586752b44fc6870abc749b999cc35f2
\ No newline at end of file
+df76c60c50e53078ae62f6684679ad18b0c6a676
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
index ee9d3f2..2284b73 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-f9fd74528acf3d52fd121e2e38b646369fb3e2a8
\ No newline at end of file
+3c0ce9d8e6dd547d7cc10654f10a1f0927e55d8d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index c0e13a71..e606343 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e180649b39da890ba7df4e37eb7454c5c6d49f69
\ No newline at end of file
+1a3e671ae05a5abb634d32c0b9816fa555904f3d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
index 78d20fd..602e5e6b 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-eeaaa908ddf78fb3113e032a551aec9acc739039
\ No newline at end of file
+e49f9c0864b49076bb683e7515480458693cb839
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 8b472d4..4edb6c68 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-cbbfa1a4d85a3f314721f1a9a72c48b8443f4dcb
\ No newline at end of file
+8498e55b64523cedf9cf152b6607cc34af94bfae
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
index aeeca0d..53a2616 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-7d52317cf2a9483a3ac3814b5a76445d9e11002b
\ No newline at end of file
+4bcfa5518df8dc628fb10cfd3a3644aee824e4e4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index cfc0540..157d7d6 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-31d0b030d303b38519003bcc428c19860972fe2a
\ No newline at end of file
+5200767f95bee40a91da86780fe9fd63e496c05a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index aaaed0e0..f413aa2 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-bc5ba6b527260c4bd0205ea7ece5f7c0e1727264
\ No newline at end of file
+7a4c99eefae0bd129fc5734e5bce76210c859b07
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index e889b70..89ba7e6 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-0f5a8d441bdf207d93286f8b02909b81c75ba902
\ No newline at end of file
+54ad7f096be08a4433422e049593ee1a6adc3b21
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
index 2786dd38..ba4f7665 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-62257c2833d0c37281197dd3f28ef04fd9ffd36c
\ No newline at end of file
+39a8cfd85586c911947db35e8060136fda06a5e1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index fc4e75cf..3cced4f2c 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-81259e8d8d0a77d37681ff1616c639bd9a993bb4
\ No newline at end of file
+f7d5c712320b2ea719cb52de3e7fd945261eb849
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 0da10a5..6f1e50eb 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-0416419033970186b857ded9bc116e80812e4c0d
\ No newline at end of file
+7046dd25d19cd6add0c8b5bf8420bc5b6074faf6
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 673fa878..e358606 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-b30c26c94c6ff70a15fcbdfca1cb5eb6574a8412
\ No newline at end of file
+71b3ef5c81a6456a4e33b1818a29eca3a39203d4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
index af430dc9..630bde9 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-a0ae1589bafb183f4d716e106344e7db1a659550
\ No newline at end of file
+fa18329a95ce624969d5ca420211cf42a2a3ed4a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index f4d1ce27..0a90c67 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-b7c988d7ebaf9f7ce00325bd27df4ce62c75bc85
\ No newline at end of file
+c2c428b5a5c1adca1501462ad97543dd28e737d9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 3c2c299..18cbeee 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-4fc69390a7b25c2ab6472df119f16268817bf3bc
\ No newline at end of file
+81eda78755a5bbb9de71404f4d4783294614848f
\ No newline at end of file
diff --git a/ios/testing/data/http_server_files/article.html b/ios/testing/data/http_server_files/article.html
index a8037c0..be0e09e 100644
--- a/ios/testing/data/http_server_files/article.html
+++ b/ios/testing/data/http_server_files/article.html
@@ -16,7 +16,7 @@
 
 <img src="chromium_logo.png" alt="Chromium Image" id="chromium_image"/>
 
-<p>Lorem ipsum dolor sit amet, at alia aliquip vel. Quas inani labore an vel. Sed an nemore minimum accusata. Sint inermis tacimates est ex, ad movet iracundia mei, delicata iracundia laboramus ei eos. Illud principes complectitur te nec, ius alienum insolens ea, cu quo oratio omnesque.
+<p>Lorem ipsum dolor sit amet, at alia aliquip vel. Quas inani labore an vel. Sed an nemore minimum accusata. Sint inermis tacimates est ex, ad movet iracundia mei, delicata iracundia laboramus ei eos. Illud principes complectitur te nec, ius alienum insolens ea, cu quo oratio omnesque. <a href="chromium://version">ultricies sed</a> <a href="data:image/png,abc">Proin</a> <a href="javascript:document.body.innerHTML='';">consequat in</a></p>
 
 <p>Lorem ipsum dolor sit amet, at alia aliquip vel. Quas inani labore an vel. Sed an nemore minimum accusata. Sint inermis tacimates est ex, ad movet iracundia mei, delicata iracundia laboramus ei eos. Illud principes complectitur te nec, ius alienum insolens ea, cu quo oratio omnesque.
 
diff --git a/ios/web_view/internal/autofill/cwv_credit_card_saver.mm b/ios/web_view/internal/autofill/cwv_credit_card_saver.mm
index 28006d5..df0ddd3 100644
--- a/ios/web_view/internal/autofill/cwv_credit_card_saver.mm
+++ b/ios/web_view/internal/autofill/cwv_credit_card_saver.mm
@@ -101,15 +101,14 @@
 
   _saveCompletionHandler = completionHandler;
   DCHECK(_saveCardCallback);
+  autofill::payments::PaymentsAutofillClient::UserProvidedCardDetails details;
+  details.cardholder_name = base::SysNSStringToUTF16(cardHolderFullName);
+  details.expiration_date_month = base::SysNSStringToUTF16(expirationMonth);
+  details.expiration_date_year = base::SysNSStringToUTF16(expirationYear);
   std::move(_saveCardCallback)
       .Run(autofill::payments::PaymentsAutofillClient::
                SaveCardOfferUserDecision::kAccepted,
-           {
-               .cardholder_name = base::SysNSStringToUTF16(cardHolderFullName),
-               .expiration_date_month =
-                   base::SysNSStringToUTF16(expirationMonth),
-               .expiration_date_year = base::SysNSStringToUTF16(expirationYear),
-           });
+           details);
   _decisionMade = YES;
 }
 
diff --git a/media/base/format_utils.cc b/media/base/format_utils.cc
index e8f67bc..891657b6 100644
--- a/media/base/format_utils.cc
+++ b/media/base/format_utils.cc
@@ -20,6 +20,9 @@
     case gfx::BufferFormat::RGBA_8888:
       return PIXEL_FORMAT_ABGR;
 
+    case gfx::BufferFormat::RGBA_F16:
+      return PIXEL_FORMAT_RGBAF16;
+
     // There is no PIXEL_FORMAT_XBGR which would have been the right mapping.
     // See ui/ozone drm_util.cc::GetFourCCFormatFromBufferFormat as reference.
     // But here it is only about indicating to not consider the alpha channel.
@@ -80,6 +83,9 @@
     case PIXEL_FORMAT_XR30:
       return gfx::BufferFormat::RGBA_1010102;
 
+    case PIXEL_FORMAT_RGBAF16:
+      return gfx::BufferFormat::RGBA_F16;
+
     default:
       DLOG(WARNING) << "Unsupported VideoPixelFormat: " << pixel_format;
       return std::nullopt;
@@ -103,6 +109,8 @@
     return PIXEL_FORMAT_ABGR;
   } else if (format == viz::SinglePlaneFormat::kRGBA_1010102) {
     return PIXEL_FORMAT_XR30;
+  } else if (format == viz::SinglePlaneFormat::kRGBA_F16) {
+    return PIXEL_FORMAT_RGBAF16;
   } else if (format == viz::MultiPlaneFormat::kYV12) {
     return PIXEL_FORMAT_YV12;
   } else if (format == viz::MultiPlaneFormat::kNV12) {
@@ -130,6 +138,8 @@
       return viz::SinglePlaneFormat::kRGBX_8888;
     case PIXEL_FORMAT_XR30:
       return viz::SinglePlaneFormat::kRGBA_1010102;
+    case PIXEL_FORMAT_RGBAF16:
+      return viz::SinglePlaneFormat::kRGBA_F16;
     case PIXEL_FORMAT_YV12:
       return viz::MultiPlaneFormat::kYV12;
     case PIXEL_FORMAT_NV12:
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 569a619..a7fce50 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -1061,12 +1061,18 @@
              "HardwareSecureDecryptionAv1",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+#if BUILDFLAG(IS_WIN)
 // Enables showing permission indicator in the omnibox when a site is allowed or
 // denied to to use protected content IDs to play protected content.
-#if BUILDFLAG(IS_WIN)
 BASE_FEATURE(kProtectedMediaIdentifierIndicator,
              "ProtectedMediaIdentifierIndicator",
              base::FEATURE_ENABLED_BY_DEFAULT);
+
+// Requires that setServerCertificate() be called before generateRequest().
+// This feature only affects MediaFoundation OS CDMs.
+BASE_FEATURE(kHardwareSecureDecryptionRequireServerCert,
+             "HardwareSecureDecryptionRequireServerCert",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
 // Enables handling of hardware media keys for controlling media.
@@ -1634,6 +1640,12 @@
              "use-fake-device-for-media-stream",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables accurate dropped frame count for MediaStreamVideoSource.
+// TODO(crbug.com/432367602): Remove after M143.
+BASE_FEATURE(kMediaStreamAccurateDroppedFrameCount,
+             "MediaStreamAccurateDroppedFrameCount",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_FUCHSIA)
 // Enables effects for camera and mic streams.
 BASE_FEATURE(kCameraMicEffects,
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 8216c61..5e30889 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -285,6 +285,7 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kHardwareSecureDecryptionAv1);
 #if BUILDFLAG(IS_WIN)
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kProtectedMediaIdentifierIndicator);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kHardwareSecureDecryptionRequireServerCert);
 #endif
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kInternalMediaSession);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kOnDeviceWebSpeech);
@@ -364,6 +365,7 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUnifiedAutoplay);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUseAndroidOverlayForSecureOnly);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUseFakeDeviceForMediaStream);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaStreamAccurateDroppedFrameCount);
 #if BUILDFLAG(IS_LINUX)
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kAcceleratedVideoDecodeLinux);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kAcceleratedVideoDecodeLinuxGL);
diff --git a/media/capture/video/apple/gpu_memory_buffer_tracker_apple.cc b/media/capture/video/apple/gpu_memory_buffer_tracker_apple.cc
index fe31b17..802cd69 100644
--- a/media/capture/video/apple/gpu_memory_buffer_tracker_apple.cc
+++ b/media/capture/video/apple/gpu_memory_buffer_tracker_apple.cc
@@ -24,9 +24,8 @@
     NOTREACHED() << "Unsupported VideoPixelFormat "
                  << VideoPixelFormatToString(format);
   }
-  if ((io_surface_ =
-           CreateIOSurface(dimensions, gfx::BufferFormat::YUV_420_BIPLANAR,
-                           /*should_clear=*/false))) {
+  if ((io_surface_ = CreateIOSurface(dimensions, viz::MultiPlaneFormat::kNV12,
+                                     /*should_clear=*/false))) {
     DVLOG(2) << __func__ << " id " << IOSurfaceGetID(io_surface_.get());
     return true;
   } else {
diff --git a/media/cdm/win/media_foundation_cdm.cc b/media/cdm/win/media_foundation_cdm.cc
index dbc7738..c2a6bc6 100644
--- a/media/cdm/win/media_foundation_cdm.cc
+++ b/media/cdm/win/media_foundation_cdm.cc
@@ -27,6 +27,7 @@
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
 #include "media/base/cdm_promise.h"
+#include "media/base/media_switches.h"
 #include "media/base/win/hresults.h"
 #include "media/base/win/media_foundation_cdm_proxy.h"
 #include "media/base/win/mf_helpers.h"
@@ -370,6 +371,7 @@
     return;
   }
 
+  server_certificate_set_ = true;
   promise->resolve();
 }
 
@@ -411,6 +413,17 @@
     return;
   }
 
+  // Check if server certificate requirement is enforced
+  if (base::FeatureList::IsEnabled(
+          kHardwareSecureDecryptionRequireServerCert) &&
+      MediaFoundationCdmModule::GetInstance()->IsOsCdm() &&
+      !server_certificate_set_) {
+    promise->reject(Exception::INVALID_STATE_ERROR, 0,
+                    "setServerCertificate must be called before "
+                    "generateRequest");
+    return;
+  }
+
   // Create and initialize session.
 
   // TODO(xhwang): Implement session expiration update.
@@ -691,6 +704,9 @@
   // Reset IMFContentDecryptionModule which also holds the old ITA.
   mf_cdm_.Reset();
 
+  // Reset server certificate flag since the CDM is being recreated
+  server_certificate_set_ = false;
+
   // Recreates IMFContentDecryptionModule so we can create new sessions.
   if (FAILED(Initialize())) {
     DLOG(ERROR) << __func__ << ": Re-initialization failed";
diff --git a/media/cdm/win/media_foundation_cdm.h b/media/cdm/win/media_foundation_cdm.h
index 0d17455..24c61c6 100644
--- a/media/cdm/win/media_foundation_cdm.h
+++ b/media/cdm/win/media_foundation_cdm.h
@@ -181,6 +181,9 @@
   // Copy of the last client token we stored.
   std::vector<uint8_t> cached_client_token_;
 
+  // Whether SetServerCertificate() has been called successfully.
+  bool server_certificate_set_ = false;
+
   // This must be the last member.
   base::WeakPtrFactory<MediaFoundationCdm> weak_factory_{this};
 };
diff --git a/media/cdm/win/media_foundation_cdm_unittest.cc b/media/cdm/win/media_foundation_cdm_unittest.cc
index 7d8c2f53..724c98a 100644
--- a/media/cdm/win/media_foundation_cdm_unittest.cc
+++ b/media/cdm/win/media_foundation_cdm_unittest.cc
@@ -9,13 +9,17 @@
 #include "base/functional/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_callback.h"
+#include "base/test/run_until.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "media/base/media_switches.h"
 #include "media/base/mock_filters.h"
 #include "media/base/test_helpers.h"
 #include "media/base/win/hresults.h"
 #include "media/base/win/media_foundation_cdm_proxy.h"
 #include "media/base/win/mf_helpers.h"
 #include "media/base/win/mf_mocks.h"
+#include "media/cdm/win/media_foundation_cdm_module.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -170,6 +174,7 @@
   bool can_initialize_ = true;
   std::string session_id_;
   scoped_refptr<MediaFoundationCdmProxy> mf_cdm_proxy_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(MediaFoundationCdmTest, SetServerCertificate) {
@@ -657,4 +662,91 @@
   task_environment_.RunUntilIdle();
 }
 
+TEST_F(MediaFoundationCdmTest, RequireServerCert_Enabled_NonOsCdm_NoCert) {
+  // For non-OS CDMs, CreateSessionAndGenerateRequest should work
+  // without SetServerCertificate when the feature is enabled
+  scoped_feature_list_.InitAndEnableFeature(
+      kHardwareSecureDecryptionRequireServerCert);
+  Initialize();
+  MediaFoundationCdmModule::GetInstance()->SetIsOsCdmForTesting(false);
+  COM_EXPECT_CALL(mf_cdm_, SetServerCertificate(_, _)).Times(0);
+  CreateSessionAndGenerateRequest();
+}
+
+TEST_F(MediaFoundationCdmTest, RequireServerCert_Disabled_NonOsCdm_NoCert) {
+  // For non-OS CDMs, CreateSessionAndGenerateRequest should work
+  // without SetServerCertificate when the feature is disabled
+  scoped_feature_list_.InitAndDisableFeature(
+      kHardwareSecureDecryptionRequireServerCert);
+  Initialize();
+  MediaFoundationCdmModule::GetInstance()->SetIsOsCdmForTesting(false);
+  COM_EXPECT_CALL(mf_cdm_, SetServerCertificate(_, _)).Times(0);
+  CreateSessionAndGenerateRequest();
+}
+
+TEST_F(MediaFoundationCdmTest, RequireServerCert_Disabled_OsCdm_NoCert) {
+  // For OS CDMs, CreateSessionAndGenerateRequest should work
+  // without SetServerCertificate when the feature is disabled
+  scoped_feature_list_.InitAndDisableFeature(
+      kHardwareSecureDecryptionRequireServerCert);
+  Initialize();
+  MediaFoundationCdmModule::GetInstance()->SetIsOsCdmForTesting(true);
+  COM_EXPECT_CALL(mf_cdm_, SetServerCertificate(_, _)).Times(0);
+  CreateSessionAndGenerateRequest();
+}
+
+TEST_F(MediaFoundationCdmTest, RequireServerCert_Enabled_OsCdm) {
+  // Set a shorter timeout then the default
+  // since this test is expected to run quickly.
+  base::test::ScopedRunLoopTimeout timeout(FROM_HERE, base::Seconds(5));
+
+  // Enable the feature flag that requires SetServerCertificate
+  // before CreateSessionAndGenerateRequest for OS CDMs.
+  scoped_feature_list_.InitAndEnableFeature(
+      kHardwareSecureDecryptionRequireServerCert);
+
+  Initialize();
+  MediaFoundationCdmModule::GetInstance()->SetIsOsCdmForTesting(true);
+
+  // For OS CDMs, CreateSessionAndGenerateRequest should fail
+  // without SetServerCertificate when the feature is enabled
+  std::vector<uint8_t> init_data = StringToVector("init_data");
+
+  COM_EXPECT_CALL(mf_cdm_, SetServerCertificate(_, _)).Times(0);
+
+  // First try CreateSessionAndGenerateRequest without calling
+  // SetServerCertificate. This should fail for OS CDMs when the
+  // feature is enabled
+  cdm_->CreateSessionAndGenerateRequest(
+      CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
+      std::make_unique<MockCdmSessionPromise>(/*expect_success=*/false,
+                                              &session_id_));
+  ASSERT_TRUE(base::test::RunUntil([&]() { return session_id_.empty(); }));
+
+  // Now call SetServerCertificate first
+  std::vector<uint8_t> certificate = StringToVector("certificate");
+  COM_EXPECT_CALL(mf_cdm_, SetServerCertificate(NotNull(), certificate.size()))
+      .WillOnce(Return(S_OK));
+
+  cdm_->SetServerCertificate(
+      certificate, std::make_unique<MockCdmPromise>(/*expect_success=*/true));
+
+  // Now CreateSessionAndGenerateRequest should succeed
+  COM_EXPECT_CALL(mf_cdm_,
+                  CreateSession(MF_MEDIAKEYSESSION_TYPE_TEMPORARY, _, _))
+      .WillOnce(DoAll(SaveComPtr<1>(&mf_cdm_session_callbacks_),
+                      SetComPointee<2>(mf_cdm_session_.Get()), Return(S_OK)));
+
+  SetGenerateRequestExpectations(mf_cdm_session_, kSessionId,
+                                 &mf_cdm_session_callbacks_);
+
+  cdm_->CreateSessionAndGenerateRequest(
+      CdmSessionType::kTemporary, EmeInitDataType::WEBM, init_data,
+      std::make_unique<MockCdmSessionPromise>(/*expect_success=*/true,
+                                              &session_id_));
+
+  ASSERT_TRUE(
+      base::test::RunUntil([&]() { return session_id_ == kSessionId; }));
+}
+
 }  // namespace media
diff --git a/media/gpu/chromeos/platform_video_frame_utils.h b/media/gpu/chromeos/platform_video_frame_utils.h
index cc53abf4..7af49b1 100644
--- a/media/gpu/chromeos/platform_video_frame_utils.h
+++ b/media/gpu/chromeos/platform_video_frame_utils.h
@@ -6,6 +6,7 @@
 #define MEDIA_GPU_CHROMEOS_PLATFORM_VIDEO_FRAME_UTILS_H_
 
 #include <optional>
+#include <set>
 
 #include "base/memory/scoped_refptr.h"
 #include "base/unguessable_token.h"
diff --git a/media/gpu/vaapi/vaapi_image_processor_backend.h b/media/gpu/vaapi/vaapi_image_processor_backend.h
index 491d783..528fcb6 100644
--- a/media/gpu/vaapi/vaapi_image_processor_backend.h
+++ b/media/gpu/vaapi/vaapi_image_processor_backend.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/containers/flat_map.h"
 #include "base/containers/id_map.h"
 #include "base/task/sequenced_task_runner.h"
 #include "media/gpu/chromeos/image_processor_backend.h"
diff --git a/media/mojo/services/media_foundation_service.cc b/media/mojo/services/media_foundation_service.cc
index 6860709..a77cac2 100644
--- a/media/mojo/services/media_foundation_service.cc
+++ b/media/mojo/services/media_foundation_service.cc
@@ -133,14 +133,14 @@
   return supported;
 }
 
-bool IsTypeSupportedInternalEx(
-    ComPtr<IMFExtendedDRMTypeSupport> mf_type_support,
-    const std::string& key_system,
-    bool is_hw_secure,
-    const std::string& content_type) {
+bool IsTypeSupportedByOsCdm(ComPtr<IMFExtendedDRMTypeSupport> mf_type_support,
+                            const std::string& key_system,
+                            bool is_hw_secure,
+                            const std::string& content_type) {
   const base::TimeTicks start_time = base::TimeTicks::Now();
+  // Force the use of the hardware based PlayReady key system.
   bool supported = IsMediaFoundationContentTypeSupported(
-      mf_type_support, key_system, content_type);
+      mf_type_support, kPlayReadyKeySystemRecommendationHwSecure, content_type);
   // The above function may take seconds to run. Report UMA to understand the
   // actual performance impact. Report UMA only for success cases.
   if (supported) {
@@ -612,10 +612,8 @@
       return;
     }
 
-    // Force the use of the hardware based PlayReady key system.
-    is_type_supported_cb =
-        base::BindRepeating(&IsTypeSupportedInternalEx, mf_type_support,
-                            kPlayReadyKeySystemRecommendationHwSecure);
+    is_type_supported_cb = base::BindRepeating(&IsTypeSupportedByOsCdm,
+                                               mf_type_support, key_system);
   } else {
     is_type_supported_cb =
         base::BindRepeating(&IsTypeSupportedInternal, cdm_factory, key_system);
diff --git a/media/renderers/paint_canvas_video_renderer_unittest.cc b/media/renderers/paint_canvas_video_renderer_unittest.cc
index 960a191..b5dffac33 100644
--- a/media/renderers/paint_canvas_video_renderer_unittest.cc
+++ b/media/renderers/paint_canvas_video_renderer_unittest.cc
@@ -381,7 +381,12 @@
 
 TEST_F(PaintCanvasVideoRendererTest, ReinterpretAsSRGB) {
   FillFrameWithColor(natural_frame(), kRed);
-  natural_frame()->set_color_space(gfx::ColorSpace::CreateHDR10());
+  // Set to HDR PQ color space but with default 601 matrix and range as I420
+  // formats cannot convert to RGB color spaces with RGB matrix.
+  auto hdr_cs = gfx::ColorSpace(
+      gfx::ColorSpace::PrimaryID::BT2020, gfx::ColorSpace::TransferID::PQ,
+      gfx::ColorSpace::MatrixID::SMPTE170M, gfx::ColorSpace::RangeID::LIMITED);
+  natural_frame()->set_color_space(hdr_cs);
 
   cc::PaintFlags flags;
   flags.setBlendMode(SkBlendMode::kSrcOver);
diff --git a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
index ae574499..46c48aa 100644
--- a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
@@ -158,6 +158,7 @@
   switch (format) {
     case PIXEL_FORMAT_ARGB:
     case PIXEL_FORMAT_ABGR:
+    case PIXEL_FORMAT_RGBAF16:
       return visible_size;
     case PIXEL_FORMAT_NV12:
       // Align number of rows to 2, because it's required by YUV_420_BIPLANAR
@@ -176,7 +177,7 @@
                                 const gfx::ColorSpace& color_space) {
   // Currently only support ARGB, ABGR and NV12.
   CHECK(format == PIXEL_FORMAT_ARGB || format == PIXEL_FORMAT_ABGR ||
-        format == PIXEL_FORMAT_NV12)
+        format == PIXEL_FORMAT_NV12 || format == PIXEL_FORMAT_RGBAF16)
       << format;
 
   auto* context = pool_->GetContext();
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index d8b5091..041bc37 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -43277,7 +43277,6 @@
     { "name": "xsenya74hram.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xtreamfire.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xtreme-cs.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xuann.wang", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xuesoska.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xwfwrestling.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xxl-bonus.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -85230,7 +85229,6 @@
     { "name": "konetsu.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "konoex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kopyandsonslandscaping.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "koujiao.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kredi-hesaplama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kristymiley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kulturbiljetter.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -85686,7 +85684,6 @@
     { "name": "zinkmetselwerken.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zpasathagroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zuhausejobs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "zuoai.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zwedenautohuur.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zwitserlandautohuur.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zzls.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -101725,7 +101722,6 @@
     { "name": "zverovod.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zwz.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zyiaactive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "090124.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1001faire-part.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "12356.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "123sportpassion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -105668,7 +105664,6 @@
     { "name": "naukriresults.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "naxsnaps.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ncadc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "neishe.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nelswong.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "netbeez.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "netnl.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -135469,7 +135464,6 @@
     { "name": "davewallerphotography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "daylinq.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dd.team", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "deadlock.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "decoshop.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "delnicismrti.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "demltd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -137300,7 +137294,6 @@
     { "name": "martinritter.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "martsinovskaolga.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "massimo.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mat.tr.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "matchable.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mater.academy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "materna.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -145895,7 +145888,6 @@
     { "name": "flywebservices.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fmciclismo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fnblindsay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "fnbo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fnbodirect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fnh.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "foamular.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -157586,7 +157578,6 @@
     { "name": "houzz.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hseal.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "huberheightschamber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hudnara.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hugin3d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hugopvigo.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "humantripod.bet", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -157685,7 +157676,6 @@
     { "name": "koffer-schweiz.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koivukangas.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "korabbio.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kraftochbalans.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kross1308.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kuixiaoran.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -157861,7 +157851,6 @@
     { "name": "nhrefco.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nicoldev.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nikkasystems.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "niksys.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "njbarberco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nni-pulse-engagement-dev.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nnisurveyqa.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -160416,7 +160405,6 @@
     { "name": "oswestrysff.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oszteralexandra.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "otp24hr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "outbrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ovarit.rip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ovog.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "owl.et", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -161634,7 +161622,6 @@
     { "name": "nbri.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nederlandseloterij.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "neuropsiperches.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "newflyer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "newstoter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "newtrendsbykate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "newyork.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -162803,7 +162790,6 @@
     { "name": "gulfdinar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "guscanada.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "guteli.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "gwaudiodesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h.hk.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "h2ocustomers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -162955,7 +162941,6 @@
     { "name": "kc-support.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kdt-lille.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kenkobox.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kesko.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kestrelconnect.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "keyth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kg6wxc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -163250,7 +163235,6 @@
     { "name": "nsimobilewatersolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nugeopend.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nzlp.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "oakhill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ocun.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oddtx.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "odebouchage.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -163479,7 +163463,6 @@
     { "name": "seniorpremium.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "serizon.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "servantsofgrace.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "serviall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "service360group.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "servicii-wordpress.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "settle.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -163833,6 +163816,2347 @@
     { "name": "zoho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zonanonton.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zorntt.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adamsmithsociety.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allxiya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alberttalkstech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allstarbyreportex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "albanycourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allstarbyreportex.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aikenwelch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akhyar.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amametall.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amenfis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alderautomation.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "americanlegaltranscription.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allstarreporting.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "airacle.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alrafayglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "539124.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aibraintest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acesdenver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ahuhvac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "250250.best", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathalliance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2neiku.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alarmreceiver.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ageverif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.app", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "analyzerhq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "archstonesecurity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acourtreporter.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antiformiche.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aquadx.net.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "albahotel.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aquadx.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arrowheadexecutivesuites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ajbelltouch.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arcenotas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artmiller.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "angelkawaii.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acegraphics.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0scar.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arkanpath.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alisufyan.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atkinsonbaker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atmmoneymachine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "assamarket.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adulttrust.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1001farmtoys.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ai-pacs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlanticreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antennistaroma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "agroexp.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acasundayschool.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asfalto.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlasflare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aadskeuken.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "augustascribes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alberchigo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "activandoideas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "authorizedcourttranscriptionists.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "authorizedcourttranscriptionists.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrcourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asjablonski.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "actionlitho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aggcom.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "100plusglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrcourtreportingblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrcourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrtrialsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "attractingaddictionnv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aosoracafe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrcourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexundnatalya.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awrtrialsolutions.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "481x.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "assently.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "159v.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "21kk.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arvin.com.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antiviraci.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advantaseeds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "51evar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ayotteshackelford.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "babiarzreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aventura-costarica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "889u.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adsintl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aiup.date", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artphototravel.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "159b.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ascendi.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "areeblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arthrise.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akumbittiyolyardim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ateam.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alternativebrands.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1275.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beanshencr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allcouponat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bankmandiritaspen.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bas.fm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asliving1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barteltnix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "568k.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aistudynow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anglesey-holiday-lettings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beadigitalreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "auraedu.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bambiva.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "articonnect.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bellreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "68workscarbon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alivenewyorkcity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baydev.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asperas.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "372m.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6k.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "157t.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "690c.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3pp3.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "349m.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bekam.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aferaacademy.africa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "attentioninsight.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alif.tj", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "357s.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "699c.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a2zhost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bemnaturalmente.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avoiding-complexity.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "astrapool.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bancosabadell.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "69asmr1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acousticbuy.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "babysitting.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biehletal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "barteltreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bigbosscleans.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "267e.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bambooviews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "502e.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bigbag.chat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aquadealz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aromavadisi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "babypanel.webhop.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlantik-clinic.msk.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aurantis.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blacklabelcourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bebra.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "avtomasla.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blacklabellegalservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alt-met.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alchemyinfusionco.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "berlinartweek.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beeps.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestsolaris.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluefrog.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlanticdermatologyandlaser.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bhcrusher1.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookdubaihome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonanzareporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "367e.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beosocial.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asa73.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluebridgehq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "berngardt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baiwulin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bi.je", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bowmanedebohls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bebra.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestastrologermohali.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bridgescourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bejbinek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "820e.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "176c.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brown-jones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bersadees.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beneshop.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beneknihy.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "269k.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brownjones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blueledgellc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blueledgeclassroom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bg9jue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "appliedprinciples.co.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brande.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bushmancourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besinspain.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "becausewematterlv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bushmanreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armadaskis.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "auto-motor-oel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autogorod24.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "btn.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bwfreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caa-it.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boombrd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "californiacourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bravechristian.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluespaceenvironments.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "135s.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bithosting.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "9d5m.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "californiacourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baiyunbrake.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bfi-edel-stahl.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aguasdefafe.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c5y.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calidognia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "budmate.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookerrecycling.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caesar.me.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cadyreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "125c.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cameoreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "camguide.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookergroupjobs.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blueremoval.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biurosuszec.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canadiancourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "capitalreporting.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "203e.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carolinacourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caminominimalista.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carmensanzchacon.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "budget4cast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ascentgaragedoors.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bursapay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carpacontracting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestonpyrolysis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caseworksonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bigbusy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caspiliving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cannabisfactsnv.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "betransfer.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "casebookonline.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cashdeskapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caspianlegalcenter.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "catempire.win", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "budgens.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ccaptioning.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cartelesparaimprimir.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "broder.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brony.quest", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "136s.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cavalier-reporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buffstreams.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carilec.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "camilla-rena.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cardpresso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amerinetusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centuryreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "broers-rolluiken.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caspianlegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acuscribe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caspiconstruction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centextlitigationservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "birco.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7014twinlakes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amtl.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ambassadorlegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centexlegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brandinstitute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "certifiedcourttranscriptions.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "19950904.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cannabisfactsnevada.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abias.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bytenest.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.dev", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathalliance.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathadvantage.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carepathinnovations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpath.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bugabond.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathadvantage.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bs14-it5xyz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charlestondepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aliciacryst.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathadvantage.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "busitee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charlestonlegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abretucuenta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advanpathadvantage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charlestoncourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acrackstreams.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centextlegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "accumulus.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "busmerch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "americasummary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "551c.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "a-rwx.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akerl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "certifiedcourttranscriptions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aidiscore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cgplumbingservice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cat.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookovnica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chanrycz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "britishacademyglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluehawks.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bstakepool.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "airlytrip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allegorics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chrismorgancreative.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "busyr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "capitanlorenzana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bratgen.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chencraft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c-tec.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "city-journal.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "651s.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "affinitihive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chefkentrathbun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aetha.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amicusreporting.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canddeis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cianipartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clearpicturelegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canaletvonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adalpha.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calendriers10.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "canact.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chiltoncountyso.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calsense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clampgenerator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carbonrus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cincoautoinsurance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alusystems.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clearview.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coca-colasip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherzoukis.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhardyzoukis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudmanagedalarms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhzoukis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "activate.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherzoukis.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhzoukis.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhardyzoukis.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "choosingcrypto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhardyzoukis.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiadepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chriszoukis.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coffeeandteatogogo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chriszoukis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiacourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherzoukis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chriszoukis.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiavideoconference.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudmanagedalarms.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiavideoconferencing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "al-amal-group.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbialegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhzoukis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chriszoukis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiareporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "compuscripts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "737478.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherzoukis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christopherhardyzoukis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clspd.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advatechgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookimed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coloringbook.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calendarios10.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "columbiarealtimecourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "animac.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "connorreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cooperlitigationservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cleopatraescorts.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chaseventar.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "corbettreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "24x7serversupport.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cilaxreklam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antek.com.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreporterlosangeles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportingcompanydc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreporternet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportersnet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportersanjose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreporter-chicago.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportingcalifornia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "businessleader.asia", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "1rzs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportersorangecounty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "configbutler.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportingfirmscalifornia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chatelain.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advaitghaisas.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportinglosangeles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportingfirmsla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreporterssandiego.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreporter-newyork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besonline.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "52evar1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beesbuzzstudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtreportingmiami.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "am-impact.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bgmarket.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtstenographyschool.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baredykk.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptoseed.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "7comm.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "condominiorganica.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chriholt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alphaclean-hannover.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "critter.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudgray.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "courtesymasters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akutakviye.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cepra.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cztt.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybermavi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "candt.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cntras.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dallascourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cnais.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dallascourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dariusstoica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dariusstoica.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cykeldirekt.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cynqx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "datenwort.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aljawad.ci", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clients-speed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "colthesweep.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ddjmechservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "david-feldman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deco.tax", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clarkglobalcity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "653c.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cartaovem.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "andrija-gradecak.from.hr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2b9.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "claudiamartins.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depoalabama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ctera.download", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depo-one.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depo-lab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberfitness.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "236h.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depowebstream.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depoone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depo-on-demand.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depoondemand.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cinedecalidad.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depolab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crackstreams.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deposition.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daffodilcentre.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "democracyfund.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deporeporters.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deporeporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darren.to", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depositionreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depos2go.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depo.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coomer.st", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dav-tech.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dgaccess.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "covid19.public-inquiry.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "craftique.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cuktech.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cellcenterchampalimaudfoundation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamond-reporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "desarrollosintecsa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamondreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dealarious.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diannejonesassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "develust.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coachspiritual.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "argency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devstats.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digicrew.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamondreportingandvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diannejonescsr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consultg.ltd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clonex.wtf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dianejonesassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cranfest.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dinamarcus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aaplasticsurgery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diannejonesandassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consult.eng.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dahliasharp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybercard.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ampmsupport.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dailyvpn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "creativetaupo.org.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "demtech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "djonescsr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doernergoldberg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anticipari.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cvm.net.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dev-amag.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "documentdepository.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "donovan-court-reporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "donovancourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cosmochem.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "donovanreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dancehallproject.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drhogarth.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dmiaviation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dropshipbunny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doterra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drsom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drdb.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clinicalsolutions.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "creativo.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dahag.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akosuasankofa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devya.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberwahid.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doudun.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "277g.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dsy4567.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dining-it.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cvroadtrip.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disinfestazione.savona.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doctordb.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disinfestazione.genova.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daveaskew.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberkey.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daveaskew.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doctortmd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "davidaskew.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daveaskew.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybertip.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybers.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberfitko.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "127n.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybertip.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drakeallegrini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberserver.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disobey.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptocardz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberix.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "e-trialsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ecoventfix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "938b.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "e-trialsolutions.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "colaba.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disinfestazione.milano.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deviceeurope.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberix.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberpet.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cryptobox.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deutsches-edelsteinhaus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dancehall-attitude.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "edgeinteriors.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "991e.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darkacek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "durangonorthstar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dtctv.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "animazione.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dmarkmobile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emeralddesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doktermarjolein.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "054c.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltaevus.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "du.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dantri.com.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eclipse-foundation.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eclipse-foundation.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "duschdichtungsprofile.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "890u.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eclipse-foundation.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eclipse-foundation.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dxjdata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "46ww.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aatransfer.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "erguinsaat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diverzus.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dripship.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drglennlyle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "desknas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consultar-latam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epiqcourtreportingblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deadhighstats.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "envisionitagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "defintrade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diag.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "davaro.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crs.kiev.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "email2gallery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aesthetica.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esquirecourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dejavu.marketing", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dubwi.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "db-maritime.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evanscourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "duchveliky.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "event.coffee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etrialsolutions.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etrialsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easymove.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "djangosites.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exelreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easymovecontainers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "essenzarj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "casadostratoresjau.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exelreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "divit.com.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "domeradzki.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibits2you.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibits2you.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dioxilife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibits2u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibits2u.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibitstoyou.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dandypan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibitbridge.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coolthissummer.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "europesummary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digitalchefs.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bigcloudy.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibitstoyou.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fahadalazmi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dtbafrica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "996557.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exhibitbridge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "duchveliky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easytec-info.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "debra-sa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "developress.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fashionscrubscanada.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digiec.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easyfloors.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fastweb.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dracollectors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esafetyfirst.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fbowling.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "falna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epicesettout34.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "astronomiaculturalemediocielo.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dinoplanners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aimixglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "farrelf.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esteticajustino.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "124b.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "encryptio.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "first-services.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esiptvpro-max.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "endocarditis.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fireems.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elektrac.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "entheor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fiverr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elysian-systems.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flyddiction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esmart.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "econcept.li", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "florencelegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chateaunainville.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dorganico.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "florencecourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "capeoni.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eastcornwallsrt.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "entretiencta.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fireclub.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evolvmodular.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "englishstuff.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allofghana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chaloo.com.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evolvemodular.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fm.ht", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fboglich.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "educationtechblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fitz.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "espressotranslations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eshfc.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evospeak.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "67ak.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fisera.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomrepository.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomcourtreporting.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomcourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "estrategiasdigitais.net.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "filtrmyfeed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alittlecoldgel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fsatech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foxfoxgo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frltexas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "franklinboglich.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fatnerdstock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fluff.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fashionseoul.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foxdeli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "familyshopperstores.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eurekahomeappliances.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flepic.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "erosvet.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etude-bet.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fcr.pp.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atris.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ferizia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aulavitaly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dorukyazokullari.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epublibre.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cospier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exogn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esfl.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "danielalaves.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "evo-ai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faus-moliner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "georgiawinegeart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eagfinance.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fecskefeszekotthonom.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "genya.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreamofice.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fuhui-app.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fincore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "endorsec.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fmartin.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "engie-energia.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fietsenopfietsen.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eldamman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gingerhomemaking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cocinayservicios360.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etcltd.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frisaga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etcltd.edu.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gibsonreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foomtbal.futbol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globalcourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emoney.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "endorsec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fietsenopfietsen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "engagerm-prod-web-01.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "giannopoulos.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freedomsvoice.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emrider.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daintonparkgolf.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "findorff.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "enprobe.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ensuritymobile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "floriansanchez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gorebrothers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goreperry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gophersland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atypique-planete.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "easy-busy.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fkingprojects.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eshaanya.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenvillecourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grama.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenvillelegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenvillecourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenvilledepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gerrys.uk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gtslotcars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gadgeteval.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "growglam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "groveld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gtconsult.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emlakkonut.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "framomans.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ficharjmd.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "filosofisksamtale.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "encoreplus.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "euracraft.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fs4is64kdohkd3twjcr2jf57r64yrfsjihgezfcbhjhproz6cjxc24qd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getmylink.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gawinex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fivvalencia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fwdmovers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drsarpermete.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hahnbowersock.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gentrack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hahnbowersock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fundacionasilo.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gov.ky", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fixerbee.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emcremodel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "happysimplelife.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gualanexteriorremodeling.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "froep.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "germantaste.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fiscape.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "formulario-rutas.lat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaypawtism.lol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hbl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beanieshow.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heartway.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haferman.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hbedocs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goodfeatherfarms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gondal.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diginno.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gofin.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hazentech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gold99999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "glleiloes.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "domandalo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gestionalecero.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gld.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goodviolin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "friendlydecorator.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bluebellaba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hendersondepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gl7n.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gpthub.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flux360.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "enuhub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guidanceflammejumelle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hightechreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gabalakarvansarayhotel.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "franc-token.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hashbrownhaus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "greenmaquinas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goldcoast.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hkm-webdesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adquest.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hitechreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gosforthlocksmithservice.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hajery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haleema.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hafrito.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hoogsreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heartofamericaservicecompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "car-solaire.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haneenshirt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bolivarstudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homesafedryerventsac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hostitcreateit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestway-disposal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "highgardengabala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "h3thai.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "honorlock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "honorpackages.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homomedicus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hkm-webdesign.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heylogin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "germainedecapuccini.com.kw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grenti.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "geografrenzy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heaan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "digitalmarketingagency-consultant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hutchingscr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hutchings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fotoinfo.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gynera.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iac-indooraircare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gedc.wa.gov.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grundrauschen-publishing.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gsmsolutions.co.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goshiba.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gobox.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caravane.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indigenouswell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hobarttownhotel.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ielenia.lgbt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grupoalbedo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "h2oracing.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immigration.com.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helmonline.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heinopeters.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eijil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ianphd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "efesan.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "india.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indymassagebangkok.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "init.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "housebuilder.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elinux.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bossmoncton.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hibiny.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helmonline.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "integrityoklahoma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "internationaltefltraininginstitute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "halocrm.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heinop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goodsfox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "insights.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helmonline.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iglesiaevangelica.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hjalta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intlliesafesolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "googsi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inuyasi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emba.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huntersam.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iitcr.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "islandbyreportex.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intsurfing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "islandbyreportex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "herbdish.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "granplaza.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heino-peters.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "islandreporters.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iitcr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "islandreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grassberry.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hotsnack.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etiquetaswithlove.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helmonline.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globetrotting.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jackwell.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hoken-fujishokai.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infinity-photography.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hydrosense.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hicklinghacks.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "imcruzb2b.center", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ho10.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "150mpg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "healthymadetasty.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inarigal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ifactfind.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cybersolve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isleoftheserpent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itcarolina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drjessicalattman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "it-help.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ichizenn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ifactfind.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intgr8ai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itransplant.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "idraulico-roma.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "imajelektro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jedayoshi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ismetroburning.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jedayoshi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hrminohub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "invariax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jilio-ca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "intilaq.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jilio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jilio.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infpik.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jilio-ca.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hairekeskus.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "irontv.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "improvisatorsdub.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jeffhaferman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huesos.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hrackac.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jeffreyhaferman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immo-ullrich.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "johntorres.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immersive-vision.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hondentrainingpootvoorpoot.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ivygarden.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isesmt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joaquinpaya.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jracsr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joywahrestaurant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "giannopoulos-realestate.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jaltest.com.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jusfifun.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fidelity-services.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "internethosting.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itsbas.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impiantitel.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iparcs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elpugli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsreportingservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsbyreportex.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsbyreportex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsreportingservices.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kamloopsreporting.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hospicjumzory.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "june.dating", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kayenta.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaneandtrap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "golkowreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaufmanandassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isanp.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jbfung.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hattayoichi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "izo.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jacksonbarreto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "imjosepho.lol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "finakalendrar.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kevin-ji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kevinji.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kelehers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kedimail.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consumerrights.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kashable.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "knipescohen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kavaofi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fruehconstruction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isrokapa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hotteprofessionnelle.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "codo.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immochrysalide.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huurdersverenigingsneek.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cododigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jezykoteka.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jjcf.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justbe.scot", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kramm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kcchung.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "festivalofthefleeces.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "helpfulinsightsolution.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "institutoiboru.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kollab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "festivalofthefleeces.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jaxmore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kasplacement.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "konectus.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lakecitydepositionreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landireporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jukisewingmachines.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infoteck.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inter-flag.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lastpetal.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "innominatum.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jobapps.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keratee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keb-drive.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kollab.com.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawstudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kmerkuri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawstudio.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kurumsalsayfa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawcollaborator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jungamer.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laplanificadora.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jpc0.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lareporting.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justarchi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "corpvs.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kazfeed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jonesanddarche.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landandcreek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legalclassroom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kot.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legalcollaborator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legacyselfservicegarage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kantelhekwinkel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legaldigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawgic.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legalrecordservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kmya.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kalisiconstructionltd.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lhm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporters.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporters.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporter.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "komo.am", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporter.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporters.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inspireedcenter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lexreporter.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ksashirt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laravel42.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "innovativepergola.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jobrs.edu.iq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kemono.cr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "likeour.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "linksbfinance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leemjaz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justinkidd.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lafafutu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gnosis.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cbmindia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lessharp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "litigation-services.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lit-services.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lit-flix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laoda.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "litigationservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dieseltms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kirstenwillner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kancelariawlt.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hestiahealth.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kutzer-consulting.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "krupinek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "koraalduikers.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kultur-vor-ort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "losiersealcoatingservices.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kongkritpost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kubiqo.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lars-preussner.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kalender10.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "losangelescourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lovecourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ersalgar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "krokiet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "klikajkupujonline.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kuchynak.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lore.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lrsnet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ljcybersolutions.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jabonariumshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hwehealthiertogether.nhs.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laperlaabaya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laptopantoan.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jeuxsuperwin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kv188.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inovatasarim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "juriskc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "labellust.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kenshin.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "letinsys.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loredrop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawinordercom.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luciara.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lawinorder.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lagardere-tr.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laser-surgery.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laboratorium-stuttgart.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luxest.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lforla.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "johnsautoparts.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lindsaylakeinspections.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "klgpecas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "linbobo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malami.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luongtuananh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leeghwatermusicals.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "licencatop.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manhattan.institute", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madisondep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kettlebellspower.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mandh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "listruct.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "londondampspecialists.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maprao.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kayziarra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emaandclay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaz-energo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impoweredhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liups.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "macdn.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elearning.taipei", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "koukei.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kliker.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lixu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lilize.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "littlecash.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livealarm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livada.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "makeupstoremx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liyong.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marymagdaleneshrine.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "i-wordpress.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "koppenhouse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itracks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mashariqalsaad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loador.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lostwood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ltrickett.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lomat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longjing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lompat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lixiang.in.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcguiresii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manlab.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "logindefense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcgrathnicol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mccreadylaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kallipso.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "innovamarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luckyfeel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mangrum.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lrs.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marinaspodcast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "macrofly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lushspaces.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leantinebastiaans.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k-scar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matber.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lucky7s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madeforthefuture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lubrary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landschaftsbaugartenbau.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leistungslotse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lksoft.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mentionlink.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m4c.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meanmugauto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lothiandisabilitysport.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meowmc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "localspicery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ltx-dev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mansage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lyyb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manupgrade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kulthome.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mbabullshit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maildrop.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mediationwithmeg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mail365.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "managedtreasures.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metrocourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melp.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melp.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metrodepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "majnooncomputer.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meritcourtreportingandvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meritreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "merittexas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maisondidon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hip-happy.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metropolitanreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "littery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magicpet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mhforce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lotrarts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "microprofile.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magnumsol.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lameuniform.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mebin.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "listany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lutarym-romane.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mebin.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mebin.studio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lorizean.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longevita.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "may-online.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "markzuckerbergisabitch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "makkenzo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minato.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minneapoliscourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "masotee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metrocityhotel.az", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mineads.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longevitadental.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "masaki1684.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mmoarab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "michael-gerard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mifi.holdings", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mikefrank.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitsu.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitsu.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitsu.asia", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mobilesetdepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moexian.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitsu.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lotrsketch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meowescorts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitsu.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "layabe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathfilm.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "miova.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kyxtro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "molezzo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mevsim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mkt.cx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moztopup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mifi.ventures", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longevitahairtransplant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "missionboss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "multicom.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metisengineering.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laurenparkerway.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mumur.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megasova.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metalwarfare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mslegalsupport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mwxjacg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mujeryempresa.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "morgen.so", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "morsel.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mauritius-luxuryestate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "martinvalen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mundomascotascr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myali.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maxcupons.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mechainics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megacek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megamarketonline.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mertalisahin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mydeposition.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moviego.ws", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mydepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "micronfts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fazah-conseil.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mindq.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megacek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megashopy.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mgm-slipac.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myremotereporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mysarnoff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "misstaiwanese.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mobidevices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "memes.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mvwoensel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nahmii.dj", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myrxnote.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "miaosuan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myrina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "miaoshi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ipso.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moodmagicmusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loversofwhisky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mpan.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationaldepo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationaldepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myveritext.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myveritext.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationaldepo.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nancysorensenreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mylocalpro.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationalvideoproductions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationalvideoproductions.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mirtouf.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mofarennen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathieu-oriol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "midalidaremed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marquisepatisserie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationwidedepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ncaaclaimsettlement.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melcom.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melcomsmit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "n64.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mainsec.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neesonchambers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mobilityworks.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "michaelwillner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mike-stobbe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neesons.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neesonsmeetings.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neesons.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "michael-willner.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "macarthurgi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "masterpfsense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcaz.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtzy.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netcourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neesoncourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netcourtreporter.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megacompany.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "morgu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meuitinerario.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myfireclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newflyergroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mr-kraken.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newyorkreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "miminek.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mentorzografos.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mk-homelab.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "motostorie.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moodlecfp.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nirbhayamc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meilleursenlignejeux.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myloux.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monopolyjuegos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nexadevs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "montemoriah.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matfiz.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nahmii.dog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "normanemark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nseicc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mainstreetauto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mindbodysoul.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "norterafoods.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muxicloudy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "microinstrument.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minsmukkekalender.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mokawenat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mastermind.ac", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netse.net.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nlp.photos", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justforgrinsortho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "meine-unternehmensberater.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moodlegnr.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mujeryfamilia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ncshosting.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "integrativetherapy.com.mt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mini927moon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ning.bo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "naturavelit.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obfc.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ninegravity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nosial.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mokawenat.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ocaladepositionreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foiz.gov.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keyabode.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oddlogic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nstiak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "isnap.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nomadtechnologies.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "multigura.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nayakaaerial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neopredix.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "methodwise.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "olympicreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "niceviolin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mundocaprino.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "okgun.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nexafuze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mre.to", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myseat.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ontariocourttranscripts.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "openpix.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "melhorescasino.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutleyhistoricalsociety.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "montmeyran.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "norcalsigmabluefoundation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orange.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "openmdm.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangelegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangelitigationsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oldiesnest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangelegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mysilvershield.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "no5251.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangelegal.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ontariocourttranscripts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangelegal.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangetrialtechnology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neelen-gym.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangetrialtech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orangereporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "operatorlabs.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neverhack.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "openmdm.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "northsecure.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nhos.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nuzpost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nooktee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neovation.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lagarblanco.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oakey.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metecnoamericas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "notida.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oneremit.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nvdxs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nfrdoz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iconpln.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ohleschefs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nd.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nellydental.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ohvoice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oanamancu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "offshore.hosting", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paddle.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mabrav.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paradigmreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinesim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obercodosguardas.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parisereporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "palisadespaint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oldsoul.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "open.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "namplan.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pacinka.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "patromed.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pattiblair.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nishinija.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pcrla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paradigmworldmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nestos-marble.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinesloten.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "painresearchforum.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcba.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kemikon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pensago.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opencartvip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padujobs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "personalcourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nyver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oe1rhi.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parenthaven.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lblok.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onedice.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pagtee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petribelove.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phastidio.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ozelderskocum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pemagear.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oasisgt.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "naszezgnilebloto.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nawadata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nelt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parentsupervisa.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nurbpropaganda.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moroccotravelguru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pimpyworld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourkidsourcall.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padujokes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panpower.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nordicpartners.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live-with-water.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pakalolo.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pachamamita.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pesschap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padujob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nileempire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "herbigummy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padushop.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "omxz9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "omind.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduserver.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padutip.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "png.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padushop.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padutip.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduwitze.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pc-reparatur.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padutip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationwidevideoproduction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padushop.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padushop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pepecoinnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nationwidevideoproduction.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padu.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powerdepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "planeteclipse.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "precisebusiness.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "originaltulsimala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "postman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pradcooutdoorbrands.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "presson.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "padushop.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "precisiontrialsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perimetersitesecurity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nghiengacha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "orhunturker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pemex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proxymonitor.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phpunit.expert", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "primewebdesign.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promolta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pissedoff.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petrachuk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oagarden.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "planning.construction", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proxylink.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plugmonkey.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peoplecheck.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peoplecheck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mauboussin.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pts-trial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pvpheroes.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "psigma.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perinkac.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poolcalculator.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "portatee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pizza-cali.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powerman.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moyce.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qauk.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "piccolospace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "odiqco.com.bd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "precaston.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perpedal.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "juanjesuscarrasco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "partyzarohem.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "octobit.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "premier-stores.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "preweather.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peters-halstenbek.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "privadency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quantaver.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qed.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prazer24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "privatedns.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "privatehost.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pt.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ranchobernardoseniorservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petleasehub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "privatespace.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rds-legal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proxylink.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "realvestors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ontarioreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oleopalma.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rda.run", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "practera.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rakosi2.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pulci.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pos-hgb.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mangator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "recipiently.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pharma-management.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pro8-sfets.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "profilfueller.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "regg.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quasarnet.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quasartech.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redwoodreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plenatus.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "queens-games.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "queertreff-hst.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pasaya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rennillo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rennillorecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quasar.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexagencies.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexagencies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qrv.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexhq.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reallyze-se.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qisda.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportervideoconference.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qm-lebenswert.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportersonmadison.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexhq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "printkalender.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "porncomichub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexagencies.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "macroad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "resumehelp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefence.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefense.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportex.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefence.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reportexagencies.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefense.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mqroofing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richardsondev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pulsarracing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefence.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qisda.com.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "penzkeresok.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quest-crusaders.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reliancecard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "microdestek.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redlineairdefense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richardleereporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richardsreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qumind.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ringeriksbanen.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prodiagnostico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pureunpay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pro8-eservices.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rockhilldepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rockhillcourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redsealine-invest.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madagascarbycar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rockhilllegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "permak.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "radroute.hamburg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rrgtampa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pouzdrac.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qdcc.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "restoremykitchen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raisecalculator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "runmyprocess.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rodoslive.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royalreporting.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roles.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manyu.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "londis.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raquest.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rxss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rxssplus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paduplace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ramib.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reane.pp.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newline.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "santabarbaracourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "santabarbaracourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rhscz.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "papuaekspose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reelranking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prg.aero", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rmj4u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sarnoffcourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "resk.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sccourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpnewspaper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "santoskhoury.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scdepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sccourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reggae-live.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scheduleareporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salesslicer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sclegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scheduleacourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "samialahmad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scheduledepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sclegalvideography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sccourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scvideoconferencing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raadsveld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rokz.ly", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scvideoconference.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scvideodepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schedule.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rekli.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poshasaudi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oicltda.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quarkdev.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seckrypto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "restaurant-ergo-bibamus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rlvascodagama43.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rozpieraki-hydrauliczne.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redrockrentalsllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megestrol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roadkeeper.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raven.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mhc.ab.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rlvg43.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ricuve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rikuwe.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scanform.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secureeclaims.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rebeccacurtismoss.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mozand.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seplatenergy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pl-beauty.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rikuwe.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rikuwe.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rikuwe.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rishikeshyogavalley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "resistsa.blue", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seotrainingcamp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scarrabili.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "protestoquiteagora.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sferastudios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "menghao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perinkac.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "picturesat11.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "semine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sawan.com.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saffron-crocuses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shahinihariandchopsticks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saveeachlife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "riusma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "safeinity.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saab-cars.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "novapaycr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scubadiving.news", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shifti.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sandokan.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "missswan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanyangwood.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saucesmaster.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rib-cosinus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shippingenius.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scansec.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roshmed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scootdelivery.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "signaturecrs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sgomberafacile.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sho-ji.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salvatorenoschese.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simplyveritext.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scooterhelmkopen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rwandalicious.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skattebomedia.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "secondhandfuermaedchen.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skattebomedia.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skattebo.media", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skattebomedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sidrona.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seabonvillas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sidedoorapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sheetflowpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slocourtreportingandvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schnittger-digits.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sirincleaning.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reboot.it.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "royalstockaysaintgeorges.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "show.ly", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sefaratvisa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scodeno.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ruempelbutler.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shadowsocks.ac", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sempreg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sende.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snipclip.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "septimus.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shirtkaya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "screaltimecourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sendpass.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qtocdn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snekul.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sandplane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sharenexus.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "solutionbuilders.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sahipleniyorum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "signdeer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simple.co.cr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shangren.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinalegalvideographer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinacourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "siafe-desa.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinalegalvideography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinavideoconference.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinareporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinarealtimecourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinalegalvideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinadepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sdsapa.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinacertifiedcourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "southcarolinavideodepositions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "semagna.gratis", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skill8.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slopable.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plast-pallet.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sousvideways.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soportesparapantalla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smirkhat.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skinonline.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "socialsecurityalerts.news", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smarthomegeldermalsen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sglcpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "srinisprojects.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sedigit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stacktobuy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "seedersinstruments.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "so-design.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanibio.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "srtfund.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snchc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simpsonizeme.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sscourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spektrasandbox-prod-web-01.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oncalldoctor.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simaris.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "springfieldpc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starbucks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stgb.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "steldingreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stanthestuccoman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "securitykane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stavbymilota.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starnora.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starnoraelizabethfitzpatrick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skonstant.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sir.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plemedia.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "staging-amag.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slotenspeciaalzaak.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sporthypehub.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rafaeloliva.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "superdogsphotos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "st-mickalos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smallguard.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stream2watch.media", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunshinereporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sweetmedicinefarm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stanard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunshine-reporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skyscanner.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svnrb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spamshield.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softpas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sekiei-lifeservice.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slotenspeciaalzaak.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swordhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "parisshop.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stonehengelabs.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smart-media-consulting.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sportverein-abtshagen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smartphonesecretary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sprind.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swibble.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "substratesystem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softwaregiant.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sparxsystems.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sportellocafpatronato.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sparxsystems.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tarrazucafe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sauvequicoupe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nimb.com.np", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "targetlearning.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "springinklee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shopbeachwearonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tdbcr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sueniosmundiales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starlight.qpon", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taylorruhland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "summersagamods.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nibl.com.np", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "t666.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stuccorepairrenonv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunioso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "talleresgonzalezyparis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tapinjury.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testimonyiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testimonyiq.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stiaans.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "storiesofglass.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sui2yoyaku.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testimonyiq.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tedscams.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promocaodesconto.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texascourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snrat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sdsapa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "piedrasconencanto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "texascourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telegram-sms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starinup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "techcaresolutions.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sudokuenlinea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thegiantmovers.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tenrod.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simsid-partner-adpapi.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stenographers.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theemployeeapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinobrake.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thepetgal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theslotz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thejevn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "staysimple.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "syntriqhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thegrapplergear.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sibifood.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thorneycroftsolicitors.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svarnainstitute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teladochealth.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theglobalwin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teehar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "talktime.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tibrag.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinobrake.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teeneom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sosyalevin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spacecoastdumpsterrental.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teekadeus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teesambo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teehany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "synvitam.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thronia2.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snrlaw.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thebutton2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tinkeratlas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tabelaofert.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thenewenglandpalletguy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thestudio.hopto.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tahlili.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "redhotmerch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theimagroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tainevenings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "startupnow.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svoystart.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinobrake.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stellamobilya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timotheory.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soka.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tenckhoff.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tehnolavka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "torontocourtreporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "torontocourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tigerdownelectronics.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "torontocourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tokoupis.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timescrypto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tourneybit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teampadu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telefonino.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thedaily.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pestwerkz.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tabaknatie.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trialpresentationservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telconews.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smokonz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tristack.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sysfreight.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trustcrest.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "telesys.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "serviceagahi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tourney.now", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "timotheories.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tryterracotta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thoged.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "technovar.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tigitata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsiakoulias.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsiak.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tecklinks.com.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsiakoulia.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thesovereigns.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thewww.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tini24.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tuscaloosacourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsiakoulias.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "temizim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stronypiotra.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thuexehuyminh.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tildavps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toldos-lagavia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "triplebit.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twonum.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "topi.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ti-aiuto.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "triplebit.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toldoslima.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "txsgmemorial.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unitly.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "plniconplus.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "upguardinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unacasitadepapel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theplantation.org.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unitedreporting.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theuniqueform.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unmatched.ventures", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usadepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theremnantrise.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "u2y.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usadepo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "turbion.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "umlautpress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testiqu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vankerrebroeck.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "touchmagazine.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trabzoncatering.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "transgendernetwerk.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "throwable.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "u.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spheraes-amc.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toolhubz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thehomeassignment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velos-sa.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velosae.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tafhoodies.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "venturacourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velos-ae.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velos-toxo.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "validateleads.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tudosobreroca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svk.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thesupportplatform.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextcloud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trafficmgr.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "venturacourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vei.st", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradeiq.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trenchbunnies.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextdmz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritext.legal", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextconnect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velosrealestate.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextcloud.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextlegal.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verbatimreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextcorp.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritext-la.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uebersetzungsshop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritext-ny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "princehenrycentre.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextllc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritxt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritxt.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vertitext.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soel.wa.edu.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tornado.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "strongguardsecurity.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextcorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "victoriareporting.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "therapeute-emdr.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "victoriareporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "traveltolearn.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stamina.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uktek.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tansin.co.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "videographernet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "views4you.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "updatedrecipes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uelzen.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vidacalendaria.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vidispine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "venalo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trungtammuasam.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tunster.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tuk-tam.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "victorwynne.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uaprava.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritextcommunitynetwork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "u-motions.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tuimpulso.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vltx.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vacpackmedical.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viaconecta.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urbex-bretagne.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tripstorome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "umeloagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "startupnewstamil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ultratek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uureka.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velossa.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w0arr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "voboxcore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wandersolo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stelcron.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wallstreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trainocate.co.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valueplanet.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "virgo-agency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sqtelcrm.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urosevesprave.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verfilme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vascodagama43.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wasilewskicourtreporting.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "traceurdirect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wasilewskicourtreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wasilewskicourtreporting.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wasilewskicourtreporting.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tokshop.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wcreativestudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warbot.party", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ugra.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webrage.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "truthtake.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uclan.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "typika.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "viprow.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vinzlocks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "testimonyiq.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valueplanet.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "utko12.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wfgukasha.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vinzhelmets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stagnesholidaypark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vipbox.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vg43.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ttjnextgenjewels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tornellandcotten.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vezirkopru.bel.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wakaya.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whatismyip.help", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unukase.ac.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "winterreporting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vivien-gault.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "velutina.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wirecable25.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thewellbeingarchitect.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woovi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woodrandall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "versicherungsmakler-in-flensburg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "universidadpopular.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vitaly.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "worlddepo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritext-dc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weakspots.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wixboo.com.gt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verumwomen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vooreenbeginner.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wreeper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vertitext.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veritext-nj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valuemomentum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "workathomesmart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vertitextllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wi.ki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "voidix.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vw0.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watchtower.pm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wreeper.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wash-express.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waca.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vorandor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weatherstylist.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "welcare.co.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "west-edge.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usamgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vntdp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpressive.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--punschkllaren-hfb.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vts-solutions.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "welsum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xtec.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wabco-auto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yanopoulos.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wichm.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waverity.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yannopoulos.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--2o2b11i93dh3r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "voordehand.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tkcm.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xxll.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wildberries.lol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vertmedical.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vtipkar.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waca.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "winterarbitrationcenter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wowecuador.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ydsbookstore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wolfen-nord.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "werkenbijbrabantsedelta.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "threelayers.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whitehartgreatyeldham.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yatescsr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xord.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "virtualimokykla.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yatescourtreporters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whychoosebob.id.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wiazarymt.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yoriso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watchdreamer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--woffi-kua.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wendywomensclinic.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiluo-sweet-home.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theslotz1.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wir-sind-frey.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ys.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "versatilestructures.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xpertgears.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wero-wallet.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ys.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youcare.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "videonieuwsbericht.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoeamar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yamasa-kanten.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wetryrecipes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vehimmo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohobookings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocatalyst.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xelionai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoholearn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoflow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeeloo.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocrm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woolcollection.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohodesk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--cmc-grn-s2a.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohostatic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohodocs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocliq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoconnect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yeditepehastaneleri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocreator.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohodirectory.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeroq.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohomeeting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoanalytics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohomail.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocalendar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocontracts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohothrive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohopeople.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradersgate.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohonotebook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoinvoice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webstarsltd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoexpense.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wmcurrency.exchange", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohobooks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoinventory.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohosprints.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoworkplace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohosign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohosheet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohosites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourbusinessblueprint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--d1aia1akb.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohosurvey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoshow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoprojects.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohowriter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wolf404.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohodomains.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocheckout.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohovault.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohocommerce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yaseminuzumcu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohorpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yakumed.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zalex.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoones.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "younesclothing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xsymm.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theslotz1.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--b1agjubigbu.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yogavluggertjes.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xmlchartsdev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zerevia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yxl.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wb-partner.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--80acddhuaxb3abbp8a.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waysandmeanstechnology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zitzhen.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waynecochran.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zing.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zonaardebasisschool.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoho.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourfood.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vinaconce.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "welovelowcarb.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiaoseai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yourvirtualgm.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snaboitiz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zolsec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiaoda.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "w3z.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yiannopoulos.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zap51.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--hirekeskus-q5a.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zooopt.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zynqit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoho.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "somovie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zouair.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yenphat.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ydspublishing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vetrnikyrychleby.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zur.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zur-kazan.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zafariqbal.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wembanya.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zur-ufa.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zzbaiyun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youiv12.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youiv14.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yan.edu.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "techtwo.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yydjtc.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "volontarisme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softenger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xylexa.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vectorforecast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradingaldia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tim-seeger.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tokenlytics.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trueprogresstherapy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "true-time.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zadu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urotek.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wgs.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zkz.kz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "villadbay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "selloenseco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "web-testpage.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waisl.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vanessabandarra.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "win.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zohoforms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usilevi.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vreestyle.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wpconnect.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ulibro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/remoting/host/linux/dbus_interfaces/BUILD.gn b/remoting/host/linux/dbus_interfaces/BUILD.gn
index f6cb5e7..08dcc5c 100644
--- a/remoting/host/linux/dbus_interfaces/BUILD.gn
+++ b/remoting/host/linux/dbus_interfaces/BUILD.gn
@@ -12,6 +12,7 @@
   sources = [
     "org_chromium_TestInterface.h",
     "org_freedesktop_DBus_Properties.h",
+    "org_gnome_Mutter_DisplayConfig.h",
     "org_gnome_Mutter_RemoteDesktop.h",
     "org_gnome_Mutter_ScreenCast.h",
     "org_gnome_ScreenSaver.h",
diff --git a/remoting/host/linux/dbus_interfaces/org_gnome_Mutter_DisplayConfig.h b/remoting/host/linux/dbus_interfaces/org_gnome_Mutter_DisplayConfig.h
new file mode 100644
index 0000000..0076fe48
--- /dev/null
+++ b/remoting/host/linux/dbus_interfaces/org_gnome_Mutter_DisplayConfig.h
@@ -0,0 +1,243 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file was generated from org.gnome.Mutter.DisplayConfig.xml
+
+#ifndef REMOTING_HOST_LINUX_DBUS_INTERFACES_ORG_GNOME_MUTTER_DISPLAYCONFIG_H_
+#define REMOTING_HOST_LINUX_DBUS_INTERFACES_ORG_GNOME_MUTTER_DISPLAYCONFIG_H_
+
+#include "remoting/host/linux/gvariant_type.h"
+
+namespace remoting::org_gnome_Mutter_DisplayConfig {
+
+// method
+struct GetResources {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "GetResources";
+  static constexpr gvariant::Type kInType{"()"};
+  static constexpr gvariant::Type kOutType{
+      "("
+      "u"                   // serial
+      "a(uxiiiiiuaua{sv})"  // crtcs
+      "a(uxiausauaua{sv})"  // outputs
+      "a(uxuudu)"           // modes
+      "i"                   // max_screen_width
+      "i"                   // max_screen_height
+      ")"};
+};
+
+// method
+struct ApplyConfiguration {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "ApplyConfiguration";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"                // serial
+      "b"                // persistent
+      "a(uiiiuaua{sv})"  // crtcs
+      "a(ua{sv})"        // outputs
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct ChangeBacklight {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "ChangeBacklight";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"  // serial
+      "u"  // output
+      "i"  // value
+      ")"};
+  static constexpr gvariant::Type kOutType{
+      "("
+      "i"  // new_value
+      ")"};
+};
+
+// method
+struct SetBacklight {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "SetBacklight";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"  // serial
+      "s"  // connector
+      "i"  // value
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct SetLuminance {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "SetLuminance";
+  static constexpr gvariant::Type kInType{
+      "("
+      "s"  // connector
+      "u"  // color_mode
+      "d"  // luminance
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct ResetLuminance {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "ResetLuminance";
+  static constexpr gvariant::Type kInType{
+      "("
+      "s"  // connector
+      "u"  // color_mode
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct GetCrtcGamma {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "GetCrtcGamma";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"  // serial
+      "u"  // crtc
+      ")"};
+  static constexpr gvariant::Type kOutType{
+      "("
+      "aq"  // red
+      "aq"  // green
+      "aq"  // blue
+      ")"};
+};
+
+// method
+struct SetCrtcGamma {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "SetCrtcGamma";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"   // serial
+      "u"   // crtc
+      "aq"  // red
+      "aq"  // green
+      "aq"  // blue
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct GetCurrentState {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "GetCurrentState";
+  static constexpr gvariant::Type kInType{"()"};
+  static constexpr gvariant::Type kOutType{
+      "("
+      "u"                              // serial
+      "a((ssss)a(siiddada{sv})a{sv})"  // monitors
+      "a(iiduba(ssss)a{sv})"           // logical_monitors
+      "a{sv}"                          // properties
+      ")"};
+};
+
+// method
+struct ApplyMonitorsConfig {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "ApplyMonitorsConfig";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"                   // serial
+      "u"                   // method
+      "a(iiduba(ssa{sv}))"  // logical_monitors
+      "a{sv}"               // properties
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// method
+struct SetOutputCTM {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kMethodName[] = "SetOutputCTM";
+  static constexpr gvariant::Type kInType{
+      "("
+      "u"            // serial
+      "u"            // output
+      "(ttttttttt)"  // ctm
+      ")"};
+  static constexpr gvariant::Type kOutType{"()"};
+};
+
+// property
+struct Backlight {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "Backlight";
+  static constexpr gvariant::Type kType{"(uaa{sv})"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// property
+struct Luminance {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "Luminance";
+  static constexpr gvariant::Type kType{"aa{sv}"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// property
+struct PowerSaveMode {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "PowerSaveMode";
+  static constexpr gvariant::Type kType{"i"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = true;
+};
+
+// property
+struct PanelOrientationManaged {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "PanelOrientationManaged";
+  static constexpr gvariant::Type kType{"b"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// property
+struct ApplyMonitorsConfigAllowed {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "ApplyMonitorsConfigAllowed";
+  static constexpr gvariant::Type kType{"b"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// property
+struct NightLightSupported {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "NightLightSupported";
+  static constexpr gvariant::Type kType{"b"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// property
+struct HasExternalMonitor {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kPropertyName[] = "HasExternalMonitor";
+  static constexpr gvariant::Type kType{"b"};
+  static constexpr bool kReadable = true;
+  static constexpr bool kWritable = false;
+};
+
+// signal
+struct MonitorsChanged {
+  static constexpr char kInterfaceName[] = "org.gnome.Mutter.DisplayConfig";
+  static constexpr char kSignalName[] = "MonitorsChanged";
+  static constexpr gvariant::Type kType{"()"};
+};
+
+}  // namespace remoting::org_gnome_Mutter_DisplayConfig
+
+#endif  // REMOTING_HOST_LINUX_DBUS_INTERFACES_ORG_GNOME_MUTTER_DISPLAYCONFIG_H_
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 420c9c80..424f755 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include "base/check.h"
+#include "base/compiler_specific.h"
 #include "base/debug/crash_logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/safe_sprintf.h"
@@ -58,6 +59,7 @@
 #endif
 
 base::debug::CrashKeyString* seccomp_crash_key = nullptr;
+base::debug::CrashKeyString* seccomp_ioctl_crash_key = nullptr;
 
 inline bool IsArchitectureX86_64() {
 #if defined(__x86_64__)
@@ -210,6 +212,31 @@
       __FILE__ ":**CRASHING**:" SECCOMP_MESSAGE_IOCTL_CONTENT "\n";
   WriteToStdErr(kSeccompIoctlError, sizeof(kSeccompIoctlError) - 1);
   PrintAndSetSeccompCrashKey(args);
+
+  // Log information about the file descriptor.
+  char message[256];
+  size_t message_len;
+  default_stat_struct stat_buf;
+  const int fstat_ret =
+      syscall(__NR_fstat_default, static_cast<int>(args.args[0]), &stat_buf);
+  if (fstat_ret == 0) {
+    MSAN_UNPOISON(&stat_buf, sizeof(stat_buf));
+
+    message_len = base::strings::SafeSPrintf(
+        message,
+        "dev=0x%x,ino=%d,mode=0%o,nlink=%d,"
+        "uid=%d,gid=%d,rdev=0x%x,size=%d,blksize=%d,blocks=%d",
+        stat_buf.st_dev, stat_buf.st_ino, stat_buf.st_mode, stat_buf.st_nlink,
+        stat_buf.st_uid, stat_buf.st_gid, stat_buf.st_rdev, stat_buf.st_size,
+        stat_buf.st_blksize, stat_buf.st_blocks);
+  } else {
+    // fstat failed, log the errno.
+    message_len = base::strings::SafeSPrintf(message, "fstat failed, errno=%d",
+                                             -fstat_ret);
+  }
+  WriteToStdErr(message, message_len);
+  base::debug::SetCrashKeyString(seccomp_ioctl_crash_key, message);
+
   // Make "request" volatile so that we can see it on the stack in a minidump.
   volatile uint64_t request = args.args[1];
   volatile char* addr = reinterpret_cast<volatile char*>(request & 0xFFFF);
@@ -524,6 +551,8 @@
 
   seccomp_crash_key = base::debug::AllocateCrashKeyString(
       "seccomp-sigsys", base::debug::CrashKeySize::Size256);
+  seccomp_ioctl_crash_key = base::debug::AllocateCrashKeyString(
+      "seccomp-sigsys-ioctl", base::debug::CrashKeySize::Size256);
 }
 
 const char* GetErrorMessageContentForTests() {
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc
index 5a0fe9f..391d9ca 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc
@@ -9,15 +9,26 @@
 
 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
 
+#include <fcntl.h>
 #include <linux/net.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <utility>
 
 #include "base/check_op.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
 #include "base/strings/safe_sprintf.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_stat.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
@@ -119,6 +130,41 @@
 #pragma GCC diagnostic pop
 }
 
+class CrashIoctlPolicy : public bpf_dsl::Policy {
+ public:
+  CrashIoctlPolicy() = default;
+  ~CrashIoctlPolicy() override = default;
+
+  ResultExpr EvaluateSyscall(int sysno) const override {
+    switch (sysno) {
+      case __NR_ioctl:
+        return CrashSIGSYSIoctl();
+      // The handler needs write() and fstat() for logging.
+      case __NR_write:
+      case __NR_fstat_default:
+        return Allow();
+      default:
+        return Allow();
+    }
+  }
+};
+
+BPF_DEATH_TEST_C(
+    SigsysHandlers,
+    SIGSYSIoctlFailureLogsFdInfo,
+    DEATH_SEGV_MESSAGE_PATTERN(
+        "*dev=0x*,ino=*,mode=0*,nlink=*,uid=*,gid=*,rdev=0x*,size=*,"
+        "blksize=*,blocks=*"),
+    CrashIoctlPolicy) {
+  base::FilePath temp_path;
+  CHECK(base::CreateTemporaryFile(&temp_path));
+  base::ScopedFD fd(open(temp_path.value().c_str(), O_RDONLY));
+  CHECK(fd.is_valid());
+
+  // This ioctl should be trapped and cause a crash.
+  ioctl(fd.get(), 0, 0);
+}
+
 const char kSigsysMessage[] =
     "nr=0x42 arg1=0xffffffffffffffff arg2=0x0 arg3=0xabcdef arg4=0xffffffff";
 
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index 4a6305c..f04066c 100644
--- a/sandbox/linux/tests/unit_tests.cc
+++ b/sandbox/linux/tests/unit_tests.cc
@@ -7,6 +7,8 @@
 #pragma allow_unsafe_libc_calls
 #endif
 
+#include "sandbox/linux/tests/unit_tests.h"
+
 #include <fcntl.h>
 #include <poll.h>
 #include <signal.h>
@@ -26,8 +28,8 @@
 #include "base/debug/leak_annotations.h"
 #include "base/files/file_util.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/strings/pattern.h"
 #include "build/build_config.h"
-#include "sandbox/linux/tests/unit_tests.h"
 
 // Specifically, PNaCl toolchain does not have this flag.
 #if !defined(POLLRDHUP)
@@ -63,6 +65,16 @@
   return num_threads;
 }
 
+// Helper for DeathSEGVMessage and DeathSEGVMessagePattern.
+// Checks that the process died with SIGSEGV.
+void CheckDeathBySEGV(int status, const std::string& details) {
+  const bool subprocess_got_sigsegv =
+      WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status));
+
+  ASSERT_TRUE(subprocess_got_sigsegv)
+      << "Exit status: " << status << " " << details;
+}
+
 }  // namespace
 
 namespace sandbox {
@@ -299,18 +311,24 @@
                                  const void* aux) {
   std::string details(TestFailedMessage(msg));
   const char* expected_msg = static_cast<const char*>(aux);
-
-  const bool subprocess_got_sigsegv =
-      WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status));
-
-  ASSERT_TRUE(subprocess_got_sigsegv) << "Exit status: " << status
-                                      << " " << details;
-
+  CheckDeathBySEGV(status, details);
   bool subprocess_exited_without_matching_message =
       !base::Contains(msg, expected_msg);
   EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
 }
 
+void UnitTests::DeathSEGVMessagePattern(int status,
+                                        const std::string& msg,
+                                        const void* aux) {
+  std::string details(TestFailedMessage(msg));
+  const char* expected_msg = static_cast<const char*>(aux);
+  CheckDeathBySEGV(status, details);
+  std::string pattern(expected_msg);
+  bool subprocess_exited_without_matching_message =
+      !base::MatchPattern(msg, pattern);
+  EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
+}
+
 void UnitTests::DeathExitCode(int status,
                               const std::string& msg,
                               const void* aux) {
diff --git a/sandbox/linux/tests/unit_tests.h b/sandbox/linux/tests/unit_tests.h
index d51eff26..d1c7cfe2 100644
--- a/sandbox/linux/tests/unit_tests.h
+++ b/sandbox/linux/tests/unit_tests.h
@@ -75,6 +75,9 @@
 #define DEATH_SEGV_MESSAGE(msg)         \
   sandbox::UnitTests::DeathSEGVMessage, \
       static_cast<const void*>(static_cast<const char*>(msg))
+#define DEATH_SEGV_MESSAGE_PATTERN(msg)        \
+  sandbox::UnitTests::DeathSEGVMessagePattern, \
+      static_cast<const void*>(static_cast<const char*>(msg))
 #define DEATH_EXIT_CODE(rc)          \
   sandbox::UnitTests::DeathExitCode, \
       reinterpret_cast<void*>(static_cast<intptr_t>(rc))
@@ -186,6 +189,12 @@
                                const std::string& msg,
                                const void* aux);
 
+  // A DeathCheck that verifies that the child process died with a SIGSEGV
+  // and printed a message matching a pattern.
+  static void DeathSEGVMessagePattern(int status,
+                                      const std::string& msg,
+                                      const void* aux);
+
   // A DeathCheck method that verifies that the test completed with a
   // particular exit code. If the test output any messages to stderr, they are
   // silently ignored. The expected exit code should be passed in by
@@ -203,6 +212,6 @@
                             const void* aux);
 };
 
-}  // namespace
+}  // namespace sandbox
 
 #endif  // SANDBOX_LINUX_TESTS_UNIT_TESTS_H_
diff --git a/services/network/prefetch_matches_unittest.cc b/services/network/prefetch_matches_unittest.cc
index 96751c786..fc7194ed 100644
--- a/services/network/prefetch_matches_unittest.cc
+++ b/services/network/prefetch_matches_unittest.cc
@@ -67,43 +67,37 @@
 TEST(PrefetchMatchesTest, HeadersPurposeDiffers) {
   ResourceRequest prefetch;
   ResourceRequest real;
-  prefetch.headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n");
+  prefetch.headers.SetHeader("User-Agent", "Mozilla/1.0");
+  prefetch.headers.SetHeader("Referer", "https://www.example.com/");
   prefetch.headers.SetHeader(blink::kPurposeHeaderName,
                              blink::kSecPurposePrefetchHeaderValue);
-  real.headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n");
+  real.headers.SetHeader("User-Agent", "Mozilla/1.0");
+  real.headers.SetHeader("Referer", "https://www.example.com/");
   EXPECT_TRUE(PrefetchMatches(prefetch, real));
 }
 
 TEST(PrefetchMatchesTest, HeadersOrderDoesntMatter) {
   ResourceRequest prefetch;
   ResourceRequest real;
-  prefetch.headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n");
+  prefetch.headers.SetHeader("User-Agent", "Mozilla/1.0");
+  prefetch.headers.SetHeader("Referer", "https://www.example.com/");
   prefetch.headers.SetHeader(blink::kPurposeHeaderName,
                              blink::kSecPurposePrefetchHeaderValue);
-  real.headers.AddHeadersFromString(
-      "Referer: https://www.example.com/\r\n"
-      "User-Agent: Mozilla/1.0\r\n");
+  real.headers.SetHeader("Referer", "https://www.example.com/");
+  real.headers.SetHeader("User-Agent", "Mozilla/1.0");
   EXPECT_TRUE(PrefetchMatches(prefetch, real));
 }
 
 TEST(PrefetchMatchesTest, HeadersOriginDiffers) {
   ResourceRequest prefetch;
   ResourceRequest real;
-  prefetch.headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Origin: https://www.example.com/\r\n");
+  prefetch.headers.SetHeader("User-Agent", "Mozilla/1.0");
+  prefetch.headers.SetHeader("Origin", "https://www.example.com/");
   prefetch.headers.SetHeader(blink::kPurposeHeaderName,
                              blink::kSecPurposePrefetchHeaderValue);
-  real.headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n"
-      "Origin: https://www2.example/\r\n");
+  real.headers.SetHeader("User-Agent", "Mozilla/1.0");
+  real.headers.SetHeader("Referer", "https://www.example.com/");
+  real.headers.SetHeader("Origin", "https://www2.example/");
   EXPECT_FALSE(PrefetchMatches(prefetch, real));
 }
 
@@ -112,14 +106,12 @@
   ResourceRequest real;
   // The "Purpose" header is not ignored when it is a field other than
   // "headers".
-  prefetch.cors_exempt_headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n");
+  prefetch.cors_exempt_headers.SetHeader("User-Agent", "Mozilla/1.0");
+  prefetch.cors_exempt_headers.SetHeader("Referer", "https://www.example.com/");
   prefetch.cors_exempt_headers.SetHeader(blink::kPurposeHeaderName,
                                          blink::kSecPurposePrefetchHeaderValue);
-  real.cors_exempt_headers.AddHeadersFromString(
-      "User-Agent: Mozilla/1.0\r\n"
-      "Referer: https://www.example.com/\r\n");
+  real.cors_exempt_headers.SetHeader("User-Agent", "Mozilla/1.0");
+  real.cors_exempt_headers.SetHeader("Referer", "https://www.example.com/");
   EXPECT_FALSE(PrefetchMatches(prefetch, real));
 }
 
diff --git a/services/network/public/cpp/attribution_utils.cc b/services/network/public/cpp/attribution_utils.cc
index f7d2b0d..17ba678 100644
--- a/services/network/public/cpp/attribution_utils.cc
+++ b/services/network/public/cpp/attribution_utils.cc
@@ -4,7 +4,6 @@
 
 #include "services/network/public/cpp/attribution_utils.h"
 
-#include "base/notreached.h"
 #include "services/network/public/mojom/attribution.mojom.h"
 
 namespace network {
@@ -16,9 +15,8 @@
       return true;
     case mojom::AttributionSupport::kWeb:
     case mojom::AttributionSupport::kNone:
-      return false;
     case mojom::AttributionSupport::kUnset:
-      NOTREACHED();
+      return false;
   }
 }
 
@@ -29,9 +27,8 @@
       return true;
     case mojom::AttributionSupport::kOs:
     case mojom::AttributionSupport::kNone:
-      return false;
     case mojom::AttributionSupport::kUnset:
-      NOTREACHED();
+      return false;
   }
 }
 
diff --git a/services/on_device_model/ml/chrome_ml_api.h b/services/on_device_model/ml/chrome_ml_api.h
index 8041af5..6964bf9 100644
--- a/services/on_device_model/ml/chrome_ml_api.h
+++ b/services/on_device_model/ml/chrome_ml_api.h
@@ -67,9 +67,11 @@
   // Matching `file_id` tells the backend that the data also matches.
   std::optional<uint32_t> file_id;
 
-  // File holding the weight cache. The file will be owned by the inference
+  // Files holding the weight cache. These files will be owned by the inference
   // library and closed upon model destruction.
   PlatformFile cache_file;
+  PlatformFile encoder_cache_file;
+  PlatformFile adapter_cache_file;
 
   // Null-terminated model path pointing to the model to use. Only kApuBackend
   // provides this field. Other backends provide model through the
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc
index b35a62f3..1a11094 100644
--- a/services/on_device_model/ml/on_device_model_executor.cc
+++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -699,6 +699,12 @@
                             assets.cache.IsValid()
                         ? assets.cache.TakePlatformFile()
                         : base::kInvalidPlatformFile;
+  if (assets.encoder_cache.IsValid()) {
+    data.encoder_cache_file = assets.encoder_cache.TakePlatformFile();
+  }
+  if (assets.adapter_cache.IsValid()) {
+    data.adapter_cache_file = assets.adapter_cache.TakePlatformFile();
+  }
   ChromeMLModelDescriptor descriptor = {
       .backend_type = params->backend_type,
       .model_data = &data,
diff --git a/services/on_device_model/public/cpp/model_assets.cc b/services/on_device_model/public/cpp/model_assets.cc
index 60488b1c..babfd233 100644
--- a/services/on_device_model/public/cpp/model_assets.cc
+++ b/services/on_device_model/public/cpp/model_assets.cc
@@ -135,12 +135,16 @@
 ModelAssets::ModelAssets(const ModelAssets& other)
     : weights(other.weights),
       sp_model_path(other.sp_model_path),
-      cache(other.cache.Duplicate()) {}
+      cache(other.cache.Duplicate()),
+      encoder_cache(other.encoder_cache.Duplicate()),
+      adapter_cache(other.adapter_cache.Duplicate()) {}
 
 ModelAssets& ModelAssets::operator=(const ModelAssets& other) {
   weights = other.weights;
   sp_model_path = other.sp_model_path;
   cache = other.cache.Duplicate();
+  encoder_cache = other.encoder_cache.Duplicate();
+  adapter_cache = other.adapter_cache.Duplicate();
   return *this;
 }
 
@@ -163,6 +167,16 @@
     assets.cache = base::File(paths.cache, kCacheFlags);
   }
 
+  if (!paths.encoder_cache.empty()) {
+    PrefetchFile(paths.encoder_cache);
+    assets.encoder_cache = base::File(paths.encoder_cache, kCacheFlags);
+  }
+
+  if (!paths.adapter_cache.empty()) {
+    PrefetchFile(paths.adapter_cache);
+    assets.adapter_cache = base::File(paths.adapter_cache, kCacheFlags);
+  }
+
   return assets;
 }
 
diff --git a/services/on_device_model/public/cpp/model_assets.h b/services/on_device_model/public/cpp/model_assets.h
index 93c2dcf..4beabd1 100644
--- a/services/on_device_model/public/cpp/model_assets.h
+++ b/services/on_device_model/public/cpp/model_assets.h
@@ -26,6 +26,8 @@
   base::FilePath weights;
   base::FilePath sp_model;
   base::FilePath cache;
+  base::FilePath encoder_cache;
+  base::FilePath adapter_cache;
 };
 
 class COMPONENT_EXPORT(ON_DEVICE_MODEL_CPP) ModelFile {
@@ -72,6 +74,8 @@
   ModelFile weights;
   base::FilePath sp_model_path;
   base::File cache;
+  base::File encoder_cache;
+  base::File adapter_cache;
 };
 
 // Helper to open files for ModelAssets given their containing paths.
diff --git a/services/on_device_model/public/cpp/model_assets_mojom_traits.cc b/services/on_device_model/public/cpp/model_assets_mojom_traits.cc
index 1446483..78b636d 100644
--- a/services/on_device_model/public/cpp/model_assets_mojom_traits.cc
+++ b/services/on_device_model/public/cpp/model_assets_mojom_traits.cc
@@ -24,7 +24,9 @@
   std::optional<base::FilePath> sp_model_path;
   bool ok = data.ReadWeights(&assets->weights) &&
             data.ReadSpModelPath(&sp_model_path) &&
-            data.ReadCache(&assets->cache);
+            data.ReadCache(&assets->cache) &&
+            data.ReadEncoderCache(&assets->encoder_cache) &&
+            data.ReadAdapterCache(&assets->adapter_cache);
   if (!ok) {
     return false;
   }
diff --git a/services/on_device_model/public/cpp/model_assets_mojom_traits.h b/services/on_device_model/public/cpp/model_assets_mojom_traits.h
index ed33195..a3fbd85 100644
--- a/services/on_device_model/public/cpp/model_assets_mojom_traits.h
+++ b/services/on_device_model/public/cpp/model_assets_mojom_traits.h
@@ -33,6 +33,14 @@
     return std::move(assets.cache);
   }
 
+  static base::File encoder_cache(on_device_model::ModelAssets& assets) {
+    return std::move(assets.encoder_cache);
+  }
+
+  static base::File adapter_cache(on_device_model::ModelAssets& assets) {
+    return std::move(assets.adapter_cache);
+  }
+
   static bool Read(on_device_model::mojom::ModelAssetsDataView data,
                    on_device_model::ModelAssets* assets);
 };
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.cc b/services/on_device_model/public/cpp/test_support/fake_service.cc
index aacde704..ad7e2ca 100644
--- a/services/on_device_model/public/cpp/test_support/fake_service.cc
+++ b/services/on_device_model/public/cpp/test_support/fake_service.cc
@@ -27,6 +27,9 @@
 namespace {
 
 std::string ReadFile(base::File& file) {
+  if (file.GetLength() == 0) {
+    return "";
+  }
   // Using MemoryMappedFile to handle async file.
   base::MemoryMappedFile map;
   CHECK(map.Initialize(std::move(file)));
@@ -221,6 +224,18 @@
     chunk->text = "Cache weight: " + model_->data().cache_weight;
     remote->OnResponse(std::move(chunk));
   }
+  if (!model_->data().encoder_cache_weight.empty()) {
+    auto chunk = mojom::ResponseChunk::New();
+    chunk->text =
+        "Encoder cache weight: " + model_->data().encoder_cache_weight;
+    remote->OnResponse(std::move(chunk));
+  }
+  if (!model_->data().adapter_cache_weight.empty()) {
+    auto chunk = mojom::ResponseChunk::New();
+    chunk->text =
+        "Adapter cache weight: " + model_->data().adapter_cache_weight;
+    remote->OnResponse(std::move(chunk));
+  }
 
   if (priority_ == on_device_model::mojom::Priority::kBackground) {
     auto chunk = mojom::ResponseChunk::New();
@@ -435,9 +450,15 @@
     LoadModelCallback callback) {
   FakeOnDeviceModel::Data data;
   data.base_weight = ReadFile(params->assets.weights.file());
-  if (params->assets.cache.IsValid() && params->assets.cache.GetLength() > 0) {
+  if (params->assets.cache.IsValid()) {
     data.cache_weight = ReadFile(params->assets.cache);
   }
+  if (params->assets.encoder_cache.IsValid()) {
+    data.encoder_cache_weight = ReadFile(params->assets.encoder_cache);
+  }
+  if (params->assets.adapter_cache.IsValid()) {
+    data.adapter_cache_weight = ReadFile(params->assets.adapter_cache);
+  }
   data.adaptation_ranks = params->adaptation_ranks;
   auto test_model = std::make_unique<FakeOnDeviceModel>(
       settings_, std::move(data), params->performance_hint,
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.h b/services/on_device_model/public/cpp/test_support/fake_service.h
index 25c56f8..951f98b 100644
--- a/services/on_device_model/public/cpp/test_support/fake_service.h
+++ b/services/on_device_model/public/cpp/test_support/fake_service.h
@@ -135,6 +135,8 @@
     std::string base_weight = "";
     std::string adaptation_model_weight = "";
     std::string cache_weight = "";
+    std::string encoder_cache_weight = "";
+    std::string adapter_cache_weight = "";
     std::vector<uint32_t> adaptation_ranks;
   };
   explicit FakeOnDeviceModel(FakeOnDeviceServiceSettings* settings,
diff --git a/services/on_device_model/public/mojom/on_device_model_service.mojom b/services/on_device_model/public/mojom/on_device_model_service.mojom
index 677cc49..c76cfe8 100644
--- a/services/on_device_model/public/mojom/on_device_model_service.mojom
+++ b/services/on_device_model/public/mojom/on_device_model_service.mojom
@@ -30,10 +30,12 @@
   // Currently the only usage of sp model will be passed by file path.
   mojo_base.mojom.FilePath? sp_model_path;
 
-  // File which may be used to store a backend-specific cache of the model
-  // weights or to load previously-cached model weights from. This file must be
-  // writable to allow the backend to write out its custom data.
+  // Files which may be used to store a backend-specific cache of the model
+  // weights or to load previously-cached model weights from. These files must
+  // be writable to allow the backend to write out its custom data.
   mojo_base.mojom.File? cache;
+  mojo_base.mojom.File? encoder_cache;
+  mojo_base.mojom.File? adapter_cache;
 };
 
 // Type of the backend to run the model.
diff --git a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
index c047e82..9a50e41 100644
--- a/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/copy_output_result_mojom_traits.cc
@@ -58,6 +58,7 @@
   switch (format) {
     case viz::CopyOutputResult::Format::RGBA:
       return viz::mojom::CopyOutputResultFormat::RGBA;
+    case viz::CopyOutputResult::Format::RGBAF16:
     case viz::CopyOutputResult::Format::I420_PLANES:
     case viz::CopyOutputResult::Format::NV12:
       break;  // Not intended for transport across service boundaries.
@@ -286,6 +287,7 @@
         }
       }
 
+    case viz::CopyOutputResult::Format::RGBAF16:
     case viz::CopyOutputResult::Format::I420_PLANES:
     case viz::CopyOutputResult::Format::NV12:
       break;  // Not intended for transport across service boundaries.
diff --git a/services/webnn/ort/model_editor_test.cc b/services/webnn/ort/model_editor_test.cc
index 92ce43a..ce05a81 100644
--- a/services/webnn/ort/model_editor_test.cc
+++ b/services/webnn/ort/model_editor_test.cc
@@ -26,7 +26,7 @@
   // Add an input.
   constexpr base::cstring_view input = "input";
   auto input_desc = OperandDescriptor::CreateForDeserialization(
-      OperandDataType::kUint32, {4, 2, 4});
+      OperandDataType::kUint32, {4, 2, 4}, {});
   ASSERT_TRUE(input_desc.has_value());
   mojom::OperandPtr input_operand =
       mojom::Operand::New(mojom::Operand::Kind::kInput,
@@ -38,7 +38,7 @@
   std::array<uint32_t, 32> add_initializer_data;  // 128 bytes
   add_initializer_data.fill(1);
   auto add_initializer_desc = OperandDescriptor::CreateForDeserialization(
-      OperandDataType::kUint32, {4, 2, 4});
+      OperandDataType::kUint32, {4, 2, 4}, {});
   ASSERT_TRUE(add_initializer_desc.has_value());
   auto add_initializer_operand = std::make_unique<WebNNConstantOperand>(
       std::move(add_initializer_desc.value()),
@@ -52,7 +52,8 @@
   std::array<int64_t, 4> gather_indices_initializer_data = {0, 1, 0,
                                                             1};  // 32 bytes
   auto gather_indices_initializer_desc =
-      OperandDescriptor::CreateForDeserialization(OperandDataType::kInt64, {4});
+      OperandDescriptor::CreateForDeserialization(OperandDataType::kInt64, {4},
+                                                  {});
   ASSERT_TRUE(gather_indices_initializer_desc.has_value());
   auto gather_indices_initializer_operand =
       std::make_unique<WebNNConstantOperand>(
@@ -85,7 +86,7 @@
 
   // Add an output.
   auto output_desc = OperandDescriptor::CreateForDeserialization(
-      OperandDataType::kUint32, {4, 4, 4});
+      OperandDataType::kUint32, {4, 4, 4}, {});
   ASSERT_TRUE(output_desc.has_value());
   mojom::OperandPtr output_operand =
       mojom::Operand::New(mojom::Operand::Kind::kOutput,
@@ -104,7 +105,7 @@
   // Add an input.
   constexpr base::cstring_view input = "input";
   auto input_desc = OperandDescriptor::CreateForDeserialization(
-      OperandDataType::kInt32, {1, 1, 1, 1});
+      OperandDataType::kInt32, {1, 1, 1, 1}, {});
   ASSERT_TRUE(input_desc.has_value());
   mojom::OperandPtr input_operand =
       mojom::Operand::New(mojom::Operand::Kind::kInput,
@@ -128,8 +129,8 @@
       reshape_outputs);
 
   // Add an output.
-  auto output_desc =
-      OperandDescriptor::CreateForDeserialization(OperandDataType::kInt32, {});
+  auto output_desc = OperandDescriptor::CreateForDeserialization(
+      OperandDataType::kInt32, {}, {});
   ASSERT_TRUE(output_desc.has_value());
   mojom::OperandPtr output_operand =
       mojom::Operand::New(mojom::Operand::Kind::kOutput,
diff --git a/services/webnn/public/cpp/operand_descriptor.cc b/services/webnn/public/cpp/operand_descriptor.cc
index f87e60e..3d698d8 100644
--- a/services/webnn/public/cpp/operand_descriptor.cc
+++ b/services/webnn/public/cpp/operand_descriptor.cc
@@ -73,6 +73,31 @@
   return number_of_bytes;
 }
 
+base::expected<void, std::string> IsValidPermutation(
+    base::span<const uint32_t> permutation,
+    OperandDataType data_type,
+    base::span<const uint32_t> shape) {
+  // TODO(crbug.com/428232161): Support sub-byte transposes.
+  if (OperandDescriptor::GetBitsPerElement(data_type) < 8u) {
+    return base::unexpected(
+        "Invalid descriptor: Permutation is not supported for sub-byte data "
+        "types.");
+  }
+  if (permutation.size() != shape.size()) {
+    return base::unexpected(
+        "Invalid descriptor: Permutation size doesn't match with shape.");
+  }
+  std::vector<uint32_t> sorted_permutation = base::ToVector(permutation);
+  std::ranges::sort(sorted_permutation);
+  for (size_t i = 0; i < sorted_permutation.size(); ++i) {
+    if (sorted_permutation[i] != i) {
+      return base::unexpected(
+          "Invalid descriptor: Permutation contains invalid dimension.");
+    }
+  }
+  return base::ok();
+}
+
 }  // namespace
 
 // static
@@ -94,18 +119,25 @@
 
 // static
 base::expected<OperandDescriptor, std::string>
-OperandDescriptor::CreateForDeserialization(OperandDataType data_type,
-                                            base::span<const uint32_t> shape) {
+OperandDescriptor::CreateForDeserialization(
+    OperandDataType data_type,
+    base::span<const uint32_t> shape,
+    base::span<const uint32_t> pending_permutation) {
   RETURN_IF_ERROR(ValidateAndGetByteLength(data_type, shape));
-
-  return OperandDescriptor(data_type, base::ToVector(shape));
+  if (!pending_permutation.empty()) {
+    RETURN_IF_ERROR(IsValidPermutation(pending_permutation, data_type, shape));
+  }
+  return OperandDescriptor(data_type, base::ToVector(shape),
+                           base::ToVector(pending_permutation));
 }
 
 // static
 OperandDescriptor OperandDescriptor::UnsafeCreateForTesting(
     OperandDataType data_type,
-    base::span<const uint32_t> shape) {
-  return OperandDescriptor(data_type, base::ToVector(shape));
+    base::span<const uint32_t> shape,
+    base::span<const uint32_t> pending_permutation) {
+  return OperandDescriptor(data_type, base::ToVector(shape),
+                           base::ToVector(pending_permutation));
 }
 
 // static
@@ -139,6 +171,13 @@
                                      std::vector<uint32_t> shape)
     : data_type_(data_type), shape_(std::move(shape)) {}
 
+OperandDescriptor::OperandDescriptor(OperandDataType data_type,
+                                     std::vector<uint32_t> shape,
+                                     std::vector<uint32_t> pending_permutation)
+    : data_type_(data_type),
+      shape_(std::move(shape)),
+      pending_permutation_(std::move(pending_permutation)) {}
+
 OperandDescriptor::OperandDescriptor(const OperandDescriptor&) = default;
 OperandDescriptor& OperandDescriptor::operator=(const OperandDescriptor&) =
     default;
@@ -166,4 +205,9 @@
                          std::multiplies());
 }
 
+void OperandDescriptor::SetPendingPermutation(
+    base::span<const uint32_t> permutation) {
+  CHECK(IsValidPermutation(permutation, data_type_, shape_).has_value());
+  pending_permutation_.assign(permutation.begin(), permutation.end());
+}
 }  // namespace webnn
diff --git a/services/webnn/public/cpp/operand_descriptor.h b/services/webnn/public/cpp/operand_descriptor.h
index 98c69b0..629cf307 100644
--- a/services/webnn/public/cpp/operand_descriptor.h
+++ b/services/webnn/public/cpp/operand_descriptor.h
@@ -46,13 +46,15 @@
   // validated tensor size limit later.
   static base::expected<OperandDescriptor, std::string>
   CreateForDeserialization(OperandDataType data_type,
-                           base::span<const uint32_t> shape);
+                           base::span<const uint32_t> shape,
+                           base::span<const uint32_t> pending_permutation);
 
   // Same as above, but skip validation checks. This may be used to create an
   // invalid descriptor to test that its deserialization fails.
   static OperandDescriptor UnsafeCreateForTesting(
       OperandDataType data_type,
-      base::span<const uint32_t> shape);
+      base::span<const uint32_t> shape,
+      base::span<const uint32_t> pending_permutation = {});
 
   static size_t GetBitsPerElement(OperandDataType data_type);
 
@@ -70,6 +72,9 @@
 
   OperandDataType data_type() const { return data_type_; }
   const std::vector<uint32_t>& shape() const { return shape_; }
+  const std::vector<uint32_t>& pending_permutation() const {
+    return pending_permutation_;
+  }
 
   uint32_t Rank() const { return static_cast<uint32_t>(shape_.size()); }
   // Total byte length assuming perfect packing. Some tensors described by this
@@ -77,14 +82,29 @@
   size_t PackedByteLength() const;
   size_t NumberOfElements() const;
 
+  void SetPendingPermutation(base::span<const uint32_t> permutation);
+
   friend constexpr auto operator<=>(const OperandDescriptor& lhs,
-                                    const OperandDescriptor& rhs) = default;
+                                    const OperandDescriptor& rhs) {
+    if (auto cmp = lhs.data_type_ <=> rhs.data_type_; cmp != 0) {
+      return cmp;
+    }
+    return lhs.shape_ <=> rhs.shape_;
+  }
+  friend constexpr bool operator==(const OperandDescriptor& lhs,
+                                   const OperandDescriptor& rhs) {
+    return lhs.data_type_ == rhs.data_type_ && lhs.shape_ == rhs.shape_;
+  }
 
  private:
   OperandDescriptor(OperandDataType data_type, std::vector<uint32_t> shape);
+  OperandDescriptor(OperandDataType data_type,
+                    std::vector<uint32_t> shape,
+                    std::vector<uint32_t> permutation);
 
   OperandDataType data_type_;
   std::vector<uint32_t> shape_;
+  std::vector<uint32_t> pending_permutation_;
 };
 
 }  // namespace webnn
diff --git a/services/webnn/public/mojom/operand_descriptor_mojom_traits.cc b/services/webnn/public/mojom/operand_descriptor_mojom_traits.cc
index e4d3b1e..baf7d32 100644
--- a/services/webnn/public/mojom/operand_descriptor_mojom_traits.cc
+++ b/services/webnn/public/mojom/operand_descriptor_mojom_traits.cc
@@ -77,9 +77,13 @@
   mojo::ArrayDataView<uint32_t> shape;
   data.GetShapeDataView(&shape);
 
+  mojo::ArrayDataView<uint32_t> pending_permutation;
+  data.GetPendingPermutationDataView(&pending_permutation);
+
   base::expected<webnn::OperandDescriptor, std::string> descriptor =
       webnn::OperandDescriptor::CreateForDeserialization(
-          FromMojoDataType(data.data_type()), base::span(shape));
+          FromMojoDataType(data.data_type()), base::span(shape),
+          base::span(pending_permutation));
 
   if (!descriptor.has_value()) {
     return false;
diff --git a/services/webnn/public/mojom/operand_descriptor_mojom_traits.h b/services/webnn/public/mojom/operand_descriptor_mojom_traits.h
index 132dcebf..9be108aa82 100644
--- a/services/webnn/public/mojom/operand_descriptor_mojom_traits.h
+++ b/services/webnn/public/mojom/operand_descriptor_mojom_traits.h
@@ -23,6 +23,10 @@
       const webnn::OperandDescriptor& descriptor) {
     return descriptor.shape();
   }
+  static const std::vector<uint32_t>& pending_permutation(
+      const webnn::OperandDescriptor& descriptor) {
+    return descriptor.pending_permutation();
+  }
 
   static bool Read(webnn::mojom::OperandDescriptorDataView data,
                    webnn::OperandDescriptor* out);
diff --git a/services/webnn/public/mojom/operand_descriptor_mojom_traits_unittest.cc b/services/webnn/public/mojom/operand_descriptor_mojom_traits_unittest.cc
index abfa4b0d..5cb69a1 100644
--- a/services/webnn/public/mojom/operand_descriptor_mojom_traits_unittest.cc
+++ b/services/webnn/public/mojom/operand_descriptor_mojom_traits_unittest.cc
@@ -28,7 +28,7 @@
 
 TEST(OperandDescriptorMojomTraitsTest, Basic) {
   auto input = webnn::OperandDescriptor::CreateForDeserialization(
-      webnn::OperandDataType::kInt32, std::array<uint32_t, 2>{2, 3});
+      webnn::OperandDataType::kInt32, std::array<uint32_t, 2>{2, 3}, {});
   ASSERT_TRUE(input.has_value());
 
   webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
@@ -40,7 +40,7 @@
 
 TEST(OperandDescriptorMojomTraitsTest, Int4) {
   auto input = webnn::OperandDescriptor::CreateForDeserialization(
-      webnn::OperandDataType::kInt4, std::array<uint32_t, 2>{3, 3});
+      webnn::OperandDataType::kInt4, std::array<uint32_t, 2>{3, 3}, {});
   ASSERT_TRUE(input.has_value());
 
   webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
@@ -56,7 +56,7 @@
 TEST(OperandDescriptorMojomTraitsTest, EmptyShape) {
   // Descriptors with an empty shape are treated as scalars.
   auto input = webnn::OperandDescriptor::CreateForDeserialization(
-      webnn::OperandDataType::kInt32, {});
+      webnn::OperandDataType::kInt32, {}, {});
   ASSERT_TRUE(input.has_value());
 
   webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
@@ -73,7 +73,7 @@
   const std::array<uint32_t, 3> shape{2, 0, 3};
 
   ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
-                   webnn::OperandDataType::kInt32, shape)
+                   webnn::OperandDataType::kInt32, shape, {})
                    .has_value());
 
   auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
@@ -92,7 +92,7 @@
   // Using int4 so that the byte length won't overflow the max size_t on 64-bit
   // platforms.
   ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
-                   webnn::OperandDataType::kInt4, shape)
+                   webnn::OperandDataType::kInt4, shape, {})
                    .has_value());
 
   auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
@@ -110,7 +110,7 @@
 
   // The byte length overflows the max size_t on all platforms.
   ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
-                   webnn::OperandDataType::kInt64, shape)
+                   webnn::OperandDataType::kInt64, shape, {})
                    .has_value());
 
   auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
@@ -129,7 +129,7 @@
       base::checked_cast<uint32_t>(std::numeric_limits<int32_t>::max() / 4), 2};
 
   auto input = webnn::OperandDescriptor::CreateForDeserialization(
-      webnn::OperandDataType::kInt32, shape);
+      webnn::OperandDataType::kInt32, shape, {});
   ASSERT_TRUE(input.has_value());
 
   webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
@@ -151,4 +151,52 @@
       input, output));
 }
 
+TEST(OperandDescriptorMojomTraitsTest, InvalidSizePendingPermutation) {
+  const std::array<uint32_t, 2> shape{1u, 2u};
+
+  const std::array<uint32_t, 1> pending_permutation{1};
+  ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
+                   webnn::OperandDataType::kInt64, shape, pending_permutation)
+                   .has_value());
+
+  auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
+      webnn::OperandDataType::kInt64, shape, pending_permutation);
+  webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
+  EXPECT_FALSE(
+      mojo::test::SerializeAndDeserialize<webnn::mojom::OperandDescriptor>(
+          input, output));
+}
+
+TEST(OperandDescriptorMojomTraitsTest, InvalidDimensionPendingPermutation) {
+  const std::array<uint32_t, 2> shape{1u, 2u};
+
+  const std::array<uint32_t, 2> pending_permutation{3, 2};
+  ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
+                   webnn::OperandDataType::kInt64, shape, pending_permutation)
+                   .has_value());
+
+  auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
+      webnn::OperandDataType::kInt64, shape, pending_permutation);
+  webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
+  EXPECT_FALSE(
+      mojo::test::SerializeAndDeserialize<webnn::mojom::OperandDescriptor>(
+          input, output));
+}
+
+TEST(OperandDescriptorMojomTraitsTest, SubBytePendingPermutation) {
+  const std::array<uint32_t, 2> shape{1u, 2u};
+
+  const std::array<uint32_t, 2> pending_permutation{1, 0};
+  ASSERT_FALSE(webnn::OperandDescriptor::CreateForDeserialization(
+                   webnn::OperandDataType::kInt4, shape, pending_permutation)
+                   .has_value());
+
+  auto input = webnn::OperandDescriptor::UnsafeCreateForTesting(
+      webnn::OperandDataType::kInt4, shape, pending_permutation);
+  webnn::OperandDescriptor output = CreateInvalidOperandDescriptor();
+  EXPECT_FALSE(
+      mojo::test::SerializeAndDeserialize<webnn::mojom::OperandDescriptor>(
+          input, output));
+}
+
 }  // namespace mojo
diff --git a/services/webnn/public/mojom/webnn_graph.mojom b/services/webnn/public/mojom/webnn_graph.mojom
index 060c46d..5169225 100644
--- a/services/webnn/public/mojom/webnn_graph.mojom
+++ b/services/webnn/public/mojom/webnn_graph.mojom
@@ -32,6 +32,9 @@
 struct OperandDescriptor {
   DataType data_type;
   array<uint32> shape;
+  // Permutation that needs to be performed on service side for constant
+  // operands.
+  array<uint32> pending_permutation;
 };
 
 struct OperandId {
diff --git a/services/webnn/webnn_constant_operand.cc b/services/webnn/webnn_constant_operand.cc
index 617b11fa5..ef715856 100644
--- a/services/webnn/webnn_constant_operand.cc
+++ b/services/webnn/webnn_constant_operand.cc
@@ -14,4 +14,8 @@
 
 WebNNConstantOperand::~WebNNConstantOperand() = default;
 
+void WebNNConstantOperand::SetData(base::HeapArray<uint8_t>&& data) {
+  data_ = std::move(data);
+}
+
 }  // namespace webnn
diff --git a/services/webnn/webnn_constant_operand.h b/services/webnn/webnn_constant_operand.h
index 9f3ec69..a3fd325b 100644
--- a/services/webnn/webnn_constant_operand.h
+++ b/services/webnn/webnn_constant_operand.h
@@ -37,6 +37,7 @@
   base::span<const uint8_t> ByteSpan() const LIFETIME_BOUND { return data_; }
 
   base::HeapArray<uint8_t> TakeData() { return std::move(data_); }
+  void SetData(base::HeapArray<uint8_t>&& data);
 
  private:
   const OperandDescriptor descriptor_;
diff --git a/services/webnn/webnn_graph_builder_impl.cc b/services/webnn/webnn_graph_builder_impl.cc
index c2075158..0c9115d 100644
--- a/services/webnn/webnn_graph_builder_impl.cc
+++ b/services/webnn/webnn_graph_builder_impl.cc
@@ -14,12 +14,15 @@
 #include "base/memory/stack_allocated.h"
 #include "base/numerics/checked_math.h"
 #include "base/task/bind_post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/types/expected.h"
+#include "base/types/fixed_array.h"
 #include "base/types/pass_key.h"
 #include "services/webnn/error.h"
 #include "services/webnn/public/cpp/graph_validation_utils.h"
 #include "services/webnn/public/cpp/operand_descriptor.h"
 #include "services/webnn/public/cpp/supported_data_types.h"
+#include "services/webnn/public/cpp/webnn_trace.h"
 #include "services/webnn/public/cpp/webnn_types.h"
 #include "services/webnn/public/mojom/webnn_error.mojom.h"
 #include "services/webnn/webnn_constant_operand.h"
@@ -2686,6 +2689,90 @@
   }
 }
 
+uint32_t GetLinearOffset(base::span<const uint32_t> multi_dim_index,
+                         base::span<const uint32_t> strides) {
+  uint32_t offset = 0;
+  for (uint32_t i = 0; i < multi_dim_index.size(); ++i) {
+    offset += multi_dim_index[i] * strides[i];
+  }
+  return offset;
+}
+
+base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>>
+TransposePendingPermutation(
+    base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>>&&
+        constant_operands) {
+  ScopedTrace scoped_trace("TransposePendingPermutation");
+  // TODO(crbug.com/432040141): Consider using XNNPack for transposing
+  // constants.
+  for (auto& [operand_id, constant] : constant_operands) {
+    if (constant->descriptor().pending_permutation().empty()) {
+      continue;
+    }
+    base::span<const uint8_t> data = constant->ByteSpan();
+    auto& descriptor = constant->descriptor();
+    uint32_t rank = descriptor.Rank();
+    auto& permutation = descriptor.pending_permutation();
+    CHECK_EQ(rank, permutation.size());
+
+    // TODO(crbug.com/428232161): Support sub-byte transposes.
+    size_t bit_size =
+        OperandDescriptor::GetBitsPerElement(descriptor.data_type());
+    CHECK_GE(bit_size, 8u);
+
+    size_t element_size = bit_size / 8;
+
+    base::FixedArray<uint32_t> inverse_permutation(rank);
+    for (size_t i = 0; i < rank; ++i) {
+      inverse_permutation[permutation[i]] = i;
+    }
+    auto& transposed_shape = descriptor.shape();
+    base::FixedArray<uint32_t> original_shape(rank);
+    for (size_t i = 0; i < rank; ++i) {
+      original_shape[i] = descriptor.shape()[inverse_permutation[i]];
+    }
+
+    std::vector<uint32_t> original_strides = CalculateStrides(original_shape);
+    std::vector<uint32_t> transposed_strides =
+        CalculateStrides(transposed_shape);
+
+    // Current logical index in transposed tensor.
+    base::FixedArray<uint32_t> transposed_idx(rank, 0);
+    base::FixedArray<uint32_t> original_idx(rank);
+
+    auto transposed_data = base::HeapArray<uint8_t>::Uninit(data.size());
+    base::span<uint8_t> transposed_span = transposed_data.as_span();
+
+    // Loop through all elements in the transposed tensor.
+    for (size_t i = 0; i < descriptor.NumberOfElements(); ++i) {
+      for (size_t d = 0; d < rank; ++d) {
+        original_idx[d] = transposed_idx[inverse_permutation[d]];
+      }
+
+      uint32_t original_offset =
+          GetLinearOffset(original_idx, original_strides);
+      uint32_t transposed_offset =
+          GetLinearOffset(transposed_idx, transposed_strides);
+
+      transposed_span.subspan(transposed_offset * element_size, element_size)
+          .copy_from(
+              data.subspan(original_offset * element_size, element_size));
+
+      for (int dimension = rank - 1; dimension >= 0; --dimension) {
+        transposed_idx[dimension]++;
+        if (transposed_idx[dimension] < transposed_shape[dimension]) {
+          // Not overflowed, continue to next element.
+          break;
+        }
+        // Reset and carry over.
+        transposed_idx[dimension] = 0;
+      }
+    }
+    constant->SetData(std::move(transposed_data));
+  }
+  return std::move(constant_operands);
+}
+
 }  // namespace
 
 WebNNGraphBuilderImpl::ValidateGraphSuccessResult::ValidateGraphSuccessResult(
@@ -2775,16 +2862,17 @@
     return;
   }
 
-  mojo::PendingAssociatedRemote<mojom::WebNNGraph> remote;
-  auto receiver = remote.InitWithNewEndpointAndPassReceiver();
-  context_->CreateGraphImpl(
-      std::move(receiver), std::move(graph_info),
-      std::move(validate_graph_result->compute_resource_info),
-      std::move(validate_graph_result->constant_operands),
-      std::move(validate_graph_result->constant_tensor_operands),
-      base::BindOnce(&WebNNGraphBuilderImpl::DidCreateGraph,
-                     weak_factory_.GetWeakPtr(), std::move(callback),
-                     std::move(remote)));
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::TaskPriority::USER_BLOCKING,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()},
+      base::BindOnce(&TransposePendingPermutation,
+                     std::move(validate_graph_result->constant_operands)),
+      base::BindOnce(&WebNNGraphBuilderImpl::DidTransposePendingPermutations,
+                     weak_factory_.GetWeakPtr(), std::move(graph_info),
+                     std::move(validate_graph_result->compute_resource_info),
+                     std::move(validate_graph_result->constant_tensor_operands),
+                     std::move(callback)));
 }
 
 void WebNNGraphBuilderImpl::SetId(
@@ -2803,6 +2891,27 @@
           .has_value());
 }
 
+void WebNNGraphBuilderImpl::DidTransposePendingPermutations(
+    mojom::GraphInfoPtr graph_info,
+    WebNNGraphImpl::ComputeResourceInfo compute_resource_info,
+    base::flat_map<OperandId, WebNNTensorImpl*> constant_tensor_operands,
+    CreateGraphCallback callback,
+    base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>>&&
+        constant_operands) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  mojo::PendingAssociatedRemote<mojom::WebNNGraph> remote;
+  auto receiver = remote.InitWithNewEndpointAndPassReceiver();
+
+  context_->CreateGraphImpl(
+      std::move(receiver), std::move(graph_info),
+      std::move(compute_resource_info), std::move(constant_operands),
+      std::move(constant_tensor_operands),
+      base::BindOnce(&WebNNGraphBuilderImpl::DidCreateGraph,
+                     weak_factory_.GetWeakPtr(), std::move(callback),
+                     std::move(remote)));
+}
+
 void WebNNGraphBuilderImpl::DidCreateGraph(
     CreateGraphCallback callback,
     mojo::PendingAssociatedRemote<mojom::WebNNGraph> remote,
diff --git a/services/webnn/webnn_graph_builder_impl.h b/services/webnn/webnn_graph_builder_impl.h
index e401092b..5aeca9f 100644
--- a/services/webnn/webnn_graph_builder_impl.h
+++ b/services/webnn/webnn_graph_builder_impl.h
@@ -54,6 +54,7 @@
       const blink::WebNNPendingConstantToken& constant_handle,
       OperandDataType data_type,
       mojo_base::BigBuffer data) override;
+
   void CreateGraph(mojom::GraphInfoPtr graph_info,
                    CreateGraphCallback callback) override;
   void IsValidGraphForTesting(const ContextProperties& context_properties,
@@ -103,6 +104,13 @@
       bool keep_builder_resources_for_testing);
 
  private:
+  void DidTransposePendingPermutations(
+      mojom::GraphInfoPtr graph_info,
+      WebNNGraphImpl::ComputeResourceInfo compute_resource_info,
+      base::flat_map<OperandId, WebNNTensorImpl*> constant_tensor_operands,
+      CreateGraphCallback callback,
+      base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>>&&
+          constant_operands);
   void DidCreateGraph(
       CreateGraphCallback callback,
       mojo::PendingAssociatedRemote<mojom::WebNNGraph> remote,
diff --git a/services/webnn/webnn_graph_mojolpm_fuzzer.cc b/services/webnn/webnn_graph_mojolpm_fuzzer.cc
index 506c4bb..54cf01d 100644
--- a/services/webnn/webnn_graph_mojolpm_fuzzer.cc
+++ b/services/webnn/webnn_graph_mojolpm_fuzzer.cc
@@ -89,6 +89,7 @@
 
     webnn::mojom::Device device;
     mojolpm::FromProto(action.device(), device);
+    // TODO(crbug.com/432040141): Fuzz test `CreatePendingConstant`.
     BuildGraph(create_graph.graph_info(), device);
   }
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 1df29e00..be4647c 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -139,8 +139,6 @@
 
 #define SK_DISABLE_LEGACY_NONRECORDER_IMAGE_APIS
 
-#define SK_DISABLE_CLIP_DRAW_GEOMETRIC_INTERSECTION
-
 #define SK_DISABLE_BLUR_OVERSCALING
 
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
diff --git a/testing/buildbot/OWNERS b/testing/buildbot/OWNERS
index 857e6c2..16889225 100644
--- a/testing/buildbot/OWNERS
+++ b/testing/buildbot/OWNERS
@@ -17,19 +17,10 @@
 
 # LINT.IfChange(chromium_tests)
 
-# For Weblayer skew tests related reviews
-per-file chromium.android.*=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-
 # For Android related reviews
 per-file chromium.android.*=zhiyuans@google.com
 per-file chromium.android.*=wnwen@chromium.org
 
-# TODO(crbug.com/40191809) Remove the following 3 lines when the conversion is done.
-per-file chromium.fyi.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file chromium.chromiumos.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file chromium.memory.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-per-file chromium.coverage.json=chrome-weblayer-builder@chops-service-accounts.iam.gserviceaccount.com
-
 # For Lacros skylab tests cros image roller related reviews
 per-file chromium.chromiumos.json=skylab-test-cros-roller@chops-service-accounts.iam.gserviceaccount.com
 per-file chromium.fyi.json=skylab-test-cros-roller@chops-service-accounts.iam.gserviceaccount.com
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 8a774d3..870636a 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -10965,9 +10965,6 @@
             "experiments": [
                 {
                     "name": "Enabled",
-                    "params": {
-                        "glic-scroll-to-enforce-document-id": "true"
-                    },
                     "enable_features": [
                         "GlicScrollTo"
                     ]
@@ -14389,24 +14386,6 @@
             ]
         }
     ],
-    "LocalWebApprovalsLinuxMacWindows": [
-        {
-            "platforms": [
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LocalWebApprovals",
-                        "SupervisedUserBlockInterstitialV3"
-                    ]
-                }
-            ]
-        }
-    ],
     "LofnPermissiveUsbPassthrough": [
         {
             "platforms": [
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_element_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_element_test.cc
index c6a7518..47b8d42 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_element_test.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_element_test.cc
@@ -57,7 +57,7 @@
   AtomicString test_attribute("test-attribute");
   EXPECT_EQ(test_attribute.Impl()->RefCountChangeCountForTesting(), 10u);
   AtomicString test_value("test-value");
-  EXPECT_EQ(test_value.Impl()->RefCountChangeCountForTesting(), 6u);
+  EXPECT_EQ(test_value.Impl()->RefCountChangeCountForTesting(), 8u);
 #endif
 
   // Trigger a low memory notification. This will signal V8 to clear its
diff --git a/third_party/blink/renderer/core/css/parser/media_query_parser.cc b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
index c5ff708..b2ffeb9 100644
--- a/third_party/blink/renderer/core/css/parser/media_query_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
@@ -226,17 +226,15 @@
     }
   }
   wtf_size_t end = stream.Offset();
-  String value_string(stream.StringRangeAt(start, end - start).ToString());
+  StringView value_string(stream.StringRangeAt(start, end - start));
   if (value_string.empty()) {
     return std::nullopt;
   }
-
-  CSSVariableData* data =
-      CSSVariableData::Create(value_string, /* is_animation_tainted= */ false,
-                              /* is_attr_tainted= */ false,
-                              /*needs_variable_resolution=*/true);
-  const CSSValue* value =
-      MakeGarbageCollected<CSSUnparsedDeclarationValue>(data, &context);
+  const CSSValue* value = CSSVariableParser::ParseDeclarationValue(
+      value_string, /* is_animation_tainted = */ false, context);
+  if (!value) {
+    return std::nullopt;
+  }
   return MediaQueryExpValue(*value);
 }
 
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 009b66a..3e85f3c 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3348,15 +3348,9 @@
   } else {
     // Legacy behaviour; no longer spec compliant.
 
-    // TODO(vogelheim): We construct an AtomicString based on legacy_sink_name
-    // so that we can use the same type across all cases. Because this instance
-    // is constructed here, we need to return a `const AtomicString` rather
-    // than a `const AtomicString&`, so that the memory is owned at all times.
-    // In blink_unittests V8ElementTest.SetAttributeOperationCallback, the
-    // number of AtomicString references is tested for, which is sensitive to
-    // this operation.
-    // Once the TrustedTypesHTML flag is removed, this code also gets removed
-    // and it should be easy to change the return type back to a reference.
+    // TODO(vogelheim): Once the TrustedTypesHTML flag is removed, this code
+    // also gets removed and it should be easy to change the return type back
+    // to a reference.
     AtomicString property_name(legacy_sink_name);
     if (!q_name.NamespaceURI().IsNull() &&
         !SVGAnimatedHref::IsKnownAttribute(q_name)) {
@@ -6639,9 +6633,18 @@
       shadow_root_init_dict->hasReferenceTarget()
           ? AtomicString(shadow_root_init_dict->referenceTarget())
           : g_null_atom;
-  CustomElementRegistry* registry = shadow_root_init_dict->hasRegistry()
-                                        ? shadow_root_init_dict->registry()
-                                        : nullptr;
+
+  CustomElementRegistry* registry = nullptr;
+  if (RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()) {
+    // 1. Let registry be this's custom element registry
+    registry = customElementRegistry();
+    // 2. If init["customElementRegistry"] is not null, then set registry to it
+    if (shadow_root_init_dict->hasCustomElementRegistry() &&
+        shadow_root_init_dict->customElementRegistry()) {
+      registry = shadow_root_init_dict->customElementRegistry();
+    }
+  }
+
   ShadowRootMode mode;
   if (const char* error_message = ErrorMessageForAttachShadow(
           mode_string, /*for_declarative*/ false, mode)) {
@@ -6766,7 +6769,10 @@
   // 9. Set shadow’s declarative to false.
   shadow_root.SetIsDeclarativeShadowRoot(false);
 
-  shadow_root.SetRegistry(registry);
+  // 12. Set shadow's custom element registry to registry
+  if (RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()) {
+    shadow_root.SetCustomElementRegistry(registry);
+  }
   // 11. Set shadow’s serializable to serializable.
   shadow_root.setSerializable(serializable);
   // 10. Set shadow’s clonable to clonable.
@@ -11970,17 +11976,32 @@
 
   auto [index, q_name] =
       LookupAttributeQNameHinted(std::move(local_name), hint);
-  AtomicString trusted_value(TrustedTypesCheckForAttribute(
-      q_name, std::move(value), "setAttribute", exception_state));
-  if (exception_state.HadException()) {
-    return;
-  }
-  // The `TrustedTypesCheckFor` call above may run script, which may modify
-  // the current element, which in turn may invalidate the index. So we'll
-  // check, and re-calculate it if necessary.
-  index = ValidateAttributeIndex(index, q_name);
 
-  SetAttributeInternal(index, q_name, trusted_value,
+  // This method is probably the most common case for `setAttribute`.
+  // For performance reasons, we'll skip the TT check if we can determine it's
+  // unnecessary based on a quick heuristic.
+  if (q_name.LocalName().StartsWith("on") ||
+      !GetCheckedAttributeTypes().empty()) [[unlikely]] {
+    value = TrustedTypesCheckForAttribute(q_name, std::move(value),
+                                          "setAttribute", exception_state);
+    if (exception_state.HadException()) {
+      return;
+    }
+    // The `TrustedTypesCheckFor` call above may run script, which may modify
+    // the current element, which in turn may invalidate the index. So we'll
+    // check, and re-calculate it if necessary.
+    index = ValidateAttributeIndex(index, q_name);
+  } else {
+    // Check whether the "real" TT check would have come to the same result.
+    // Debug-only, since not running the check at all is the whole point of this
+    // branch.
+    DCHECK_EQ(value, TrustedTypesCheckForAttribute(
+                         q_name, value, "setAttribute", exception_state));
+    DCHECK(!exception_state.HadException());
+    DCHECK_EQ(index, ValidateAttributeIndex(index, q_name));
+  }
+
+  SetAttributeInternal(index, q_name, AtomicString(std::move(value)),
                        AttributeModificationReason::kDirectly);
 }
 
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc
index 9994c2d..509c0aad 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -79,7 +79,7 @@
 struct SameSizeAsShadowRoot : public DocumentFragment,
                               public TreeScope,
                               public ElementRareDataField {
-  Member<void*> member[3];
+  Member<void*> member[2];
   unsigned flags[1];
 };
 
@@ -340,16 +340,6 @@
   }
 }
 
-void ShadowRoot::SetRegistry(CustomElementRegistry* registry) {
-  DCHECK(!registry_);
-  DCHECK(!registry ||
-         RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled());
-  registry_ = registry;
-  if (registry) {
-    registry->AssociatedWith(GetDocument());
-  }
-}
-
 void ShadowRoot::setReferenceTarget(const AtomicString& reference_target) {
   if (!RuntimeEnabledFeatures::ShadowRootReferenceTargetEnabled(
           GetDocument().GetExecutionContext())) {
@@ -407,7 +397,6 @@
 
 void ShadowRoot::Trace(Visitor* visitor) const {
   visitor->Trace(slot_assignment_);
-  visitor->Trace(registry_);
   visitor->Trace(reference_target_id_observer_);
   ElementRareDataField::Trace(visitor);
   TreeScope::Trace(visitor);
diff --git a/third_party/blink/renderer/core/dom/shadow_root.h b/third_party/blink/renderer/core/dom/shadow_root.h
index 4aea4d5b..1b8e5d5 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/third_party/blink/renderer/core/dom/shadow_root.h
@@ -180,8 +180,6 @@
     return has_focusgroup_attribute_on_descendant_;
   }
 
-  void SetRegistry(CustomElementRegistry*);
-
   bool ContainsShadowRoots() const { return child_shadow_root_count_; }
 
   void Trace(Visitor*) const override;
@@ -202,7 +200,6 @@
   void ReferenceTargetChanged();
 
   Member<SlotAssignment> slot_assignment_;
-  Member<CustomElementRegistry> registry_;
   Member<ReferenceTargetIdObserver> reference_target_id_observer_;
   unsigned child_shadow_root_count_ : 16;
   unsigned mode_ : 2;
diff --git a/third_party/blink/renderer/core/dom/shadow_root_init.idl b/third_party/blink/renderer/core/dom/shadow_root_init.idl
index 6a96a030..deede3d5 100644
--- a/third_party/blink/renderer/core/dom/shadow_root_init.idl
+++ b/third_party/blink/renderer/core/dom/shadow_root_init.idl
@@ -11,7 +11,7 @@
   required ShadowRootMode mode;
   boolean delegatesFocus;
   SlotAssignmentMode slotAssignment;
-  [RuntimeEnabled=ScopedCustomElementRegistry] CustomElementRegistry registry;
+  [RuntimeEnabled=ScopedCustomElementRegistry] CustomElementRegistry? customElementRegistry;
   boolean serializable;
   boolean clonable;
   [RuntimeEnabled=ShadowRootReferenceTarget] DOMString referenceTarget;
diff --git a/third_party/blink/renderer/core/dom/tree_scope.cc b/third_party/blink/renderer/core/dom/tree_scope.cc
index a51ddd1..4448f31 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -295,6 +295,18 @@
   return nullptr;
 }
 
+// Custom element registry of a tree scope can only be set once.
+// Setting registry on a tree scope with existing registry will fail.
+bool TreeScope::SetCustomElementRegistry(CustomElementRegistry* registry) {
+  if (RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled() &&
+      !custom_element_registry_ && registry) {
+    custom_element_registry_ = registry;
+    registry->AssociatedWith(GetDocument());
+    return true;
+  }
+  return false;
+}
+
 static bool ShouldAcceptNonElementNode(const Node& node) {
   Node* parent = node.parentNode();
   if (!parent)
diff --git a/third_party/blink/renderer/core/dom/tree_scope.h b/third_party/blink/renderer/core/dom/tree_scope.h
index 898dd447..205a14d 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.h
+++ b/third_party/blink/renderer/core/dom/tree_scope.h
@@ -181,6 +181,9 @@
 
 
   CustomElementRegistry* customElementRegistry() const;
+  // Return true when custom element registry was set successfully, return false
+  // otherwise.
+  bool SetCustomElementRegistry(CustomElementRegistry*);
 
   // Given a `node` targeteted by an event, returns the element that this event
   // should be dispatched to.
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
index b57056aa..967bac5 100644
--- a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
+++ b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
@@ -174,9 +174,7 @@
       NOTREACHED();
     case Node::kCdataSectionNode: {
       auto& cdata = To<CDATASection>(node);
-      if (RuntimeEnabledFeatures::
-              SerializeCdataAsTextInHTMLDocumentsEnabled() &&
-          SerializeAsHTML()) {
+      if (SerializeAsHTML()) {
         AppendText(result, cdata);
       } else {
         AppendCDATASection(result, cdata.data());
diff --git a/third_party/blink/renderer/core/frame/ad_tracker.cc b/third_party/blink/renderer/core/frame/ad_tracker.cc
index c7aa66bc..4dfdf8d 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker.cc
+++ b/third_party/blink/renderer/core/frame/ad_tracker.cc
@@ -384,11 +384,38 @@
   if (stack_type == StackType::kBottomOnly)
     return false;
 
+  // If we're not aware of any ad scripts at all, or any scripts in this
+  // context, don't bother looking at the stack.
+  if (ad_script_ids_.empty()) {
+    return false;
+  }
+  auto it = context_known_ad_scripts_.find(execution_context);
+  if (it == context_known_ad_scripts_.end() || it->value.empty()) {
+    return false;
+  }
+
   // The stack scanned by the AdTracker contains entry points into the stack
   // (e.g., when v8 is executed) but not the entire stack. For a small cost we
   // can also check the top of the stack (this is much cheaper than getting the
   // full stack from v8).
-  return IsKnownAdScriptForCheckedContext(*execution_context, out_ad_script);
+  int top_script_id = ScriptAtTopOfStack();
+  if (top_script_id <= 0) {
+    return false;
+  }
+
+  bool is_ad_script = ad_script_ids_.Contains(top_script_id);
+  if (is_ad_script && out_ad_script) {
+    v8::Isolate* isolate = v8::Isolate::TryGetCurrent();
+
+    // We don't know the script name/url here, but that's okay. `GetAncestry()`
+    // will look up the ancestry node by script_id and use the
+    // AdScriptIdentifier from that.
+    *out_ad_script = AdScriptIdentifier(
+        GetDebuggerIdForContext(isolate->GetCurrentContext()), top_script_id,
+        "");
+  }
+
+  return is_ad_script;
 }
 
 bool AdTracker::IsKnownAdScript(ExecutionContext* execution_context,
@@ -410,39 +437,6 @@
   return it->value.Contains(url);
 }
 
-bool AdTracker::IsKnownAdScriptForCheckedContext(
-    ExecutionContext& execution_context,
-    std::optional<AdScriptIdentifier>* out_ad_script) {
-  DCHECK(!IsKnownAdExecutionContext(&execution_context));
-  auto it = context_known_ad_scripts_.find(&execution_context);
-  if (it == context_known_ad_scripts_.end()) {
-    return false;
-  }
-
-  if (it->value.empty()) {
-    return false;
-  }
-
-  int top_script_id = ScriptAtTopOfStack();
-  if (top_script_id <= 0) {
-    return false;
-  }
-
-  bool is_ad_script = ad_script_ids_.Contains(top_script_id);
-  if (is_ad_script && out_ad_script) {
-    v8::Isolate* isolate = v8::Isolate::TryGetCurrent();
-
-    // We don't know the script name/url here, but that's okay. `GetAncestry()`
-    // will look up the ancestry node by script_id and use the
-    // AdScriptIdentifier from that.
-    *out_ad_script = AdScriptIdentifier(
-        GetDebuggerIdForContext(isolate->GetCurrentContext()), top_script_id,
-        "");
-  }
-
-  return is_ad_script;
-}
-
 // This is a separate function for testing purposes.
 void AdTracker::AppendToKnownAdScripts(
     ExecutionContext& execution_context,
diff --git a/third_party/blink/renderer/core/frame/ad_tracker.h b/third_party/blink/renderer/core/frame/ad_tracker.h
index 4b06903..2630060 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -221,9 +221,6 @@
 
   void DidExecuteScript();
   bool IsKnownAdScript(ExecutionContext*, const String& url);
-  bool IsKnownAdScriptForCheckedContext(
-      ExecutionContext&,
-      std::optional<AdScriptIdentifier>* out_ad_script);
 
   // Adds the given `url` and its associated `ad_provenance` to the set of known
   // ad scripts associated with the provided `execution_context`.
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 1cb6b73..37b2fa1 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -2111,6 +2111,7 @@
   if (!custom_elements_ && document_) {
     custom_elements_ = MakeGarbageCollected<CustomElementRegistry>(this);
     custom_elements_->AssociatedWith(*document_);
+    document_->SetCustomElementRegistry(custom_elements_);
   }
   return custom_elements_.Get();
 }
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
index 794c8ab3..ef9ee6f 100644
--- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
+++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -193,16 +193,6 @@
 PhysicalNaturalSizingInfo LayoutCustomScrollbarPart::GetNaturalDimensions()
     const {
   NOT_DESTROYED();
-  if (RuntimeEnabledFeatures::
-          LayoutReplacedReturnExplicitDefaultNaturalSizeEnabled()) {
-    // 300x150, no aspect ratio. (Should probably be none.)
-    PhysicalSize natural_size{LayoutUnit(kDefaultWidth),
-                              LayoutUnit(kDefaultHeight)};
-    natural_size.Scale(StyleRef().EffectiveZoom());
-    PhysicalNaturalSizingInfo sizing_info;
-    sizing_info.size = natural_size;
-    return sizing_info;
-  }
   return PhysicalNaturalSizingInfo::None();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.cc b/third_party/blink/renderer/core/layout/layout_embedded_content.cc
index b975c78..771fa27 100644
--- a/third_party/blink/renderer/core/layout/layout_embedded_content.cc
+++ b/third_party/blink/renderer/core/layout/layout_embedded_content.cc
@@ -105,16 +105,6 @@
 
 PhysicalNaturalSizingInfo LayoutEmbeddedContent::GetNaturalDimensions() const {
   NOT_DESTROYED();
-  if (RuntimeEnabledFeatures::
-          LayoutReplacedReturnExplicitDefaultNaturalSizeEnabled()) {
-    // 300x150, no aspect ratio. (Should probably be none.)
-    PhysicalSize natural_size{LayoutUnit(kDefaultWidth),
-                              LayoutUnit(kDefaultHeight)};
-    natural_size.Scale(StyleRef().EffectiveZoom());
-    PhysicalNaturalSizingInfo sizing_info;
-    sizing_info.size = natural_size;
-    return sizing_info;
-  }
   return PhysicalNaturalSizingInfo::None();
 }
 
diff --git a/third_party/blink/renderer/core/paint/box_fragment_painter.cc b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
index f22ba43d..88465eb 100644
--- a/third_party/blink/renderer/core/paint/box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
@@ -1460,10 +1460,6 @@
     rule_outset = style.RowRuleOutset();
   }
 
-  rule_colors.ExpandValues();
-  rule_styles.ExpandValues();
-  rule_widths.ExpandValues();
-
   // Determines if the `end_index` should advance when determining pairs for gap
   // decorations. For `kSpanningItem` rule break, decorations break only at "T"
   // intersections, so we simply check that the intersection isn't blocked
@@ -1558,6 +1554,13 @@
                                       : gap_geometry.GetBlockGapSize();
 
   const auto gaps = gap_geometry.GetGapIntersections(track_direction);
+  auto width_iterator =
+      GapDataListIterator<int>(rule_widths.GetGapDataList(), gaps.size());
+  auto style_iterator = GapDataListIterator<EBorderStyle>(
+      rule_styles.GetGapDataList(), gaps.size());
+  auto color_iterator = GapDataListIterator<StyleColor>(
+      rule_colors.GetGapDataList(), gaps.size());
+
   for (wtf_size_t gap_index = 0; gap_index < gaps.size(); ++gap_index) {
     LayoutUnit inline_start;
     LayoutUnit inline_size;
@@ -1569,6 +1572,13 @@
     CHECK(!gap.empty());
     const auto num_intersections = gap.size();
 
+    StyleColor rule_color = color_iterator.Next();
+    Color resolved_rule_color = style.VisitedDependentGapColor(
+        rule_color, style, /*is_column_rule=*/track_direction == kForColumns);
+    EBorderStyle rule_style =
+        ComputedStyle::CollapsedBorderStyle(style_iterator.Next());
+    LayoutUnit rule_thickness = LayoutUnit(width_iterator.Next());
+
     // Gap decorations are painted relative to (start, end) pairs of gap
     // intersection points in the center of the corresponding gap and parallel
     // to its edges.
@@ -1608,14 +1618,6 @@
       LayoutUnit decoration_end_offset =
           LayoutUnit(end_width / 2.0f) - end_outset;
 
-      StyleColor rule_color =
-          rule_colors.GetGapDecorationForGapIndex(gap_index, gaps.size());
-      Color resolved_rule_color = style.VisitedDependentGapColor(
-          rule_color, style, /*is_column_rule=*/track_direction == kForColumns);
-      EBorderStyle rule_style = ComputedStyle::CollapsedBorderStyle(
-          rule_styles.GetGapDecorationForGapIndex(gap_index, gaps.size()));
-      LayoutUnit rule_thickness = LayoutUnit(
-          rule_widths.GetGapDecorationForGapIndex(gap_index, gaps.size()));
       if (track_direction == kForColumns) {
         // For columns, paint a vertical strip at the center of the gap.
         const LayoutUnit center = gap[start].inline_offset;
diff --git a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc
index 8c233984..89c46e1 100644
--- a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc
+++ b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc
@@ -103,6 +103,13 @@
   texts_queued_for_paint_time_.erase(&object);
 }
 
+void TextPaintTimingDetector::ResetPaintTrackingOnInteraction(
+    const LayoutObject& object) {
+  if (auto iter = recorded_set_.find(&object); iter != recorded_set_.end()) {
+    iter->value = TextPaintStatus::kAllowRepaint;
+  }
+}
+
 bool TextPaintTimingDetector::ShouldWalkObject(
     const LayoutBoxModelObject& aggregator) {
   Node* node = aggregator.GetNode();
@@ -110,8 +117,10 @@
     return false;
 
   // Do not walk the object if it has already been recorded, unless it has
-  // specifically been marked for "re-walking".
-  if (recorded_set_.Contains(&aggregator)) {
+  // specifically been marked for "re-walking" or allowing repaint.
+  if (auto iter = recorded_set_.find(&aggregator);
+      iter != recorded_set_.end() &&
+      iter->value != TextPaintStatus::kAllowRepaint) {
     // TODO(crbug.com/40220033): rewalkable_set_ should be empty most of the
     // time, until we ship the feature for custom fonts.
     // HashSet::Contains() appears to hash key even when container is empty.
@@ -148,7 +157,7 @@
   // correct (i.e. late application of elementtiming or an Interaction which
   // toggles content within the node, i.e. adding textContent for the first time
   // to a previously empty node.)
-  recorded_set_.insert(&aggregator);
+  recorded_set_.insert(&aggregator, TextPaintStatus::kPainted);
   return false;
 }
 
@@ -206,10 +215,10 @@
     }
   }
 
-  recorded_set_.insert(&aggregator);
+  auto result = recorded_set_.Set(&aggregator, TextPaintStatus::kPainted);
   TextRecord* record = MaybeRecordTextRecord(
       aggregator, aggregated_size, property_tree_state, aggregated_visual_rect,
-      mapped_visual_rect, context);
+      mapped_visual_rect, context, /*is_repaint=*/!result.is_new_entry);
   if (context && record) {
     context->AddPaintedArea(record);
   }
@@ -325,12 +334,14 @@
     const PropertyTreeStateOrAlias& property_tree_state,
     const gfx::Rect& frame_visual_rect,
     const gfx::RectF& root_visual_rect,
-    SoftNavigationContext* context) {
+    SoftNavigationContext* context,
+    bool is_repaint) {
   Node* node = object.GetNode();
   DCHECK(node);
 
   bool is_needed_for_lcp = IsRecordingLargestTextPaint() && visual_size > 0u;
-  bool is_needed_for_element_timing = TextElementTiming::NeededForTiming(*node);
+  bool is_needed_for_element_timing =
+      !is_repaint && TextElementTiming::NeededForTiming(*node);
   bool is_needed_for_soft_navs = context != nullptr;
 
   // If the node is not required by LCP and not required by ElementTiming,
diff --git a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.h b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.h
index 51a410d..710da96 100644
--- a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.h
+++ b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.h
@@ -109,6 +109,12 @@
     callback_manager_ = manager;
   }
 
+  // Mark that the `LayoutObject` should be considered for paint timing, even if
+  // it's already been painted, because it was modified as part of an
+  // interaction (after hard LCP has stopped). This will not cause new element
+  // timing entries to be emitted.
+  void ResetPaintTrackingOnInteraction(const LayoutObject&);
+
   inline bool IsRecordingLargestTextPaint() const {
     return recording_largest_text_paint_;
   }
@@ -121,6 +127,9 @@
  private:
   friend class LargestContentfulPaintCalculatorTest;
 
+  // The state of `LayoutObject`s being tracked in the `recorded_set_`.
+  enum class TextPaintStatus { kPainted, kAllowRepaint };
+
   void AssignPaintTimeToQueuedRecords(uint32_t frame_index,
                                       const base::TimeTicks&,
                                       const DOMPaintTimingInfo&);
@@ -130,7 +139,8 @@
       const PropertyTreeStateOrAlias& property_tree_state,
       const gfx::Rect& frame_visual_rect,
       const gfx::RectF& root_visual_rect,
-      SoftNavigationContext* context);
+      SoftNavigationContext* context,
+      bool is_repaint);
   inline void QueueToMeasurePaintTime(const LayoutObject& object,
                                       TextRecord* record) {
     texts_queued_for_paint_time_.insert(&object, record);
@@ -138,7 +148,7 @@
   }
 
   // LayoutObjects for which text has been aggregated.
-  HeapHashSet<Member<const LayoutObject>> recorded_set_;
+  HeapHashMap<Member<const LayoutObject>, TextPaintStatus> recorded_set_;
   HeapHashSet<Member<const LayoutObject>> rewalkable_set_;
 
   // Text records queued for paint time. Indexed by LayoutObject to make removal
diff --git a/third_party/blink/renderer/core/style/gap_data_list.h b/third_party/blink/renderer/core/style/gap_data_list.h
index 56e6506a..1c0c974 100644
--- a/third_party/blink/renderer/core/style/gap_data_list.h
+++ b/third_party/blink/renderer/core/style/gap_data_list.h
@@ -102,7 +102,6 @@
 
   void Trace(Visitor* visitor) const {
     visitor->Trace(gap_data_list_);
-    TraceIfNeeded<VectorType>::Trace(visitor, expanded_values_);
   }
 
   const GapDataVector& GetGapDataList() const { return gap_data_list_; }
@@ -115,97 +114,6 @@
     return gap_data_list_[0].GetValue();
   }
 
-  // TODO(samomekarajr): Potential optimization. We might not need to expand
-  // values. Instead, we can adopt a method similar to the grid's implementation
-  // by using sets. This way, when given a particular gap index, we can
-  // translate it to a specific item in the set. This approach allows us to
-  // avoid expanding values and storing them in a vector, especially when an
-  // integer repeater has a very large count. For this to be worthwhie, we need
-  // to be able to get a given decoration value for a gap index in less than
-  // O(n) time.
-
-  // Expands `gap_data_list_` into `expanded_values_` by evaluating the
-  // repeaters and storing the values in the order they are specified.
-  // When an auto repeater is present, it stores the range of the auto
-  // repeated values as [`auto_repeat_start_`, `auto_repeat_end_`).
-  void ExpandValues() {
-    expanded_values_.clear();
-    auto_repeat_start_ = kNotFound;
-    auto_repeat_end_ = kNotFound;
-
-    for (const auto& gap_data : gap_data_list_) {
-      if (!gap_data.IsRepeaterData()) {
-        // Simple single value, add to `expanded_values_`.
-        expanded_values_.push_back(gap_data.GetValue());
-      } else {
-        const ValueRepeater<T>* repeater = gap_data.GetValueRepeater();
-
-        if (repeater->IsAutoRepeater()) {
-          // Only one auto repeater is allowed, so store the range of the auto
-          // repeated values.
-          CHECK_EQ(auto_repeat_start_, kNotFound);
-          CHECK_EQ(auto_repeat_end_, kNotFound);
-          auto_repeat_start_ = expanded_values_.size();
-          for (const auto& value : repeater->RepeatedValues()) {
-            expanded_values_.push_back(value);
-          }
-          auto_repeat_end_ = expanded_values_.size();
-        } else {
-          // Integer repeater, add values `count` times.
-          wtf_size_t count = repeater->RepeatCount();
-
-          for (size_t i = 0; i < count; ++i) {
-            for (const auto& value : repeater->RepeatedValues()) {
-              expanded_values_.push_back(value);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  // Returns the gap decoration value for a given gap index. It uses the
-  // `auto_repeat_start_` and `auto_repeat_end_` to partition the
-  // `expanded_values_` into leading, auto repeat, and trailing sections. The
-  // value at the given index is then determined based on the section it falls
-  // into.
-  T GetGapDecorationForGapIndex(wtf_size_t gap_index,
-                                wtf_size_t total_gaps) const {
-    if (auto_repeat_start_ == kNotFound) {
-      // No auto repeaters are present, so we need to return the value at the
-      // valid index. The size of `expanded_values_` might be less than the
-      // `total_gaps`, so we apply values cyclically.
-      return expanded_values_[gap_index % expanded_values_.size()];
-    }
-
-    // Leading section ends at the start of the auto repeat section.
-    const wtf_size_t leading_section_end = auto_repeat_start_;
-
-    // Trailing section starts after the auto repeat section so it'll be the
-    // number of gaps minus the number of trailing values.
-    const wtf_size_t trailing_section_start =
-        total_gaps - (expanded_values_.size() - auto_repeat_end_);
-
-    if (gap_index < leading_section_end) {
-      // Leading values can be indexed directly.
-      return expanded_values_[gap_index];
-    } else if (gap_index >= trailing_section_start) {
-      // Get the index of the gap relative to the trailing section and return
-      // expanded value at that index. Note: `trailing_index` indicates the
-      // index of the gap relative to trailing values, hence we need to add
-      // `auto_repeat_end_` to get the actual index in the expanded values.
-      wtf_size_t trailing_index = gap_index - trailing_section_start;
-      return expanded_values_[auto_repeat_end_ + trailing_index];
-    } else {
-      // For auto repeat values, we get the index of the gap relative to the
-      // auto section and return the expanded value at that index.
-      wtf_size_t auto_section_length = auto_repeat_end_ - auto_repeat_start_;
-      wtf_size_t gap_index_in_auto_section =
-          (gap_index - leading_section_end) % auto_section_length;
-      return expanded_values_[auto_repeat_start_ + gap_index_in_auto_section];
-    }
-  }
-
   bool operator==(const GapDataList& o) const {
     return gap_data_list_ == o.gap_data_list_;
   }
@@ -214,16 +122,230 @@
 
  private:
   GapDataVector gap_data_list_;
+};
 
-  // Holds the expanded values of `gap_data_list_` in the order they are
-  // specified. This is used to get the gap decoration value for a given gap
-  // index. If the `gap_data_list_` contains an auto repeater, the repeated
-  // values are stored in the order they are specified, with
-  // `auto_repeat_start_` and `auto_repeat_end_` indicating the range of the
-  // auto repeated values.
-  VectorType expanded_values_;
-  wtf_size_t auto_repeat_start_ = kNotFound;
-  wtf_size_t auto_repeat_end_ = kNotFound;
+// GapDataListIterator traverses a GapDataList without fully expanding repeater
+// gap data. At paint time, the number of gaps is fixed. Using that information,
+// the iterator segments the GapDataList into three logical regions based on the
+// position of the auto-repeater: Leading, Auto and Trailing.
+//
+// Each region is assigned a slot count indicating how many gaps it contributes.
+// The iterator uses internal state to walk through the list item-by-item,
+// respecting repeat counts and repeated value sequences without constructing
+// the expanded form.
+template <typename T>
+class CORE_EXPORT GapDataListIterator {
+  DISALLOW_NEW();
+  // Enum to represent three possible regions in the gap data list:
+  // - kLeading: Fixed data before an auto-repeater.
+  // - kAuto: Auto-repeating segment.
+  // - kTrailing: Fixed data after an auto-repeater.
+  enum GapDataListRegion { kLeading, kAuto, kTrailing };
+
+ public:
+  using GapDataVector = GapDataList<T>::GapDataVector;
+  using GapData = GapData<T>;
+  explicit GapDataListIterator(const GapDataVector& gap_data_list,
+                               wtf_size_t gap_count)
+      : gap_data_list_(gap_data_list), gap_count_(gap_count) {
+    CHECK(!gap_data_list_.empty());
+    BuildRegions();
+
+    if (auto_idx_ == 0) {
+      // Here, the auto repeater is the first item, so start at kAuto region.
+      region_ = kAuto;
+      current_region_slots_remaining_ = auto_repeat_slot_count_;
+      repeated_value_idx_ = 0;
+    } else {
+      // Auto-repeater is not the first item, start at kLeading region.
+      region_ = kLeading;
+      current_region_slots_remaining_ = leading_slot_count_;
+      list_idx_ = 0;
+      InitNonAutoDataState();
+    }
+  }
+
+  bool HasNext() const { return current_gap_index_ < gap_count_; }
+
+  T Next() {
+    CHECK(HasNext());
+    T value = GetData();
+
+    --current_region_slots_remaining_;
+    current_gap_index_++;
+
+    // Either advance in the current region or move to the next region.
+    if (current_region_slots_remaining_ > 0) {
+      AdvanceWithinCurrentRegion();
+    } else if (current_gap_index_ < gap_count_) {
+      TransitionToNextRegion();
+    }
+
+    return value;
+  }
+
+ private:
+  // Iterates through `gap_data_list_` to determine region boundaries and slot
+  // counts.
+  void BuildRegions() {
+    leading_slot_count_ = 0;
+    trailing_slot_count_ = 0;
+    auto_repeat_slot_count_ = 0;
+    auto_idx_ = kNotFound;
+
+    for (wtf_size_t i = 0; i < gap_data_list_.size(); ++i) {
+      const GapData& gap_data = gap_data_list_[i];
+
+      wtf_size_t gap_data_slot_count = 1;
+      if (gap_data.IsRepeaterData()) {
+        if (gap_data.GetValueRepeater()->IsAutoRepeater()) {
+          CHECK_EQ(auto_idx_, kNotFound);
+          auto_idx_ = i;
+          continue;
+        }
+        gap_data_slot_count =
+            gap_data.GetValueRepeater()->RepeatCount() *
+            gap_data.GetValueRepeater()->RepeatedValues().size();
+      }
+
+      if (auto_idx_ == kNotFound) {
+        leading_slot_count_ += gap_data_slot_count;
+      } else {
+        trailing_slot_count_ += gap_data_slot_count;
+      }
+    }
+    if (auto_idx_ != kNotFound) {
+      // Compute the number of slots allocated to the auto region. If the
+      // combined slots from leading and trailing regions is greater than the
+      // total gap count, the auto region slot count remains zero.
+      wtf_size_t combined_slot_count =
+          leading_slot_count_ + trailing_slot_count_;
+      if (combined_slot_count < gap_count_) {
+        auto_repeat_slot_count_ = gap_count_ - combined_slot_count;
+      }
+    }
+  }
+
+  // Retrieves the current value based on the region and index.
+  T GetData() const {
+    const GapData& gap_data =
+        gap_data_list_[region_ == kAuto ? auto_idx_ : list_idx_];
+    return gap_data.IsRepeaterData()
+               ? gap_data.GetValueRepeater()
+                     ->RepeatedValues()[repeated_value_idx_]
+               : gap_data.GetValue();
+  }
+
+  void AdvanceWithinCurrentRegion() {
+    if (region_ == GapDataListRegion::kAuto) {
+      AdvanceWithinAutoRegion();
+    } else {
+      AdvanceWithinNonAutoRegion();
+    }
+  }
+
+  void AdvanceWithinNonAutoRegion() {
+    repeated_value_idx_ += 1;
+
+    const GapData& gap_data = gap_data_list_[list_idx_];
+
+    // Determine how many repeated values are associated with this gap_data. If
+    // it's not a repeater (i.e. regular gap data item), we treat it as having
+    // one repeated value with a single repeat.
+    wtf_size_t repeated_values_count =
+        gap_data.IsRepeaterData()
+            ? gap_data.GetValueRepeater()->RepeatedValues().size()
+            : 1;
+
+    // If we've processed all values for this gap_data:
+    // - Reset `repeated_value_idx_` for the next repeat cycle.
+    // - Decrement remaining repeat count.
+    // - If no repeats remain, advance to the next item.
+    if (repeated_value_idx_ == repeated_values_count) {
+      repeated_value_idx_ = 0;
+      repeats_left_ -= 1;
+      if (repeats_left_ == 0) {
+        list_idx_++;
+        InitNonAutoDataState();
+      }
+    }
+  }
+
+  void AdvanceWithinAutoRegion() {
+    CHECK_EQ(region_, kAuto);
+    wtf_size_t repeated_auto_values_size =
+        gap_data_list_[auto_idx_].GetValueRepeater()->RepeatedValues().size();
+    repeated_value_idx_ = (repeated_value_idx_ + 1) % repeated_auto_values_size;
+  }
+
+  void TransitionToNextRegion() {
+    switch (region_) {
+      case kLeading:
+        if (auto_idx_ == kNotFound) {
+          // No auto-repeater, so cycle back to the leading.
+          current_region_slots_remaining_ = leading_slot_count_;
+          list_idx_ = 0;
+          InitNonAutoDataState();
+        } else {
+          if (auto_repeat_slot_count_ > 0) {
+            // Move from leading to the auto region.
+            region_ = GapDataListRegion::kAuto;
+            current_region_slots_remaining_ = auto_repeat_slot_count_;
+            repeated_value_idx_ = 0;
+          } else {
+            // Auto-repeater is present but squashed due
+            // `leading_slot_count_` + `trailing_slot_count_`
+            // being greater than or equal to the number of gaps, so jump to
+            // trailing segment.
+            region_ = GapDataListRegion::kTrailing;
+            current_region_slots_remaining_ = trailing_slot_count_;
+            list_idx_ = auto_idx_ + 1;
+            InitNonAutoDataState();
+          }
+        }
+        break;
+      case kAuto:
+        // Move from the auto region to the trailing region.
+        region_ = GapDataListRegion::kTrailing;
+        current_region_slots_remaining_ = trailing_slot_count_;
+        list_idx_ = auto_idx_ + 1;
+        InitNonAutoDataState();
+        break;
+      case kTrailing:
+        // Should mark end of iteration.
+        CHECK_EQ(current_gap_index_, gap_count_);
+        break;
+    }
+  }
+
+  void InitNonAutoDataState() {
+    const GapData& gap_data = gap_data_list_[list_idx_];
+    if (gap_data.IsRepeaterData()) {
+      CHECK(!gap_data.GetValueRepeater()->IsAutoRepeater());
+      repeats_left_ = gap_data.GetValueRepeater()->RepeatCount();
+    } else {
+      repeats_left_ = 1;
+    }
+    repeated_value_idx_ = 0;
+  }
+
+  const GapDataVector& gap_data_list_;
+  wtf_size_t gap_count_;
+
+  // Index of the current gap to which we are assigning a gap data.
+  wtf_size_t current_gap_index_ = 0;
+
+  wtf_size_t leading_slot_count_, auto_repeat_slot_count_, trailing_slot_count_;
+
+  // Traversal states.
+  GapDataListRegion region_;
+  wtf_size_t current_region_slots_remaining_ = 0;
+
+  // Internal iterators states.
+  wtf_size_t list_idx_ = 0;
+  wtf_size_t auto_idx_ = kNotFound;
+  wtf_size_t repeats_left_ = 0;
+  wtf_size_t repeated_value_idx_ = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
index 28490fd..73d17e5 100644
--- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
+++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -229,8 +229,10 @@
   LocalFrame* frame = window->GetFrame();
   CHECK(frame && frame->View());
   if (IsPrePaintBasedAttributionEnabled()) {
+    TextPaintTimingDetector* detector =
+        &frame->View()->GetPaintTimingDetector().GetTextPaintTimingDetector();
     paint_attribution_tracker_ =
-        MakeGarbageCollected<SoftNavigationPaintAttributionTracker>();
+        MakeGarbageCollected<SoftNavigationPaintAttributionTracker>(detector);
   }
 }
 
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.cc b/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.cc
index 3cf4a64..b9a2837 100644
--- a/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.cc
+++ b/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.cc
@@ -4,27 +4,43 @@
 
 #include "third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h"
 
+#include "base/check_deref.h"
+#include "base/feature_list.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/timing/soft_navigation_context.h"
 
 namespace blink {
 
 namespace {
+
 // TODO(crbug.com/423670827): Consider moving this to ImagePaintTimingDetector.
 bool IsImageType(const LayoutObject& object) {
   return object.IsImage() || object.IsSVGImage() || object.IsVideo() ||
          object.StyleRef().HasBackgroundImage();
 }
+
+// When enabled, text aggregator nodes are marked as needing repaint in the
+// `TextPaintTimingDetector` when the `SoftNavigationContext` associated with
+// the node changes.
+BASE_FEATURE(kMarkTextNodesForRepaintOnContextChange,
+             "MarkTextNodesForRepaintOnContextChange",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 }  // namespace
 
-SoftNavigationPaintAttributionTracker::SoftNavigationPaintAttributionTracker() =
-    default;
+SoftNavigationPaintAttributionTracker::SoftNavigationPaintAttributionTracker(
+    TextPaintTimingDetector* detector)
+    : text_paint_timing_detector_(detector) {
+  CHECK(text_paint_timing_detector_);
+}
 
 void SoftNavigationPaintAttributionTracker::Trace(Visitor* visitor) const {
   visitor->Trace(marked_nodes_);
+  visitor->Trace(text_paint_timing_detector_);
 }
 
 void SoftNavigationPaintAttributionTracker::MarkNodeAsDirectlyModified(
@@ -41,9 +57,11 @@
   // If this node is being modified again by the same context in the same
   // generation, there's no need to update anything, unless upgrading to a
   // direct modification.
-  if (auto* state = GetNodeState(node)) {
-    if (state->IsDirectlyModified() &&
-        state->ModificationId() == current_modification_generation_id_) {
+  NodeState* previous_node_state = GetNodeState(node);
+  if (previous_node_state) {
+    if (previous_node_state->IsDirectlyModified() &&
+        previous_node_state->ModificationId() ==
+            current_modification_generation_id_) {
       return;
     }
   }
@@ -54,6 +72,10 @@
   context->AddModifiedNode(node);
   if (auto* object = node->GetLayoutObject()) {
     object->MarkSoftNavigationContextChanged();
+    if (!previous_node_state ||
+        previous_node_state->GetSoftNavigationContext() != context) {
+      NotifyPaintTimingDetectorOnContextChanged(*object);
+    }
   }
 }
 
@@ -63,8 +85,8 @@
   CHECK(node);
   CHECK(inherited_state);
 
-  NodeState* current_paint_state = GetNodeState(node);
-  if (current_paint_state && current_paint_state->ModificationId() >=
+  NodeState* previous_node_state = GetNodeState(node);
+  if (previous_node_state && previous_node_state->ModificationId() >=
                                  inherited_state->ModificationId()) {
     return;
   }
@@ -77,6 +99,11 @@
                               inherited_state->GetSoftNavigationContext(),
                               inherited_state->ModificationId(),
                               /*is_directly_modified=*/false));
+  if (!previous_node_state || previous_node_state->GetSoftNavigationContext() !=
+                                  inherited_state->GetSoftNavigationContext()) {
+    NotifyPaintTimingDetectorOnContextChanged(
+        CHECK_DEREF(node->GetLayoutObject()));
+  }
 }
 
 SoftNavigationPaintAttributionTracker::PrePaintUpdateResult
@@ -132,6 +159,17 @@
   return PrePaintUpdateResult::kPropagateAncestorNode;
 }
 
+void SoftNavigationPaintAttributionTracker::
+    NotifyPaintTimingDetectorOnContextChanged(const LayoutObject& object) {
+  if (!base::FeatureList::IsEnabled(kMarkTextNodesForRepaintOnContextChange)) {
+    return;
+  }
+  if (IsImageType(object)) {
+    return;
+  }
+  text_paint_timing_detector_->ResetPaintTrackingOnInteraction(object);
+}
+
 SoftNavigationPaintAttributionTracker::NodeState::NodeState(
     SoftNavigationContext* context,
     uint64_t modification_id,
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h b/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h
index b0ad1dfa..864f799 100644
--- a/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h
+++ b/third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h
@@ -15,6 +15,7 @@
 class LayoutObject;
 class Node;
 class SoftNavigationContext;
+class TextPaintTimingDetector;
 
 // `SoftNavigationPaintAttributionTracker` helps attribute contentful paints to
 // DOM nodes that were modified as part of an interaction, working together with
@@ -70,7 +71,7 @@
 class CORE_EXPORT SoftNavigationPaintAttributionTracker
     : public GarbageCollected<SoftNavigationPaintAttributionTracker> {
  public:
-  SoftNavigationPaintAttributionTracker();
+  explicit SoftNavigationPaintAttributionTracker(TextPaintTimingDetector*);
 
   // Initializes paint tracking for the given node, such that contentful paints
   // to it or its descendants will be associated with the given context.
@@ -151,6 +152,11 @@
   // "contenful nodes" (images and text aggregation nodes).
   void MarkNodeForPaintTrackingIfNeeded(Node* node, NodeState* inherited_state);
 
+  // Inform the relevant paint timing detector that we need paint tracking for
+  // the object -- regardless of whether its been previously painted -- because
+  // its `SoftNavigationContext` changed.
+  void NotifyPaintTimingDetectorOnContextChanged(const LayoutObject&);
+
   // IDs used for determining the modification order of `NodeState` objects.  We
   // use a "modification generation" scheme, incrementing the
   // `current_modification_generation_id_` when `MarkNodeAsDirectlyModified()`
@@ -172,6 +178,8 @@
   // eligible for GC earlier, but need to figure out how attribution should be
   // handled if there are ancestors with an older context.
   HeapHashMap<WeakMember<Node>, Member<NodeState>> marked_nodes_;
+
+  Member<TextPaintTimingDetector> text_paint_timing_detector_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/web_media_player_ms_compositor.cc b/third_party/blink/renderer/modules/mediastream/web_media_player_ms_compositor.cc
index 79ca485..d8ad1c7 100644
--- a/third_party/blink/renderer/modules/mediastream/web_media_player_ms_compositor.cc
+++ b/third_party/blink/renderer/modules/mediastream/web_media_player_ms_compositor.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/hash/hash.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -473,7 +474,16 @@
     // same as |current_frame_|. Function SetCurrentFrame() handles whether
     // to increase |dropped_frame_count_| for that frame, so here we should
     // increase |dropped_frame_count_| by the count of all other frames.
-    dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1;
+    //
+    // Use std::max to prevent |dropped_frame_count_| from integer underflow
+    // when frames_queued() is 0.
+    if (base::FeatureList::IsEnabled(
+            media::kMediaStreamAccurateDroppedFrameCount)) {
+      dropped_frame_count_ +=
+          std::max<size_t>(rendering_frame_buffer_->frames_queued(), 1u) - 1;
+    } else {
+      dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1;
+    }
     rendering_frame_buffer_->Reset();
     pending_frames_info_.clear();
     RenderWithoutAlgorithm(frame, is_copy);
@@ -774,8 +784,18 @@
                        TRACE_EVENT_SCOPE_THREAD, "Timestamp",
                        frame->timestamp().InMicroseconds());
 
-  if (!current_frame_rendered_)
-    ++dropped_frame_count_;
+  if (base::FeatureList::IsEnabled(
+          media::kMediaStreamAccurateDroppedFrameCount)) {
+    // Check if there was a previous frame that wasn't rendered
+    if (current_frame_ && !current_frame_rendered_) {
+      ++dropped_frame_count_;
+    }
+  } else {
+    if (!current_frame_rendered_) {
+      ++dropped_frame_count_;
+    }
+  }
+
   current_frame_rendered_ = false;
 
   // Compare current frame with |frame|. Initialize values as if there is no
diff --git a/third_party/blink/renderer/modules/ml/BUILD.gn b/third_party/blink/renderer/modules/ml/BUILD.gn
index 30a59faf..f0cde24 100644
--- a/third_party/blink/renderer/modules/ml/BUILD.gn
+++ b/third_party/blink/renderer/modules/ml/BUILD.gn
@@ -22,6 +22,8 @@
     "webnn/ml_graph.h",
     "webnn/ml_graph_builder.cc",
     "webnn/ml_graph_builder.h",
+    "webnn/ml_graph_transform/constant_folding_transformer.cc",
+    "webnn/ml_graph_transform/constant_folding_transformer.h",
     "webnn/ml_graph_transform/layout_transformer.cc",
     "webnn/ml_graph_transform/layout_transformer.h",
     "webnn/ml_graph_transform/ml_graph_transformer.cc",
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.cc b/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.cc
index ae545e6..1cdad02c 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.cc
@@ -17,6 +17,14 @@
                 webnn::mojom::blink::Operand::Kind::kConstant,
                 std::move(descriptor)) {}
 
+MLConstantOperand::MLConstantOperand(MLGraphBuilder* builder,
+                                     webnn::OperandDescriptor descriptor,
+                                     WebNNPendingConstantToken handle)
+    : MLOperand(builder,
+                webnn::mojom::blink::Operand::Kind::kConstant,
+                std::move(descriptor)),
+      handle_(std::move(handle)) {}
+
 MLConstantOperand::MLConstantOperand(MLGraphBuilder* builder, MLTensor* tensor)
     : MLOperand(builder,
                 webnn::mojom::blink::Operand::Kind::kConstant,
@@ -30,4 +38,9 @@
   MLOperand::Trace(visitor);
 }
 
+void MLConstantOperand::SetPendingPermutation(
+    base::span<const uint32_t> permutation) {
+  descriptor_.SetPendingPermutation(permutation);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h b/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h
index 5544010..b93f4ca 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h
@@ -27,6 +27,10 @@
   MLConstantOperand(MLGraphBuilder* builder,
                     webnn::OperandDescriptor descriptor);
 
+  MLConstantOperand(MLGraphBuilder* builder,
+                    webnn::OperandDescriptor descriptor,
+                    WebNNPendingConstantToken handle);
+
   // Similar to above but uses a tensor for weight data.
   MLConstantOperand(MLGraphBuilder* builder, MLTensor* tensor);
 
@@ -41,6 +45,8 @@
 
   const MLTensor* tensor() const { return tensor_; }
 
+  void SetPendingPermutation(base::span<const uint32_t> permutation);
+
  private:
   // Identifies this constant operand in the WebNN service.
   const WebNNPendingConstantToken handle_;
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
index e22e8b94..7f2d75f 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
@@ -66,6 +66,7 @@
 #include "third_party/blink/renderer/modules/ml/ml_context.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test_utils.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/qdq_detection_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/transpose_elimination_transformer.h"
@@ -1673,7 +1674,7 @@
     ASSERT_THAT(builder, testing::NotNull());
 
     // [a] -> transpose -> [b] -> transpose -> [c]
-    // This shouldn't be eliminated otherwise the graph will have no operation.
+    // This shouldn't be eliminated otherwise the graph will have no operations.
     auto* a = BuildInput(scope.GetScriptState(), builder, "a", {3, 4, 5},
                          V8MLOperandDataType::Enum::kFloat32, exception_state);
     auto* transpose_options = MLTransposeOptions::Create();
@@ -2188,4 +2189,81 @@
   }
 }
 
+TEST_F(MLGraphTest, MLConstantFoldingTransformerNoOpTest) {
+  V8TestingScope scope;
+  // Bind fake WebNN Context in the service for testing.
+  ScopedWebNNServiceBinder scoped_setup_binder(*this, scope);
+  MLContext* context = CreateContext(scope, MLContextOptions::Create());
+
+  DummyExceptionStateForTesting exception_state;
+  auto* builder =
+      MLGraphBuilder::Create(scope.GetScriptState(), context, exception_state);
+  ASSERT_THAT(builder, testing::NotNull());
+
+  // [a] -> transpose -> [b]
+  // This shouldn't be eliminated otherwise the graph will have no operations.
+  auto* a = BuildConstant(scope.GetScriptState(), builder, {3, 4, 5},
+                          V8MLOperandDataType::Enum::kFloat32, exception_state);
+  auto* transpose_options = MLTransposeOptions::Create();
+  transpose_options->setPermutation({0, 2, 1});
+  auto* b = builder->transpose(a, transpose_options, exception_state);
+  ASSERT_THAT(b, testing::NotNull());
+
+  EXPECT_EQ(b->Shape(), std::vector<uint32_t>({3, 5, 4}));
+  MLNamedOperands named_outputs = {{"b", b}};
+
+  auto* constant_folding_transformer =
+      MakeGarbageCollected<ConstantFoldingTransformer>(builder);
+  constant_folding_transformer->Transform(named_outputs);
+
+  // Expect no change in the graph.
+  EXPECT_EQ(b->Operator()->Inputs()[0], a);
+
+  auto [graph, error_name, error_message] =
+      BuildGraph(scope, builder, named_outputs);
+  ASSERT_THAT(graph, testing::NotNull());
+}
+
+TEST_F(MLGraphTest, MLConstantFoldingTransformerTest) {
+  V8TestingScope scope;
+  // Bind fake WebNN Context in the service for testing.
+  ScopedWebNNServiceBinder scoped_setup_binder(*this, scope);
+  MLContext* context = CreateContext(scope, MLContextOptions::Create());
+  DummyExceptionStateForTesting exception_state;
+  auto* builder =
+      MLGraphBuilder::Create(scope.GetScriptState(), context, exception_state);
+  ASSERT_THAT(builder, testing::NotNull());
+
+  // [a] -> transpose -> reshape -> transpose -> relu -> [e]
+  auto* a = BuildConstant(scope.GetScriptState(), builder, {3, 4, 5},
+                          V8MLOperandDataType::Enum::kFloat32, exception_state);
+  auto* transpose_options = MLTransposeOptions::Create();
+  transpose_options->setPermutation({0, 2, 1});
+  auto* b = builder->transpose(a, transpose_options, exception_state);
+  ASSERT_THAT(b, testing::NotNull());
+  auto* c = builder->reshape(b, {3, 20}, MLOperatorOptions::Create(),
+                             exception_state);
+  ASSERT_THAT(c, testing::NotNull());
+  auto* d =
+      builder->transpose(c, MLTransposeOptions::Create(), exception_state);
+  ASSERT_THAT(d, testing::NotNull());
+  auto* e = builder->relu(d, MLOperatorOptions::Create(), exception_state);
+  ASSERT_THAT(e, testing::NotNull());
+
+  MLNamedOperands named_outputs = {{"e", e}};
+
+  auto* constant_folding_transformer =
+      MakeGarbageCollected<ConstantFoldingTransformer>(builder);
+  constant_folding_transformer->Transform(named_outputs);
+  auto& relu_input = e->Operator()->Inputs()[0];
+  EXPECT_EQ(relu_input->Kind(), webnn::mojom::blink::Operand::Kind::kConstant);
+  Vector<uint32_t> expected_shape{20, 3};
+  EXPECT_EQ(e->shape(), expected_shape);
+  EXPECT_EQ(e->shape(), relu_input->shape());
+
+  auto [graph, error_name, error_message] =
+      BuildGraph(scope, builder, named_outputs);
+  ASSERT_THAT(graph, testing::NotNull());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.cc
new file mode 100644
index 0000000..cd80c8b
--- /dev/null
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.cc
@@ -0,0 +1,92 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h"
+
+#include "services/webnn/public/cpp/operand_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_transpose_options.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_graph_utils.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_operand.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_operator.h"
+
+namespace blink_mojom = webnn::mojom::blink;
+
+namespace blink {
+
+void ConstantFoldingTransformer::Transform(MLNamedOperands& named_outputs) {
+  HeapVector<Member<MLOperator>> sorted_operators =
+      GetOperatorsInTopologicalOrder(named_outputs);
+  HeapHashSet<Member<const MLOperator>> graph_output_operators =
+      GetGraphOutputOperators(named_outputs);
+
+  for (auto& op : sorted_operators) {
+    if (!graph_output_operators.Contains(op)) {
+      TryFoldConstant(*op);
+    }
+  }
+}
+
+void ConstantFoldingTransformer::TryFoldConstant(MLOperator& op) {
+  if (op.Kind() != blink_mojom::Operation::Tag::kTranspose &&
+      op.Kind() != blink_mojom::Operation::Tag::kReshape) {
+    return;
+  }
+  MLOperand* input = op.Inputs()[0];
+  if (input->Kind() != blink_mojom::Operand::Kind::kConstant) {
+    return;
+  }
+  MLOperand* output = op.Outputs()[0];
+  if (input->DependentOperators().size() != 1 ||
+      output->DependentOperators().size() != 1) {
+    return;
+  }
+  MLConstantOperand* constant_operand = input->AsConstantOperand();
+  if (op.Kind() == blink_mojom::Operation::Tag::kTranspose) {
+    // TODO(crbug.com/428232161): Support sub byte transposes.
+    if (webnn::OperandDescriptor::GetBitsPerElement(input->DataType()) < 8u) {
+      return;
+    }
+    // TODO(crbug.com/428232161): Support transposing constant tensors.
+    if (constant_operand->tensor()) {
+      return;
+    }
+  }
+  MLConstantOperand* new_constant_operand =
+      ReplaceConstantOperandWithNewShape(constant_operand, output->shape());
+  RemoveUnaryOperator(&op);
+  if (op.Kind() == blink_mojom::Operation::Tag::kReshape) {
+    return;
+  }
+
+  // If the op is transpose, apply permutation to the new constant.
+  auto* options = static_cast<const MLTransposeOptions*>(op.Options());
+  wtf_size_t rank = input->Rank();
+  Vector<uint32_t> default_permutation = CreateDefaultPermutation(rank);
+  Vector<uint32_t> permutation =
+      options->getPermutationOr(std::move(default_permutation));
+  ApplyPermutation(constant_operand, new_constant_operand,
+                   std::move(permutation));
+}
+
+void ConstantFoldingTransformer::ApplyPermutation(
+    MLConstantOperand* old_constant,
+    MLConstantOperand* new_constant,
+    Vector<uint32_t> permutation) {
+  base::span<const uint32_t> previous_permutation =
+      old_constant->Descriptor().pending_permutation();
+  if (previous_permutation.empty()) {
+    new_constant->SetPendingPermutation(permutation);
+    return;
+  }
+  Vector<uint32_t> squashed_permutation(permutation.size());
+  for (size_t i = 0; i < permutation.size(); ++i) {
+    // The new permutation maps index 'i' to
+    // previous_permutation[permutation[i]]
+    squashed_permutation[i] = previous_permutation[permutation[i]];
+  }
+  new_constant->SetPendingPermutation(squashed_permutation);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h
new file mode 100644
index 0000000..8a3a10c
--- /dev/null
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_TRANSFORM_CONSTANT_FOLDING_TRANSFORMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_TRANSFORM_CONSTANT_FOLDING_TRANSFORMER_H_
+
+#include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+
+namespace blink {
+
+class MLConstantOperand;
+
+// Fold reshape and transpose operations on constants so that only output of
+// these operations are left as constants.
+class MODULES_EXPORT ConstantFoldingTransformer : public MLGraphTransformer {
+ public:
+  explicit ConstantFoldingTransformer(MLGraphBuilder* graph_builder)
+      : MLGraphTransformer(graph_builder) {}
+  void Transform(MLNamedOperands& named_outputs) override;
+
+ private:
+  void TryFoldConstant(MLOperator& op);
+  void ApplyPermutation(MLConstantOperand* old_constant,
+                        MLConstantOperand* new_constant,
+                        Vector<uint32_t> permutation);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_TRANSFORM_CONSTANT_FOLDING_TRANSFORMER_H_
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.cc
index 4dcf5ca5d..d531827 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_lstm_cell_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_lstm_options.h"
 #include "third_party/blink/renderer/modules/ml/ml_context.h"
+#include "third_party/blink/renderer/modules/ml/webnn/ml_constant_operand.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_utils.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_operand.h"
 
@@ -332,12 +333,14 @@
 }
 
 // static
-void MLGraphTransformer::ReplaceOperand(MLOperand* old_operand,
+void MLGraphTransformer::ReplaceOperand(const MLOperand* old_operand,
                                         MLOperand* new_operand) {
-  auto* op = old_operand->Operator();
-  for (auto& output : op->outputs_) {
-    if (output == old_operand) {
-      output = new_operand;
+  if (old_operand->Kind() == webnn::mojom::blink::Operand::Kind::kOutput) {
+    auto* op = old_operand->Operator();
+    for (auto& output : op->outputs_) {
+      if (output == old_operand) {
+        output = new_operand;
+      }
     }
   }
 
@@ -361,6 +364,23 @@
   return new_operand;
 }
 
+MLConstantOperand* MLGraphTransformer::ReplaceConstantOperandWithNewShape(
+    const MLConstantOperand* old_operand,
+    const Vector<uint32_t>& new_shape) {
+  auto descriptor = webnn::OperandDescriptor::Create(
+      old_operand->Builder()->GetContext()->GetProperties(),
+      old_operand->DataType(), new_shape, /*label=*/"");
+  CHECK(descriptor.has_value());
+  CHECK_EQ(old_operand->NumberOfElements(), descriptor->NumberOfElements());
+
+  MLConstantOperand* new_operand = MakeGarbageCollected<MLConstantOperand>(
+      old_operand->Builder(), descriptor.value(), old_operand->handle());
+
+  new_operand->dependent_operators_ = old_operand->dependent_operators_;
+  ReplaceOperand(old_operand, new_operand);
+  return new_operand;
+}
+
 MLOperand* MLGraphTransformer::ReplaceOperandWithNewDataType(
     MLOperand* old_operand,
     webnn::OperandDataType new_data_type) {
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h
index f6b8a76..ad1e4870 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/ml_graph_transformer.h
@@ -10,6 +10,7 @@
 
 namespace blink {
 
+class MLConstantOperand;
 using OperandIndex = wtf_size_t;
 
 class MODULES_EXPORT MLGraphTransformer
@@ -50,6 +51,12 @@
       MLOperand* old_operand,
       const Vector<uint32_t>& new_shape);
 
+  // Replace constant operand with a new constant operand, the constant handle
+  // gets reused for the new constant.
+  static MLConstantOperand* ReplaceConstantOperandWithNewShape(
+      const MLConstantOperand* old_operand,
+      const Vector<uint32_t>& new_shape);
+
   static MLOperand* ReplaceOperandWithNewDataType(
       MLOperand* old_operand,
       webnn::OperandDataType new_data_type);
@@ -72,7 +79,8 @@
       const MLOperand* operand,
       webnn::OperandDataType data_type);
 
-  static void ReplaceOperand(MLOperand* old_operand, MLOperand* new_operand);
+  static void ReplaceOperand(const MLOperand* old_operand,
+                             MLOperand* new_operand);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/pipeline.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/pipeline.cc
index 8f28f90a..13f0d73 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/pipeline.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/pipeline.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/pipeline.h"
 
+#include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/constant_folding_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/layout_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/qdq_detection_transformer.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_transform/transpose_elimination_transformer.h"
@@ -25,6 +26,8 @@
 
   // Non-essential transformers. For better performance.
   transformers_.push_back(
+      MakeGarbageCollected<ConstantFoldingTransformer>(graph_builder));
+  transformers_.push_back(
       MakeGarbageCollected<QDQDetectionTransformer>(graph_builder));
   transformers_.push_back(
       MakeGarbageCollected<TransposeEliminationTransformer>(graph_builder));
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc b/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
index 12d6313a..d09a494 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
@@ -124,9 +124,9 @@
   return ToBlinkDataType(descriptor_.data_type());
 }
 
-MLConstantOperand const* MLOperand::AsConstantOperand() const {
+MLConstantOperand* MLOperand::AsConstantOperand() {
   CHECK_EQ(kind_, webnn::mojom::blink::Operand::Kind::kConstant);
-  return static_cast<MLConstantOperand const*>(this);
+  return static_cast<MLConstantOperand*>(this);
 }
 
 void MLOperand::AddDependentOperator(MLOperator* ml_operator) {
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operand.h b/third_party/blink/renderer/modules/ml/webnn/ml_operand.h
index 819657f3..8d49935c 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operand.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operand.h
@@ -81,7 +81,7 @@
   V8MLOperandDataType dataType() const;
   Vector<uint32_t> shape() const;
 
-  MLConstantOperand const* AsConstantOperand() const;
+  MLConstantOperand* AsConstantOperand();
 
   void AddDependentOperator(MLOperator* ml_operator);
 
@@ -92,7 +92,7 @@
 
   // Represents a valid MLOperandDescriptor.
   // https://www.w3.org/TR/webnn/#dictdef-mloperanddescriptor
-  const webnn::OperandDescriptor descriptor_;
+  webnn::OperandDescriptor descriptor_;
 
   // The name of input operand. According to
   // https://www.w3.org/TR/webnn/#dom-mlgraphbuilder-input, only input operand
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc b/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc
index f531d8a..b7c8a3c 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc
@@ -433,6 +433,10 @@
                                GetDeferredTaskHandler().RenderQuantumFrames()));
 }
 
+double AudioParamHandler::ClampedToCurrentTime(double time) {
+  return std::max(time, DestinationHandler().CurrentTime());
+}
+
 String AudioParamHandler::EventToString(const ParamEvent& event) const {
   // The default arguments for most automation methods is the value and the
   // time.
@@ -724,6 +728,8 @@
     return;
   }
 
+  start_time = ClampedToCurrentTime(start_time);
+
   base::AutoLock locker(events_lock_);
   InsertEvent(ParamEvent::CreateSetValueEvent(value, start_time),
               exception_state);
@@ -741,6 +747,8 @@
     return;
   }
 
+  end_time = ClampedToCurrentTime(end_time);
+
   base::AutoLock locker(events_lock_);
   InsertEvent(ParamEvent::CreateLinearRampEvent(value, end_time, initial_value,
                                                 call_time),
@@ -768,6 +776,8 @@
     return;
   }
 
+  end_time = ClampedToCurrentTime(end_time);
+
   base::AutoLock locker(events_lock_);
   InsertEvent(ParamEvent::CreateExponentialRampEvent(value, end_time,
                                                      initial_value, call_time),
@@ -786,6 +796,8 @@
     return;
   }
 
+  start_time = ClampedToCurrentTime(start_time);
+
   base::AutoLock locker(events_lock_);
 
   // If timeConstant = 0, we instantly jump to the target value, so
@@ -819,6 +831,8 @@
     return;
   }
 
+  start_time = ClampedToCurrentTime(start_time);
+
   base::AutoLock locker(events_lock_);
   bool result = InsertEvent(
       ParamEvent::CreateSetValueCurveEvent(curve, start_time, duration),
@@ -859,16 +873,14 @@
        event->GetType() == ParamEvent::Type::kExponentialRampToValue)) {
     // There are no events preceding these ramps.  Insert a new
     // setValueAtTime event to set the starting point for these
-    // events.  Use a time of 0 to make sure it precedes all other
-    // events.  This will get fixed when when handle new events.
-    events_.insert(0, AudioParamHandler::ParamEvent::CreateSetValueEvent(
-                          event->InitialValue(), 0));
-    new_events_.insert(events_[0].get());
+    // events.
+    events_.insert(
+        0, AudioParamHandler::ParamEvent::CreateSetValueEvent(
+               event->InitialValue(), DestinationHandler().CurrentTime()));
   }
 
   if (events_.empty()) {
     events_.insert(0, std::move(event));
-    new_events_.insert(events_[0].get());
     return true;
   }
 
@@ -974,7 +986,6 @@
   }
 
   events_.insert(insertion_idx, std::move(event));
-  new_events_.insert(events_[insertion_idx].get());
   return true;
 }
 
@@ -1070,6 +1081,8 @@
     return;
   }
 
+  cancel_time = ClampedToCurrentTime(cancel_time);
+
   base::AutoLock locker(events_lock_);
 
   // Remove all events starting at startTime.
@@ -1103,6 +1116,8 @@
     return;
   }
 
+  cancel_time = ClampedToCurrentTime(cancel_time);
+
   base::AutoLock locker(events_lock_);
 
   wtf_size_t i;
@@ -1294,17 +1309,6 @@
 
   int number_of_events = events_.size();
 
-  // MUST clamp event before `events_` is possibly mutated because
-  // `new_events_` has raw pointers to objects in `events_`.  Clamping
-  // will clear out all of these pointers before `events_` is
-  // potentially modified.
-  //
-  // TODO(rtoy): Consider making `events_` be scoped_refptr instead of
-  // unique_ptr.
-  if (new_events_.size() > 0) {
-    ClampNewEventsToCurrentTime(start_frame / sample_rate);
-  }
-
   if (number_of_events > 0) {
     double current_time = start_frame / sample_rate;
 
@@ -1458,9 +1462,6 @@
   // running with the m_events lock so we can safely modify the m_events
   // array.)
   if (last_skipped_event_index > 0) {
-    // `new_events_` should be empty here so we don't have to
-    // do any updates due to this mutation of `events_`.
-    DCHECK_EQ(new_events_.size(), 0u);
     RemoveOldEvents(last_skipped_event_index - 1);
   }
 
@@ -1544,25 +1545,6 @@
   return true;
 }
 
-void AudioParamHandler::ClampNewEventsToCurrentTime(double current_time) {
-  bool clamped_some_event_time = false;
-
-  for (auto* event : new_events_) {
-    if (event->Time() < current_time) {
-      event->SetTime(current_time);
-      clamped_some_event_time = true;
-    }
-  }
-
-  if (clamped_some_event_time) {
-    // If we clamped some event time to current time, we need to sort
-    // the event list in time order again, but it must be stable!
-    std::stable_sort(events_.begin(), events_.end(), ParamEvent::EventPrecedes);
-  }
-
-  new_events_.clear();
-}
-
 bool AudioParamHandler::HandleAllEventsInThePast(
     double current_time,
     double sample_rate,
@@ -1596,9 +1578,6 @@
       }
     }
 
-    // `events_` is being mutated.  `new_events_` better be empty because there
-    // are raw pointers there.
-    DCHECK_EQ(new_events_.size(), 0U);
     // The event has finished, so just copy the default value out.
     // Since all events are now also in the past, we can just remove all
     // timeline events too because `default_value` has the expected
@@ -2282,15 +2261,7 @@
 
 void AudioParamHandler::RemoveCancelledEvents(
     wtf_size_t first_event_to_remove) {
-  // For all the events that are being removed, also remove that event
-  // from `new_events_`.
-  if (new_events_.size() > 0) {
-    for (wtf_size_t k = first_event_to_remove; k < events_.size(); ++k) {
-      new_events_.erase(events_[k].get());
-    }
-  }
-
-  // Now we can remove the cancelled events from the list.
+  // Remove the cancelled events from the list.
   events_.EraseAt(first_event_to_remove,
                   events_.size() - first_event_to_remove);
 }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_handler.h b/third_party/blink/renderer/modules/webaudio/audio_param_handler.h
index aad2637..f935b0f 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_param_handler.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_handler.h
@@ -471,12 +471,6 @@
                       size_t current_frame,
                       double sample_rate) const;
 
-  // Clamp times to current time, if needed for any new events.  Note,
-  // this method can mutate `events_`, so do call this only in safe
-  // places.
-  void ClampNewEventsToCurrentTime(double current_time)
-      EXCLUSIVE_LOCKS_REQUIRED(events_lock_);
-
   // Handle the case where the last event in the timeline is in the
   // past.  Returns false if any event is not in the past. Otherwise,
   // return true and also fill in `values` with `default_value`.
@@ -570,7 +564,7 @@
                            uint32_t write_index);
 
   // When cancelling events, remove the items from `events_` starting
-  // at the given index.  Update `new_events_` too.
+  // at the given index.
   void RemoveCancelledEvents(wtf_size_t first_event_to_remove)
       EXCLUSIVE_LOCKS_REQUIRED(events_lock_);
 
@@ -585,6 +579,9 @@
   void CalculateFinalValues(base::span<float> values, bool sample_accurate);
   void CalculateTimelineValues(base::span<float> values);
 
+  // Returns time clamped to current time, if needed for any new events.
+  double ClampedToCurrentTime(double time);
+
   // The type of AudioParam, indicating what this AudioParam represents and
   // what node it belongs to.  Mostly for informational purposes and doesn't
   // affect implementation.
@@ -616,14 +613,6 @@
   // Vector of all automation events for the AudioParam.
   Vector<std::unique_ptr<ParamEvent>> events_ GUARDED_BY(events_lock_);
 
-  // Vector of raw pointers to the actual ParamEvent that was
-  // inserted.  As new events are added, `new_events_` is updated with
-  // the new event.  When the timline is processed, these events are
-  // clamped to current time by `ClampNewEventsToCurrentTime`. Access
-  // must be locked via `events_lock_`.  Must be maintained together
-  // with `events_`.
-  HashSet<ParamEvent*> new_events_ GUARDED_BY(events_lock_);
-
   mutable base::Lock events_lock_;
 
   // The destination node used to get necessary information like the sample
diff --git a/third_party/blink/renderer/platform/fonts/script_run_iterator.cc b/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
index 59d8d3fb..928ebbb 100644
--- a/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
+++ b/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
@@ -471,7 +471,9 @@
 
   UNSAFE_TODO(U16_NEXT(text_, ahead_pos_, length_, ahead_character_));
 
-  if (Character::IsGcMark(ahead_character_)) [[unlikely]] {
+  if (Character::IsGcMark(ahead_character_) &&
+      RuntimeEnabledFeatures::ScriptRunIteratorCombiningMarksEnabled())
+      [[unlikely]] {
     // A combining mark--whatever its Script property value--should inherit the
     // script property value of its base character.
     // https://www.unicode.org/reports/tr24/#Nonspacing_Marks
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 7e9321c..1d990dff 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -1311,8 +1311,14 @@
 
 #if BUILDFLAG(IS_WIN)
   if (base::FeatureList::IsEnabled(kUseCRPSIForLowLatencyOnWindows)) {
+    // On Windows, SCANOUT usage is additionally supported in the special case
+    // of the swapchain being used on the service side to implement concurrent
+    // read/write.
     is_overlay_supported =
-        is_overlay_supported || shared_image_caps.shared_image_swap_chain;
+        is_overlay_supported ||
+        (shared_image_usage_flags.Has(
+             gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE) &&
+         shared_image_caps.shared_image_swap_chain);
   }
 #endif
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/DEPS b/third_party/blink/renderer/platform/graphics/gpu/DEPS
index 53183e0..8a0bcbc6 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/DEPS
+++ b/third_party/blink/renderer/platform/graphics/gpu/DEPS
@@ -15,3 +15,12 @@
     "+ui/gl/buildflags.h",
     "+ui/gl/gpu_preference.h",
 ]
+
+specific_include_rules = {
+  "drawing_buffer.h": [
+    "+base/containers/flat_set.h",
+  ],
+  "xr_webgl_drawing_buffer.h": [
+    "+base/containers/flat_set.h",
+  ],
+}
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index 4b2911e1..c04d4a3 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -34,6 +34,7 @@
 #include <limits>
 #include <memory>
 
+#include "base/containers/flat_set.h"
 #include "base/containers/span.h"
 #include "base/functional/function_ref.h"
 #include "base/memory/raw_ptr.h"
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
index 8d091079..dd9323ed 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_XR_WEBGL_DRAWING_BUFFER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_XR_WEBGL_DRAWING_BUFFER_H_
 
+#include "base/containers/flat_set.h"
 #include "base/threading/platform_thread.h"
 #include "cc/layers/texture_layer_client.h"
 #include "gpu/command_buffer/client/client_shared_image.h"
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index b74c3a83c..452cb97 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1122,6 +1122,8 @@
     {
       name: "CrashReportingStorageAPI",
       status: "experimental",
+      base_feature_status: "enabled",
+      copied_from_base_feature_if: "overridden",
     },
     {
       // Allow WebAuthn relying parties to report information about existing
@@ -2893,9 +2895,6 @@
       base_feature: "LayoutNGShapeCache",
     },
     {
-      name: "LayoutReplacedReturnExplicitDefaultNaturalSize",
-    },
-    {
       name: "LayoutStretch",
       status: "stable",
     },
@@ -4224,6 +4223,10 @@
       status: "stable",
     },
     {
+      name: "ScriptRunIteratorCombiningMarks",
+      status: "stable",
+    },
+    {
       name: "ScriptTools",
       status: "test",
     },
@@ -4438,12 +4441,6 @@
       base_feature: "WebSerialAPI",
     },
     {
-      // Kill-switch for crbug.com/40791925.
-      // Added in M138, and it can be removed in M140.
-      name: "SerializeCdataAsTextInHTMLDocuments",
-      status: "stable",
-    },
-    {
       name: "SerializeViewTransitionStateInSPA",
     },
     {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f466234..82ca13be 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6666,6 +6666,11 @@
 crbug.com/40146374 virtual/select-parser-relaxation/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-selected-value-behavior.tentative.html [ Failure ]
 crbug.com/40146374 virtual/select-parser-relaxation/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-text-only.tentative.html [ Failure ]
 
+# To-be-fixed tests from the IndexedDB SQLite virtual suite.
+crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/clear-site-data/storage.https.html [ Failure ]
+crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/fs/FileSystemBaseHandle-IndexedDB.https.any.html [ Crash Failure ]
+crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/storage/partitioned-estimate-usage-details-indexeddb.tentative.https.sub.html [ Timeout ]
+
 # CustomizableSelectInPage
 crbug.com/357649033 virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/customizable-select-in-page/customizable-select-in-page-appearance.tentative.html [ Failure ]
 crbug.com/357649033 virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/customizable-select-in-page/customizable-select-in-page-keyboard-behavior.tentative.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 8b1593c6..22ba4b5 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1702,7 +1702,24 @@
     "bases": [
       "external/wpt/IndexedDB",
       "storage/indexeddb",
-      "wpt_internal/IndexedDB"
+      "wpt_internal/IndexedDB",
+      "crypto/subtle/rsa-indexeddb.html",
+      "external/wpt/clear-site-data/storage.https.html",
+      "external/wpt/fs/FileSystemBaseHandle-IndexedDB.https.any.html",
+      "external/wpt/html/anonymous-iframe/indexeddb.tentative.https.window.html",
+      "external/wpt/html/infrastructure/common-dom-interfaces/collections/domstringlist.html",
+      "external/wpt/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html",
+      "external/wpt/service-workers/service-worker/indexeddb.https.html",
+      "external/wpt/storage-access-api/storage-access-beyond-cookies.indexedDB.sub.https.window.html",
+      "external/wpt/storage/buckets/bucket-quota-indexeddb.tentative.https.any.html",
+      "external/wpt/storage/estimate-indexeddb.https.any.html",
+      "external/wpt/storage/estimate-usage-details-indexeddb.https.tentative.any.html",
+      "external/wpt/storage/partitioned-estimate-usage-details-indexeddb.tentative.https.sub.html",
+      "external/wpt/wasm/webapi/historical.any.html",
+      "external/wpt/webcodecs/video-frame-serialization.any.html",
+      "external/wpt/workers/data-url-shared.html",
+      "external/wpt/workers/data-url.html",
+      "fast/dom/domstringlist.html"
     ],
     "args": [
       "--enable-features=IdbSqliteBackingStore"
@@ -3084,7 +3101,8 @@
     "bases": [
       "external/wpt/custom-elements/registries/Document-createElement.html",
       "external/wpt/custom-elements/registries/Document-createElementNS.html",
-      "external/wpt/custom-elements/registries/Document-customElementRegistry.html"
+      "external/wpt/custom-elements/registries/Document-customElementRegistry.html",
+      "external/wpt/custom-elements/registries/ShadowRoot-init-customElementRegistry.html"
     ],
     "args": [
       "--enable-blink-features=ScopedCustomElementRegistry"
@@ -4293,7 +4311,9 @@
       "external/wpt/soft-navigation-heuristics/"
     ],
     "exclusive_tests": [
-      "external/wpt/soft-navigation-heuristics/smoke/tentative/late-url-change.html"
+      "external/wpt/soft-navigation-heuristics/smoke/tentative/late-url-change.html",
+      "external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text.html",
+      "external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text-once-per-interaction.html"
     ],
     "args": [
       "--enable-features=SoftNavigationDetectionPrePaintBasedAttribution"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/at-container-style-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/at-container-style-parsing.html
index 2890727a..1bb5e1a7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/at-container-style-parsing.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/container-queries/at-container-style-parsing.html
@@ -43,9 +43,12 @@
   test_cq_condition_known('style(10px < 10em < 10)');
   test_cq_condition_known('style(var(--p) < calc(100 + 200))');
   test_cq_condition_known('style(attr(data-foo type(<number>)) < var(--p) < var(--q))');
+  test_cq_condition_known('style(--foo < initial)');
 
   test_cq_condition_unknown('style(--foo: bar;)');
   test_cq_condition_unknown('style(style(--foo: bar))');
   test_cq_condition_unknown('style(10px < 10em > 10)');
   test_cq_condition_unknown('style( < 10em)');
+  test_cq_condition_unknown('style(10px < 10em !)');
+  test_cq_condition_unknown('style(10px ! < 10em)');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048-ref.html
new file mode 100644
index 0000000..0e34c5af
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048-ref.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+  }
+
+  .row-gap {
+    height: 0px;
+    width: 650px;
+    position: absolute;
+
+  }
+
+  .row-gap1 {
+    border-bottom: 10px solid yellow;
+    top: 100px;
+  }
+
+  .row-gap2 {
+    border-bottom: 8px solid yellow;
+    top: 211px;
+  }
+
+  .row-gap3 {
+    border-bottom: 2px solid yellow;
+    top: 324px;
+  }
+
+  .row-gap4 {
+    border-bottom: 2px solid yellow;
+    top: 434px;
+  }
+
+  .row-gap5 {
+    border-bottom: 5px solid yellow;
+    top: 542.5px;
+  }
+
+  .col-gap {
+    width: 0px;
+    height: 650px;
+    position: absolute;
+    top: 0px;
+  }
+
+  .col-gap1 {
+    border-left: 2px solid purple;
+    left: 104px;
+  }
+
+  .col-gap2 {
+    border-left: 5px solid green;
+    left: 212.5px;
+  }
+
+  .col-gap3 {
+    border-left: 2px solid white;
+    left: 324px;
+  }
+
+  .col-gap4 {
+    border-left: 10px solid yellow;
+    left: 430px;
+  }
+
+  .col-gap5 {
+    border-left: 10px solid blue;
+    left: 540px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
+
+<div class="col-gap col-gap1"> </div>
+<div class="col-gap col-gap2"> </div>
+<div class="col-gap col-gap3"> </div>
+<div class="col-gap col-gap4"> </div>
+<div class="col-gap col-gap5"> </div>
+
+<div class="row-gap row-gap1"> </div>
+<div class="row-gap row-gap2"> </div>
+<div class="row-gap row-gap3"> </div>
+<div class="row-gap row-gap4"> </div>
+<div class="row-gap row-gap5"> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048.html
new file mode 100644
index 0000000..0943502
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-048.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>
+  CSS Gap Decorations: Grid gaps are painted with multiple line-colors values for *-rule-colors. Tests
+  number of leading colors + trailing colors equal to number of gaps.
+</title>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="match" href="grid-gap-decorations-048-ref.html">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+
+    column-rule-color: purple green white yellow repeat(auto, red) blue;
+    column-rule-style: solid;
+    column-rule-width: 2px repeat(auto, 5px 2px) repeat(2, 10px);
+
+    row-rule-color: repeat(auto, yellow);
+    row-rule-style: solid;
+    row-rule-width: repeat(auto, 10px 8px) repeat(2, 2px) 5px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049-ref.html
new file mode 100644
index 0000000..fda312a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049-ref.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+  }
+
+  .row-gap {
+    height: 0px;
+    width: 650px;
+    position: absolute;
+
+  }
+
+  .row-gap1 {
+    border-bottom: 10px solid yellow;
+    top: 100px;
+  }
+
+  .row-gap2 {
+    border-bottom: 8px solid yellow;
+    top: 211px;
+  }
+
+  .row-gap3 {
+    border-bottom: 2px solid red;
+    top: 324px;
+  }
+
+  .row-gap4 {
+    border-bottom: 2px solid red;
+    top: 434px;
+  }
+
+  .row-gap5 {
+    border-bottom: 5px solid red;
+    top: 542.5px;
+  }
+
+  .col-gap {
+    width: 0px;
+    height: 650px;
+    position: absolute;
+    top: 0px;
+  }
+
+  .col-gap1 {
+    border-left: 2px solid red;
+    left: 104px;
+  }
+
+  .col-gap2 {
+    border-left: 5px solid green;
+    left: 212.5px;
+  }
+
+  .col-gap3 {
+    border-left: 2px solid red;
+    left: 324px;
+  }
+
+  .col-gap4 {
+    border-left: 10px solid green;
+    left: 430px;
+  }
+
+  .col-gap5 {
+    border-left: 10px solid blue;
+    left: 540px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
+
+<div class="col-gap col-gap1"> </div>
+<div class="col-gap col-gap2"> </div>
+<div class="col-gap col-gap3"> </div>
+<div class="col-gap col-gap4"> </div>
+<div class="col-gap col-gap5"> </div>
+
+<div class="row-gap row-gap1"> </div>
+<div class="row-gap row-gap2"> </div>
+<div class="row-gap row-gap3"> </div>
+<div class="row-gap row-gap4"> </div>
+<div class="row-gap row-gap5"> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049.html
new file mode 100644
index 0000000..7eeeb034
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-049.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>
+  CSS Gap Decorations: Grid gaps are painted with multiple line-colors values for *-rule-colors. Tests
+  that an auto repeater color is the last value.
+</title>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="match" href="grid-gap-decorations-049-ref.html">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+
+    column-rule-color: repeat(2, red green ) blue ;
+    column-rule-style: solid;
+    column-rule-width: 2px repeat(auto, 5px 2px) repeat(2, 10px);
+
+    row-rule-color: repeat(2, yellow) repeat(auto, red);
+    row-rule-style: solid;
+    row-rule-width: repeat(auto, 10px 8px) repeat(2, 2px) 5px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050-ref.html
new file mode 100644
index 0000000..72dbb2c3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050-ref.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+  }
+
+  .row-gap {
+    height: 0px;
+    width: 650px;
+    position: absolute;
+
+  }
+
+  .row-gap1 {
+    border-bottom: 10px solid red;
+    top: 100px;
+  }
+
+  .row-gap2 {
+    border-bottom: 8px solid red;
+    top: 211px;
+  }
+
+  .row-gap3 {
+    border-bottom: 2px solid red;
+    top: 324px;
+  }
+
+  .row-gap4 {
+    border-bottom: 2px solid yellow;
+    top: 434px;
+  }
+
+  .row-gap5 {
+    border-bottom: 5px solid yellow;
+    top: 542.5px;
+  }
+
+  .col-gap {
+    width: 0px;
+    height: 650px;
+    position: absolute;
+    top: 0px;
+  }
+
+  .col-gap1 {
+    border-left: 2px solid teal;
+    left: 104px;
+  }
+
+  .col-gap2 {
+    border-left: 5px solid red;
+    left: 212.5px;
+  }
+
+  .col-gap3 {
+    border-left: 2px solid green;
+    left: 324px;
+  }
+
+  .col-gap4 {
+    border-left: 10px solid red;
+    left: 430px;
+  }
+
+  .col-gap5 {
+    border-left: 10px solid blue;
+    left: 540px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
+
+<div class="col-gap col-gap1"> </div>
+<div class="col-gap col-gap2"> </div>
+<div class="col-gap col-gap3"> </div>
+<div class="col-gap col-gap4"> </div>
+<div class="col-gap col-gap5"> </div>
+
+<div class="row-gap row-gap1"> </div>
+<div class="row-gap row-gap2"> </div>
+<div class="row-gap row-gap3"> </div>
+<div class="row-gap row-gap4"> </div>
+<div class="row-gap row-gap5"> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050.html
new file mode 100644
index 0000000..93b160b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-050.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<title>
+  CSS Gap Decorations: Grid gaps are painted with multiple line-colors values for *-rule-colors.
+</title>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="match" href="grid-gap-decorations-050-ref.html">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+
+    column-rule-color: teal repeat(auto, red green) blue ;
+    column-rule-style: solid;
+    column-rule-width: 2px repeat(auto, 5px 2px) repeat(2, 10px);
+
+    row-rule-color: repeat(auto, red) repeat(2, yellow) ;
+    row-rule-style: solid;
+    row-rule-width: repeat(auto, 10px 8px) repeat(2, 2px) 5px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051-ref.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051-ref.html
new file mode 100644
index 0000000..cafaa51
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051-ref.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+  }
+
+  .row-gap {
+    height: 0px;
+    width: 650px;
+    position: absolute;
+
+  }
+
+  .row-gap1 {
+    border-bottom: 10px solid red;
+    top: 100px;
+  }
+
+  .row-gap2 {
+    border-bottom: 8px solid red;
+    top: 211px;
+  }
+
+  .row-gap3 {
+    border-bottom: 2px solid red;
+    top: 324px;
+  }
+
+  .row-gap4 {
+    border-bottom: 2px solid yellow;
+    top: 434px;
+  }
+
+  .row-gap5 {
+    border-bottom: 5px solid yellow;
+    top: 542.5px;
+  }
+
+  .col-gap {
+    width: 0px;
+    height: 650px;
+    position: absolute;
+    top: 0px;
+  }
+
+  .col-gap1 {
+    border-left: 2px solid teal;
+    left: 104px;
+  }
+
+  .col-gap2 {
+    border-left: 5px solid indigo;
+    left: 212.5px;
+  }
+
+  .col-gap3 {
+    border-left: 2px solid violet;
+    left: 324px;
+  }
+
+  .col-gap4 {
+    border-left: 10px solid blue;
+    left: 430px;
+  }
+
+  .col-gap5 {
+    border-left: 10px solid purple;
+    left: 540px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
+
+<div class="col-gap col-gap1"> </div>
+<div class="col-gap col-gap2"> </div>
+<div class="col-gap col-gap3"> </div>
+<div class="col-gap col-gap4"> </div>
+<div class="col-gap col-gap5"> </div>
+
+<div class="row-gap row-gap1"> </div>
+<div class="row-gap row-gap2"> </div>
+<div class="row-gap row-gap3"> </div>
+<div class="row-gap row-gap4"> </div>
+<div class="row-gap row-gap5"> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051.html b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051.html
new file mode 100644
index 0000000..9197ffd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-gaps/grid/grid-gap-decorations-051.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>
+  CSS Gap Decorations: Grid gaps are painted with multiple line-colors values for *-rule-colors.
+  Tests the case where number of trailing decorations is greater than the number of trailing gaps.
+</title>
+<link rel="help" href="https://www.w3.org/TR/css-gaps-1/#lists-repeat">
+<link rel="match" href="grid-gap-decorations-051-ref.html">
+<link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com">
+<style>
+  body {
+    margin: 0px;
+  }
+
+  .grid-container {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: repeat(6, 100px);
+    height: 650px;
+    width: 650px;
+
+    column-rule-color: teal indigo violet repeat(auto, red green) blue purple coral ;
+    column-rule-style: solid;
+    column-rule-width: 2px repeat(auto, 5px 2px) repeat(2, 10px);
+
+    row-rule-color: repeat(auto, red) repeat(2, yellow) ;
+    row-rule-style: solid;
+    row-rule-width: repeat(auto, 10px 8px) repeat(2, 2px) 5px;
+  }
+
+  .item {
+    background: gray;
+    opacity: 0.5;
+  }
+</style>
+<div class="grid-container">
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+  <div class="item"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end.html
index 8643b3c1..0ed0b07 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end.html
@@ -6,6 +6,7 @@
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-actions.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
+<script src="/dom/events/scrolling/scroll_support.js"></script>
 <script src="support/common.js"></script>
 <style>
 html {
@@ -28,84 +29,35 @@
   overflow: hidden;
   scroll-snap-align: start;
 }
-#i1 {
-  color: red;
-  font-weight: bold;
-}
 </style>
-
 <div id="content">
   <div id="target">
-    <h1>CSSScrollSnap</h1>
-    <h4>Tests that the window can snap at user scroll end.</h4>
-    <ol>
-      <li id="i1" style="color: red">
-        Scroll the page vertically and horizontally.
-        Keep scrolling until background has turned yellow.</li>
-      <li id="i2"> Press the button "Done"</li>
-    </ol>
-    <input type="button" id="btn" value="DONE" style="width: 100px; height: 50px;"/>
+    <!-- CSSScrollSnap
+    Tests that the window snaps at user scroll end.
+    Manual steps:
+      1. Scroll the page once vertically and once horizontally.
+      2. Verify in console (or otherwise) window scroll position is same as
+      target's offset position -->
   </div>
 </div>
-
 <script>
-var snap_test = async_test('Tests that window should snap at user scroll end.');
-var body = document.body;
-var button = document.getElementById("btn");
-var target = document.getElementById("target");
-var instruction1 = document.getElementById("i1");
-var instruction2 = document.getElementById("i2");
-var scrolled_x = false;
-var scrolled_y = false;
-var start_x = window.scrollX;
-var start_y = window.scrollY;
-var actions_promise;
-
-scrollTop = () => window.scrollY;
-
-window.onscroll = function() {
-  if (scrolled_x && scrolled_y) {
-    body.style.backgroundColor = "yellow";
-    instruction1.style.color = "black";
-    instruction1.style.fontWeight = "normal";
-    instruction2.style.color = "red";
-    instruction2.style.fontWeight = "bold";
-    return;
-  }
-
-  scrolled_x |= window.scrollX != start_x;
-  scrolled_y |= window.scrollY != start_y;
-}
-
-button.onclick = function() {
-  if (!scrolled_x || !scrolled_y)
-    return;
-
-  snap_test.step(() => {
-    assert_equals(window.scrollX, target.offsetLeft,
-          "window.scrollX should be at snapped position.");
-    assert_equals(window.scrollY, target.offsetTop,
-          "window.scrollY should be at snapped position.");
-  });
-
-  // To make the test result visible.
-  var content = document.getElementById("content");
-  body.removeChild(content);
-  actions_promise.then( () => {
-    snap_test.done();
-  });
-}
-
-// Inject scroll actions.
-const pos_x = 20;
-const pos_y = 20;
-const scroll_delta_x = 100;
-const scroll_delta_y = 100;
-actions_promise = new test_driver.Actions()
-    .scroll(pos_x, pos_y, scroll_delta_x, scroll_delta_y)
-    .send().then(() => {
-  return waitForAnimationEnd(scrollTop);
-}).then(() => {
-  return test_driver.click(button);
-});
+promise_test(async t => {
+  await waitForCompositorReady();
+  const target = document.getElementById("target");
+  // Inject scroll actions.
+  const pos_x = 20;
+  const pos_y = 20;
+  const scroll_delta_x = 100;
+  const scroll_delta_y = 100;
+  const wheelPromise = waitForWheelEvent(window);
+  await new test_driver.Actions()
+      .scroll(pos_x, pos_y, scroll_delta_x, scroll_delta_y)
+      .send()
+  await wheelPromise;
+  await waitForAnimationEnd(() => window.scrollY);
+  assert_approx_equals(window.scrollX, target.offsetLeft, 0.5,
+        "window.scrollX should be at snapped position.");
+  assert_approx_equals(window.scrollY, target.offsetTop, 0.5,
+        "window.scrollY should be at snapped position.");
+}, "Tests that window should snap at user scroll end.");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html b/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
index a299b26..1167172e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
@@ -528,6 +528,9 @@
 
   // style() queries with range syntax in the condition, literals on both sides of equation
   test_if_with_custom_properties('if(style(5 > 3): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(5 > 3 !invalid): true_value; else: false_value)', [], 'false_value');
+  test_if_with_custom_properties('if(style(5 !invalid > 3): true_value; else: false_value)', [], 'false_value');
+  test_if_with_custom_properties('if(style(5 > 3 !): true_value; else: false_value)', [], 'false_value');
   test_if_with_custom_properties('if(style(5.5 > 3): true_value; else: false_value)', [], 'true_value');
   test_if_with_custom_properties('if(style(5.5 > 3.3): true_value; else: false_value)', [], 'true_value');
   test_if_with_custom_properties('if(style(10em > 3px): true_value; else: false_value)', [], 'true_value');
@@ -539,6 +542,11 @@
   test_if_with_custom_properties('if(style(3% >= 3%): true_value; else: false_value)', [], 'true_value');
   test_if_with_custom_properties('if(style(3s > 3ms): true_value; else: false_value)', [], 'true_value');
   test_if_with_custom_properties('if(style(3dppx > 96dpi): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties(`if(style(--length > initial): true_value;
+          else: false_value)`,
+        [['--length', '5px']],
+        'false_value');
+  test_if_with_custom_properties('if(style(--x = initial): true_value; else: false_value)', [['--x', 'initial']], 'false_value');
 
   // style() queries with range syntax in the condition, simple custom properties in the condition
   test_if_with_custom_properties('if(style(--x <= 3): true_value; else: false_value)',
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/if-range-with-attr-crash.html b/third_party/blink/web_tests/external/wpt/css/css-values/if-range-with-attr-crash.html
new file mode 100644
index 0000000..0943f18
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/if-range-with-attr-crash.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>CSS Values and Units Test: invalid attr() syntax inside if style range</title>
+<link rel="help" href="https://crbug.com/407890255">
+<style>
+  div {
+    color: if(
+      style(attr(data-foo <number>) = 3): green;
+      else: red;
+    );
+  }
+</style>
+<div id="test" data-foo=3>
+  Pass if loading this page does not crash.
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
index 5c83faa..e68d28c 100644
--- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
@@ -4,7 +4,7 @@
 <link rel="author" href="mailto:masonf@chromium.org">
 <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
 <link rel="match"  href="backdrop-filter-plus-filter-ref.html">
-<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-210">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-298">
 
 <p>Expected: A green box with an overlapping purple box.<br>
 The overlapping portion of the boxes should be bright magenta.<br>
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text-once-per-interaction.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text-once-per-interaction.html
new file mode 100644
index 0000000..41a3638
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text-once-per-interaction.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script>
+
+<button id="navigateButton">Click here!</button>
+<h1>Heading!</h1>
+<div id="content" elementtiming="content-text">Initial Text</div>
+<div id="container"></div>
+
+<script>
+  promise_test(async t => {
+    const url = 'soft-nav-1';
+
+    // Wait for the initial text load and make its way through the text timing
+    // pipeline before changing its contents.
+    const elementId = "content-text";
+    let entries = await new Promise(resolve => {
+      new PerformanceObserver((list, observer) => {
+        resolve(list.getEntries());
+        observer.disconnect();
+      }).observe({type: 'element', buffered: true});
+    });
+    assert_equals(
+        entries.length, 1,
+        `Expected exactly one ElementTiming entry for "${elementId}"`);
+    assert_equals(
+        entries[0].identifier, elementId,
+        `Unexpected ElementTiming entry: expected "${elementId}"`);
+
+    const softNavPromise = SoftNavigationTestHelper.getPerformanceEntries(
+        "soft-navigation",
+        /* includeSoftNavigationObservations= */true,
+        /* minNumEntries= */ 1);
+    let icpPromise = SoftNavigationTestHelper.getPerformanceEntries(
+        "interaction-contentful-paint",
+        /* includeSoftNavigationObservations= */true,
+        /* minNumEntries= */ 1);
+    const {promise, resolve} = Promise.withResolvers();
+
+    navigateButton.addEventListener('click', async () => {
+      // This is sufficient to trigger an initial soft nav and ICP entry.
+      history.pushState({}, '', url);
+      content.innerText = 'This is some new text!';
+
+      // Wait for the first round of soft nav/ICP checking.
+      await promise;
+
+      // Add more text, which should produce another ICP entry.
+      container.innerHTML = `<div id="container-text">${content.innerText} (and more text)</div>`;
+      // Now, update the same text as before with even more text than above.
+      // We shouldn't get an ICP entry for this, even though it's larger,
+      // because we already have an entry for this node.
+      content.innerText = content.innerText + ' (and even more text)';
+    }, {once: true});
+
+    if (test_driver) {
+      test_driver.click(navigateButton);
+    }
+
+    const helper = new SoftNavigationTestHelper(t);
+    // Check if we detected a soft nav.
+    const softNavs = await helper.withTimeoutMessage(
+        softNavPromise, "Soft navigation not detected.", /*timeout=*/ 3000);
+    assert_equals(softNavs.length, 1, 'Expected exactly one soft navigation.');
+    assert_true(
+      softNavs[0].name.endsWith(url),
+      `Unexpected Soft Navigation URL. Expected url to end with ${url} but got ${softNavs[0].name}`);
+
+    // Check that we only get one ICP entry, and that it's for the node whose
+    // text we overwrote.
+    let icps = await helper.withTimeoutMessage(
+        icpPromise, 'ICP not detected.', /*timeout=*/ 3000);
+    assert_equals(icps.length, 1, 'Expected exactly one ICP entry.');
+    assert_equals(icps[0].id, 'content', 'Expected ICP candidate to be "content"');
+
+
+    // Set things up for the next ICP entry.
+    icpPromise = SoftNavigationTestHelper.getPerformanceEntries(
+        "interaction-contentful-paint",
+        /* includeSoftNavigationObservations= */true,
+        /* minNumEntries= */ 1);
+    resolve();
+
+    icps = await helper.withTimeoutMessage(
+        icpPromise, 'New ICP not detected.', /*timeout=*/ 3000);
+    assert_equals(icps.length, 1, 'Expected exactly one ICP entry.');
+    assert_equals(icps[0].id, 'container-text', 'Expected ICP candidate to be "container-text"');
+  }, 'Soft Navigation Detection supports replacing existing text once per interaction');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text.html
new file mode 100644
index 0000000..653ae684
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/detection/tentative/overwriting-text.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script>
+
+<button id="navigateButton">Click here!</button>
+<h1>Heading!</h1>
+<div id="content" elementtiming="content-text">Initial Text</div>
+<div id="container"></div>
+
+<script>
+  async function waitForExactlyOneElementTimingEntry(id, buffered) {
+    let entries = await new Promise(resolve => {
+      new PerformanceObserver((list, observer) => {
+        resolve(list.getEntries());
+        observer.disconnect();
+      }).observe({type: 'element', buffered});
+    });
+    assert_equals(
+        entries.length, 1,
+        `Expected exactly one ElementTiming entry for "${id}"`);
+    assert_equals(
+        entries[0].identifier, id,
+        `Unexpected ElementTiming entry: expected "${id}"`);
+  }
+
+  async function runTest(t, url, text) {
+    navigateButton.addEventListener('click', async () => {
+      // We expect to get a timing entry for this, but not a soft nav ICP entry.
+      // This lets us check that we don't get more than the initial timing entry
+      // for `content`.
+      const div = document.createElement("div");
+      div.innerHTML = `<div id="additional" elementtiming="${url}">hi</div>`;
+      container.appendChild(div);
+
+      content.innerText = text;
+
+      history.pushState({}, '', url);
+    }, {once: true});
+
+    // Set up the PerformanceObservers before clicking to avoid races,
+    // and use unbuffered here so we don't get duplicate entries.
+    const elementTimingPromise =
+        waitForExactlyOneElementTimingEntry(url, /*buffered=*/false);
+    const softNavPromise = SoftNavigationTestHelper.getPerformanceEntries(
+        "soft-navigation",
+        /* includeSoftNavigationObservations= */true,
+        /* minNumEntries= */ 1);
+    const icpPromise = SoftNavigationTestHelper.getPerformanceEntries(
+        "interaction-contentful-paint",
+        /* includeSoftNavigationObservations= */true,
+        /* minNumEntries= */ 1);
+
+    if (test_driver) {
+      test_driver.click(navigateButton);
+    }
+
+    const helper = new SoftNavigationTestHelper(t);
+
+    // Check if we detected a soft nav.
+    const softNavs = await helper.withTimeoutMessage(
+        softNavPromise, "Soft navigation not detected.", /*timeout=*/ 3000);
+    assert_equals(softNavs.length, 1, 'Expected exactly one soft navigation.');
+    assert_true(
+      softNavs[0].name.endsWith(url),
+      `Unexpected Soft Navigation URL. Expected url to end with ${url} but got ${softNavs[0].name}`);
+
+    // Check that we only get one ICP entry, and that it's for the node whose
+    // text we overwrote.
+    const icps = await helper.withTimeoutMessage(
+        icpPromise, 'ICP not detected.', /*timeout=*/ 3000);
+    assert_equals(icps.length, 1, 'Expected exactly one ICP entry.');
+    assert_equals(icps[0].id, 'content', 'Expected ICP candidate to be "content"');
+
+    // Finally, check to make sure we don't get an additional timing entry.
+    return elementTimingPromise;
+  }
+
+  // Wait for the initial text load and make its way through the text timing
+  // pipeline before changing its contents.
+  promise_setup(() => waitForExactlyOneElementTimingEntry('content-text', /*buffered=*/true));
+
+  promise_test(t => {
+    const url = 'soft-nav-1';
+    const text = 'The initial text has been replaced!';
+    return runTest(t, url, text);
+  }, 'Soft Navigation Detection supports replacing existing text');
+
+  promise_test(t => {
+    const url = 'soft-nav-2';
+    const text = 'The initial text has been replaced again!';
+    return runTest(t, url, text);
+  }, 'Soft Navigation Detection supports replacing existing text in multiple interactions');
+</script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index f1ff40a..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index a039f25..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png
deleted file mode 100644
index d36b011..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png
deleted file mode 100644
index 5e3a620..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-clip-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-clip-expected.png
deleted file mode 100644
index ff6fb3a..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-expected.png
deleted file mode 100644
index ff6fb3a..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
deleted file mode 100644
index 47e4a36..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/transforms/3d/general/transform-origin-z-change-expected.png
deleted file mode 100644
index c681736..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/transforms/3d/general/transform-origin-z-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png
index a4e8341a..548f1e1 100644
--- a/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png
index 51a82e7..dc3f404 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
deleted file mode 100644
index 9f3893a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac12/images/png-crbug423310049-expected.png
deleted file mode 100644
index 2f6f5ae..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12/images/png-crbug423310049-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac12/virtual/gpu-rasterization/images/png-crbug423310049-expected.png
deleted file mode 100644
index c183cfe..0000000
--- a/third_party/blink/web_tests/platform/mac-mac12/virtual/gpu-rasterization/images/png-crbug423310049-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/masks/mask-with-added-filters-expected.png
deleted file mode 100644
index f3ca7fc..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/masks/mask-with-added-filters-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-clip-expected.png
deleted file mode 100644
index b8a22b8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-expected.png
deleted file mode 100644
index b8a22b8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
deleted file mode 100644
index bd26650f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/video/video-controls-squashing-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/video/video-controls-squashing-expected.png
deleted file mode 100644
index 58ccdc0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/compositing/video/video-controls-squashing-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/borders/border-radius-with-composited-child-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/borders/border-radius-with-composited-child-expected.png
deleted file mode 100644
index 12572f54..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/borders/border-radius-with-composited-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
deleted file mode 100644
index 492e008..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/transforms/3d/general/transform-origin-z-change-expected.png
deleted file mode 100644
index e5ade18..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/transforms/3d/general/transform-origin-z-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
deleted file mode 100644
index 9f3893a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 16e804e..fd187f4 100644
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac13/images/png-crbug423310049-expected.png
deleted file mode 100644
index 2f6f5ae..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13/images/png-crbug423310049-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac13/virtual/gpu-rasterization/images/png-crbug423310049-expected.png
deleted file mode 100644
index c183cfe..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13/virtual/gpu-rasterization/images/png-crbug423310049-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/masks/mask-with-added-filters-expected.png
deleted file mode 100644
index 52ff234..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/masks/mask-with-added-filters-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-clip-expected.png
deleted file mode 100644
index e8089c26..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-expected.png
deleted file mode 100644
index e8089c26..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
deleted file mode 100644
index 1ae8591..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/video/video-controls-squashing-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/video/video-controls-squashing-expected.png
deleted file mode 100644
index e687e4e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/compositing/video/video-controls-squashing-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/borders/border-radius-with-composited-child-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/borders/border-radius-with-composited-child-expected.png
deleted file mode 100644
index 279f280..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/borders/border-radius-with-composited-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png
deleted file mode 100644
index 8e5fb6e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
deleted file mode 100644
index d459fbc..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/transforms/3d/general/transform-origin-z-change-expected.png
deleted file mode 100644
index 7ef557f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/transforms/3d/general/transform-origin-z-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
deleted file mode 100644
index 9f3893a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
new file mode 100644
index 0000000..fc1a2cd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
new file mode 100644
index 0000000..6e8d1bc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-clip-path-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-clip-path-expected.png
new file mode 100644
index 0000000..fe463352e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-clip-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-dynamic-clip-path-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-dynamic-clip-path-expected.png
new file mode 100644
index 0000000..fe463352e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/images/direct-image-dynamic-clip-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/masks/mask-with-added-filters-expected.png
index f3ca7fc..a7d29fc 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/masks/mask-with-added-filters-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/masks/mask-with-added-filters-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/opacity-with-mask-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/opacity-with-mask-expected.png
new file mode 100644
index 0000000..e711a0a8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/opacity-with-mask-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
new file mode 100644
index 0000000..2f52b8c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/opacity-with-mask-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png
similarity index 62%
rename from third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/opacity-with-mask-expected.png
rename to third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png
index 8a735d18..a655ee6 100644
--- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/compositing/opacity-with-mask-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png
new file mode 100644
index 0000000..3b4956b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/composited-layer-under-border-radius-under-composited-layer-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-clip-expected.png
index b8a22b8..5511701d 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-clip-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-clip-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-expected.png
index b8a22b8..5511701d 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
index bd26650f..c95a473 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/video/video-controls-squashing-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/video/video-controls-squashing-expected.png
index 58ccdc0..594a6f3 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/video/video-controls-squashing-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/compositing/video/video-controls-squashing-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-blur-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-blur-hw-expected.png
index 5e94e54..acd841d3 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-blur-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-drop-shadow-hw-expected.png
index ae315efc..7cd3ac2 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-drop-shadow-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-hw-expected.png
index a891652..dc9d6ee 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-ordering-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-ordering-hw-expected.png
index e577ec7b..ad3d281c 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-ordering-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-ordering-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-zoom-hw-expected.png
index 0ac9d94..e9e6f97 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-zoom-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/effect-reference-zoom-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/filter-change-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/filter-change-repaint-expected.png
index 48666def..c46a625 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/filter-change-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/css3/filters/filter-change-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/borders/border-radius-with-composited-child-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/borders/border-radius-with-composited-child-expected.png
index 12572f54..5e394680 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/borders/border-radius-with-composited-child-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/borders/border-radius-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png
new file mode 100644
index 0000000..9245d7bc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-overlay-menu-expected.png
new file mode 100644
index 0000000..79fbfaa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png
new file mode 100644
index 0000000..06eb1aa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png
new file mode 100644
index 0000000..5c3669f9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png
new file mode 100644
index 0000000..27c64e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png
new file mode 100644
index 0000000..229a228
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png
new file mode 100644
index 0000000..5c3669f9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png
new file mode 100644
index 0000000..dd12fb1e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png
new file mode 100644
index 0000000..68a9efc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png
new file mode 100644
index 0000000..ff73cec
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png
new file mode 100644
index 0000000..fc0941a4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png
new file mode 100644
index 0000000..610dc33
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png
new file mode 100644
index 0000000..574806b2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png
new file mode 100644
index 0000000..c640b106
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png
new file mode 100644
index 0000000..4b73df6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png
new file mode 100644
index 0000000..7dcad9fd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png
new file mode 100644
index 0000000..517f78f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png
new file mode 100644
index 0000000..32064d10
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png
new file mode 100644
index 0000000..cb7fd8d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png
new file mode 100644
index 0000000..cb7fd8d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png
new file mode 100644
index 0000000..959bc00
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png
new file mode 100644
index 0000000..818b655
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png
new file mode 100644
index 0000000..d1af504
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png
new file mode 100644
index 0000000..9d499d6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png
new file mode 100644
index 0000000..845452f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png
new file mode 100644
index 0000000..157a9b2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png
new file mode 100644
index 0000000..c6cc382
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png
new file mode 100644
index 0000000..53cdfc5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png
new file mode 100644
index 0000000..c6faee2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png
new file mode 100644
index 0000000..6f516e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/forms/color/color-picker-appearance-zoom200-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
index 492e008..9bde591 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/images/png-crbug423310049-expected.png
deleted file mode 100644
index 866cf6a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/images/png-crbug423310049-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/transforms/3d/general/transform-origin-z-change-expected.png
index e5ade18..07c2365ec 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/transforms/3d/general/transform-origin-z-change-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/transforms/3d/general/transform-origin-z-change-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png
new file mode 100644
index 0000000..0cd51a4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png
index 74e26a1..c191f2be 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-playback-speed-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
new file mode 100644
index 0000000..c588de1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
new file mode 100644
index 0000000..277deb854
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index 1489257..6f32a30 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-border-image-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
index 97c0c83c..7faa9404 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
index 9f3893a..e524389 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-composite-transformclip-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 16e804e..fd187f4 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 3a97942..d4f53e5c 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png
index be70d63..d00898d 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
index e2c445b..0a72f26 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-hw-expected.png
index 7ce7aae..de38d72 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-ordering-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-ordering-hw-expected.png
index f168d905..094c4a25 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-ordering-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-ordering-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-subregion-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-subregion-hw-expected.png
index f5d6308..d58ec6f 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-subregion-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-subregion-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-zoom-hw-expected.png
index c5106b4..dd6b6cb 100644
--- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-zoom-hw-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/scalefactor200/css3/filters/effect-reference-zoom-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png
index 2f6f5ae..bbd341a 100644
--- a/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png
index 4ad3f745..8b31bd3 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png
new file mode 100644
index 0000000..88d42ac
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png
new file mode 100644
index 0000000..81724b9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-conditional/container-queries/at-container-style-parsing-expected.txt b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-conditional/container-queries/at-container-style-parsing-expected.txt
index bc71c68a..b30d1c0 100644
--- a/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-conditional/container-queries/at-container-style-parsing-expected.txt
+++ b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-conditional/container-queries/at-container-style-parsing-expected.txt
@@ -47,5 +47,7 @@
   assert_equals: expected 2 but got 1
 [FAIL] Query condition should be valid: style(attr(data-foo type(<number>)) < var(--p) < var(--q))
   assert_equals: expected 2 but got 1
+[FAIL] Query condition should be valid: style(--foo < initial)
+  assert_equals: expected "true" but got ""
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt
index 1251e0a..3561063d5 100644
--- a/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt
+++ b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt
@@ -2,69 +2,69 @@
 Found 33 FAIL, 0 TIMEOUT, 0 NOTRUN.
 [FAIL] CSS Values and Units Test: CSS inline if() function 112
   assert_equals: "if(style(5 > 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 113
-  assert_equals: "if(style(5.5 > 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 114
-  assert_equals: "if(style(5.5 > 3.3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 115
-  assert_equals: "if(style(10em > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 116
-  assert_equals: "if(style(1em > 1px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(5.5 > 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 117
-  assert_equals: "if(style(7px > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(5.5 > 3.3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 118
+  assert_equals: "if(style(10em > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 119
-  assert_equals: "if(style(3turn > 3deg): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 121
-  assert_equals: "if(style(3% >= 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(1em > 1px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 120
+  assert_equals: "if(style(7px > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 122
-  assert_equals: "if(style(3s > 3ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 123
-  assert_equals: "if(style(3dppx > 96dpi): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(3turn > 3deg): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 124
-  assert_equals: "if(style(--x <= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(3% >= 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 125
-  assert_equals: "if(style(--x >= --y): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(3s > 3ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 126
-  assert_equals: "if(style(--length > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 127
-  assert_equals: "if(style(--x > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 128
-  assert_equals: "if(style(--number >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(3dppx > 96dpi): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 129
-  assert_equals: "if(style(--x >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x <= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 130
-  assert_equals: "if(style(--percentage > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x >= --y): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 131
-  assert_equals: "if(style(--x > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--length > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 132
-  assert_equals: "if(style(--angle < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 133
-  assert_equals: "if(style(--x < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--number >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 134
-  assert_equals: "if(style(--time <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 135
-  assert_equals: "if(style(var(--time) <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
+  assert_equals: "if(style(--percentage > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 136
-  assert_equals: "if(style(--x <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 137
-  assert_equals: "if(style(3dppx > --resolution): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--angle < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 138
-  assert_equals: "if(style(3dppx > --x): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+  assert_equals: "if(style(--x < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 139
+  assert_equals: "if(style(--time <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 140
+  assert_equals: "if(style(var(--time) <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
 [FAIL] CSS Values and Units Test: CSS inline if() function 141
-  assert_equals: "if(style(calc(--x + 1) >= --y): true_value; else: false_value)" should be substituted to "false_value". expected "false_value" but got ""
+  assert_equals: "if(style(--x <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 142
+  assert_equals: "if(style(3dppx > --resolution): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 [FAIL] CSS Values and Units Test: CSS inline if() function 143
+  assert_equals: "if(style(3dppx > --x): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 146
+  assert_equals: "if(style(calc(--x + 1) >= --y): true_value; else: false_value)" should be substituted to "false_value". expected "false_value" but got ""
+[FAIL] CSS Values and Units Test: CSS inline if() function 148
   assert_equals: "if(style(--x >= calc(3px + 3px)): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 144
+[FAIL] CSS Values and Units Test: CSS inline if() function 149
   assert_equals: "if(style(calc(var(--x) + 1) >= var(--y)): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
-[FAIL] CSS Values and Units Test: CSS inline if() function 145
+[FAIL] CSS Values and Units Test: CSS inline if() function 150
   assert_equals: "if(style(var(--x) >= --x): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
-[FAIL] CSS Values and Units Test: CSS inline if() function 152
+[FAIL] CSS Values and Units Test: CSS inline if() function 157
   assert_equals: "if(style(--length >= 30px): true_value;\n                                    else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 153
+[FAIL] CSS Values and Units Test: CSS inline if() function 158
   assert_equals: "if(style(10px <= 10px < 11px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 154
+[FAIL] CSS Values and Units Test: CSS inline if() function 159
   assert_equals: "if(style(3 < --x <= 5): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
-[FAIL] CSS Values and Units Test: CSS inline if() function 156
+[FAIL] CSS Values and Units Test: CSS inline if() function 161
   assert_equals: "if(style(--x >= --y > --z): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/Document-customElementRegistry-expected.txt b/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/Document-customElementRegistry-expected.txt
index e8e6ab1..9a67946 100644
--- a/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/Document-customElementRegistry-expected.txt
+++ b/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/Document-customElementRegistry-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-[FAIL] customElementRegistry on a document of a disconnected iframe should return contentWindow.customElements
-  assert_equals: expected object "[object CustomElementRegistry]" but got null
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
 Harness: the test ran to completion.
\ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/ShadowRoot-init-customElementRegistry-expected.txt b/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/ShadowRoot-init-customElementRegistry-expected.txt
new file mode 100644
index 0000000..9a67946
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/scoped-custom-element-registry/external/wpt/custom-elements/registries/ShadowRoot-init-customElementRegistry-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
\ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/smoke/tentative/dom-expected.txt b/third_party/blink/web_tests/virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/smoke/tentative/dom-expected.txt
new file mode 100644
index 0000000..d2490db
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/smoke/tentative/dom-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness: the test ran to completion.
+
diff --git a/third_party/catapult b/third_party/catapult
index 4e4076a..0fd1415f 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 4e4076a0d7a836b779a094989e911a65b2a3c1ee
+Subproject commit 0fd1415f0cf3219ba097d37336141897fab7c5e9
diff --git a/third_party/dawn b/third_party/dawn
index ae94721..24eec2f 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit ae947216dca9cfc32bf61421849762c568682b8c
+Subproject commit 24eec2f88310a949c1de8e25f10ff410c38e537b
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index c71680a..6f50004 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-13-3-304-g6c18a397c
-Revision: 6c18a397cba160e659ae96c01a33871ad2b1704b
+Version: VER-2-13-3-305-g08805be53
+Revision: 08805be530d6820d2bf8a1b7685826de40f06812
 CPEPrefix: cpe:/a:freetype:freetype:2.13.3
 License: FTL
 License File: src/docs/FTL.TXT
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 6c18a39..08805be5 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 6c18a397cba160e659ae96c01a33871ad2b1704b
+Subproject commit 08805be530d6820d2bf8a1b7685826de40f06812
diff --git a/third_party/glslang/src b/third_party/glslang/src
index f43df42f..38f6708 160000
--- a/third_party/glslang/src
+++ b/third_party/glslang/src
@@ -1 +1 @@
-Subproject commit f43df42fe69bb38d43625b53e0706bbee43d74b4
+Subproject commit 38f6708b6b6f213010c51ffa8f577a7751e12ce7
diff --git a/third_party/jni_zero/jni_zero_internal.h b/third_party/jni_zero/jni_zero_internal.h
index a50a064..3da6a8a 100644
--- a/third_party/jni_zero/jni_zero_internal.h
+++ b/third_party/jni_zero/jni_zero_internal.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifdef UNSAFE_BUFFERS_BUILD
+// TODO(crbug.com/393091624): Remove this and convert code to safer constructs.
+#pragma allow_unsafe_buffers
+#endif
+
 #ifndef JNI_ZERO_JNI_ZERO_INTERNAL_H
 #define JNI_ZERO_JNI_ZERO_INTERNAL_H
 
diff --git a/third_party/jni_zero/logging.cc b/third_party/jni_zero/logging.cc
index 362909ab..6852296 100644
--- a/third_party/jni_zero/logging.cc
+++ b/third_party/jni_zero/logging.cc
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifdef UNSAFE_BUFFERS_BUILD
+// TODO(crbug.com/393091624): Remove this and convert code to safer constructs.
+#pragma allow_unsafe_buffers
+#endif
+
 #include "third_party/jni_zero/logging.h"
 
 #include <stdarg.h>
diff --git a/third_party/jni_zero/logging.h b/third_party/jni_zero/logging.h
index a04f592..d3f709ea 100644
--- a/third_party/jni_zero/logging.h
+++ b/third_party/jni_zero/logging.h
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifdef UNSAFE_BUFFERS_BUILD
+// TODO(crbug.com/393091624): Remove this and convert code to safer constructs.
+#pragma allow_unsafe_buffers
+#endif
+
 // IWYU pragma: private, include "third_party/jni_zero/jni_zero.h"
 
 #ifndef JNI_ZERO_LOGGING_H_
diff --git a/third_party/liburlpattern/pattern.cc b/third_party/liburlpattern/pattern.cc
index 99775f34..86b01caa 100644
--- a/third_party/liburlpattern/pattern.cc
+++ b/third_party/liburlpattern/pattern.cc
@@ -3,6 +3,11 @@
 // Use of this source code is governed by an MIT-style license that can be
 // found in the LICENSE file or at https://opensource.org/licenses/MIT.
 
+#ifdef UNSAFE_BUFFERS_BUILD
+// TODO(crbug.com/393091624): Remove this and convert code to safer constructs.
+#pragma allow_unsafe_buffers
+#endif
+
 #include "third_party/liburlpattern/pattern.h"
 
 #include <algorithm>
diff --git a/third_party/liburlpattern/tokenize.cc b/third_party/liburlpattern/tokenize.cc
index 49723e5..671e9a5 100644
--- a/third_party/liburlpattern/tokenize.cc
+++ b/third_party/liburlpattern/tokenize.cc
@@ -3,6 +3,11 @@
 // Use of this source code is governed by an MIT-style license that can be
 // found in the LICENSE file or at https://opensource.org/licenses/MIT.
 
+#ifdef UNSAFE_BUFFERS_BUILD
+// TODO(crbug.com/393091624): Remove this and convert code to safer constructs.
+#pragma allow_unsafe_buffers
+#endif
+
 #include "third_party/liburlpattern/tokenize.h"
 
 #include <string_view>
diff --git a/third_party/libyuv b/third_party/libyuv
index 3ff31b2a..cdd3bae 160000
--- a/third_party/libyuv
+++ b/third_party/libyuv
@@ -1 +1 @@
-Subproject commit 3ff31b2a5fd88d57fed619678da1708097c81504
+Subproject commit cdd3bae84818e78466fec1ce954eead8f403d10c
diff --git a/third_party/perfetto b/third_party/perfetto
index 4c0ba92..d248102 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 4c0ba925d3304ab862e4e866d9b1ad6b451cc82f
+Subproject commit d248102abcfb167da566d0ca45d2fa32652aa31c
diff --git a/third_party/polymer/v3_0/BUILD.gn b/third_party/polymer/v3_0/BUILD.gn
index 712c223e..52acbf8 100644
--- a/third_party/polymer/v3_0/BUILD.gn
+++ b/third_party/polymer/v3_0/BUILD.gn
@@ -128,7 +128,6 @@
     "//chrome/browser/resources/inline_login:build_ts",
     "//chrome/browser/resources/lens/overlay:build_ts",
     "//chrome/browser/resources/lens/shared:build_ts",
-    "//chrome/browser/resources/new_tab_page:build_ts",
     "//chrome/browser/resources/password_manager:build_ts",
     "//chrome/browser/resources/pdf:build_ts",
     "//chrome/browser/resources/privacy_sandbox:build_ts",
@@ -145,7 +144,6 @@
     "//chrome/test/data/webui/cr_elements:build_ts",
     "//chrome/test/data/webui/history:build_ts",
     "//chrome/test/data/webui/inline_login:build_ts",
-    "//chrome/test/data/webui/new_tab_page:build_ts",
     "//chrome/test/data/webui/password_manager:build_ts",
     "//chrome/test/data/webui/print_preview:build_ts",
     "//chrome/test/data/webui/privacy_sandbox:build_ts",
diff --git a/third_party/re2/src b/third_party/re2/src
index 66a656e..8451125 160000
--- a/third_party/re2/src
+++ b/third_party/re2/src
@@ -1 +1 @@
-Subproject commit 66a656e6d9f8b78806c76201eb03038e85103e28
+Subproject commit 8451125897dd7816a5c118925e8e42309d598ecc
diff --git a/third_party/spirv-headers/src b/third_party/spirv-headers/src
index de1807b..97e96f9 160000
--- a/third_party/spirv-headers/src
+++ b/third_party/spirv-headers/src
@@ -1 +1 @@
-Subproject commit de1807b7cfa8e722979d5ab7b7445b258dbc1836
+Subproject commit 97e96f9e9defeb4bba3cfbd034dec516671dd7a3
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src
index ed173ab1..3aeaaa0 160000
--- a/third_party/spirv-tools/src
+++ b/third_party/spirv-tools/src
@@ -1 +1 @@
-Subproject commit ed173ab1848b82e19690e10ce8f2818c0ac78f8d
+Subproject commit 3aeaaa088d37b86cff036eee1a9bf452abad7d9d
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index 4c0ad3b2..5755777 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit 4c0ad3b279656534b70f5e1983bbf1fc50db5456
+Subproject commit 5755777e263c93928218fef6d1a0c3f6750efbf3
diff --git a/third_party/vulkan-headers/src b/third_party/vulkan-headers/src
index 89268a6..37057b4 160000
--- a/third_party/vulkan-headers/src
+++ b/third_party/vulkan-headers/src
@@ -1 +1 @@
-Subproject commit 89268a6d17fc87003b209a1422c17ab288be99a0
+Subproject commit 37057b4756df4009ad85803bd2e06ec8a3bb1bca
diff --git a/third_party/vulkan-loader/src b/third_party/vulkan-loader/src
index a1684e4..f2389e2 160000
--- a/third_party/vulkan-loader/src
+++ b/third_party/vulkan-loader/src
@@ -1 +1 @@
-Subproject commit a1684e4bd23ab130c5e7c37ab72b07dd541897a9
+Subproject commit f2389e27734347c1d9f40e03be53f69f969976b1
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 72c2c64..f113d73 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 72c2c64b82c3fbd587f478c810363479cd011b6d
+Subproject commit f113d73531fb6b82f6cb3aebc0e7c0915b3f611e
diff --git a/third_party/webrtc b/third_party/webrtc
index 22735d7..cdc641f 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 22735d7b9726d04e6fb4ae7af92c0e5f0bc03380
+Subproject commit cdc641f20d7a1bffdbcdd59fa88706c5404f2c64
diff --git a/tools/autotest.py b/tools/autotest.py
index 067f5a15..056fa7e 100755
--- a/tools/autotest.py
+++ b/tools/autotest.py
@@ -171,8 +171,8 @@
 
 TEST_FILE_NAME_REGEX = re.compile(
     r'(.*Test\.java)' +
-    r'|(.*_[a-z]*test(?:_win|_mac|_linux|_chromeos|_android)?\.cc)' + r'|(' +
-    _PREF_MAPPING_FILE_PATTERN + r')')
+    r'|(.*_[a-z]*test(?:_win|_mac|_linux|_chromeos|_android)?\.(cc|mm))' +
+    r'|(' + _PREF_MAPPING_FILE_PATTERN + r')')
 
 # Some tests don't directly include gtest.h and instead include it via gmock.h
 # or a test_utils.h file, so make sure these cases are captured. Also include
@@ -217,7 +217,7 @@
 def IsTestFile(file_path):
   if not TEST_FILE_NAME_REGEX.match(file_path):
     return TestValidity.NOT_A_TEST
-  if file_path.endswith('.cc'):
+  if file_path.endswith('.cc') or file_path.endswith('.mm'):
     # Try a bit harder to remove non-test files for c++. Without this,
     # 'autotest.py base/' finds non-test files.
     try:
@@ -343,25 +343,9 @@
 def FindMatchingTestFiles(target, remote_search=False):
   # Return early if there's an exact file match.
   if os.path.isfile(target):
-    # If the target is a C++ implementation file, try to guess the test file.
-    if target.endswith('.cc') or target.endswith('.h'):
-      target_validity = IsTestFile(target)
-      if target_validity is TestValidity.VALID_TEST:
-        return [target]
-      alternate = f"{target.rsplit('.', 1)[0]}_unittest.cc"
-      alt_validity = TestValidity.NOT_A_TEST if not os.path.isfile(
-          alternate) else IsTestFile(alternate)
-      if alt_validity is TestValidity.VALID_TEST:
-        return [alternate]
-
-      # If neither the target nor its alternative were valid, check if they just
-      # didn't include the gtest files before deciding to exit.
-      if target_validity is TestValidity.MAYBE_A_TEST:
-        return [target]
-      if alt_validity is TestValidity.MAYBE_A_TEST:
-        return [alternate]
-      ExitWithMessage(f"{target} doesn't look like a test file")
-    return [target]
+    if test_file := _FindTestForFile(target):
+      return [test_file]
+    ExitWithMessage(f"{target} doesn't look like a test file")
   # If this is a directory, return all the test files it contains.
   if os.path.isdir(target):
     files = FindTestFilesInDirectory(target)
@@ -420,6 +404,32 @@
   return test_files
 
 
+def _FindTestForFile(target: os.PathLike) -> str | None:
+  root, ext = os.path.splitext(target)
+  # If the target is a C++ implementation file, try to guess the test file.
+  # Candidates should be ordered most to least promising.
+  test_candidates = [target]
+  if ext == '.h':
+    # `*_unittest.{cc,mm}` are both possible.
+    test_candidates.append(f'{root}_unittest.cc')
+    test_candidates.append(f'{root}_unittest.mm')
+  elif ext == '.cc' or ext == '.mm':
+    test_candidates.append(f'{root}_unittest{ext}')
+  else:
+    return target
+
+  maybe_valid = []
+  for candidate in test_candidates:
+    if not os.path.isfile(candidate):
+      continue
+    validity = IsTestFile(candidate)
+    if validity is TestValidity.VALID_TEST:
+      return candidate
+    elif validity is TestValidity.MAYBE_A_TEST:
+      maybe_valid.append(candidate)
+  return maybe_valid[0] if maybe_valid else None
+
+
 def HaveUserPickFile(paths):
   paths = sorted(paths, key=lambda p: (len(p), p))
   path_list = '\n'.join(f'{i}. {t}' for i, t in enumerate(paths))
@@ -605,7 +615,11 @@
 
 def BuildTestFilter(filenames, line):
   java_files = [f for f in filenames if f.endswith('.java')]
-  cc_files = [f for f in filenames if f.endswith('.cc')]
+  # TODO(crbug.com/434009870): Support EarlGrey tests, which don't use
+  # Googletest's macros or pascal case naming convention.
+  cc_files = [
+      f for f in filenames if f.endswith('.cc') or f.endswith('_unittest.mm')
+  ]
   filters = []
   if java_files:
     filters.append(BuildJavaTestFilter(java_files))
diff --git a/tools/autotest_test.py b/tools/autotest_test.py
index 26c81d3..ca275696 100755
--- a/tools/autotest_test.py
+++ b/tools/autotest_test.py
@@ -29,6 +29,11 @@
     self.assertEqual(['foo_unittest.cc'],
                      autotest.FindMatchingTestFiles('foo_unittest.cc'))
 
+  def test_mm_test(self):
+    self.create_cc_test('foo_unittest.mm')
+    self.assertEqual(['foo_unittest.mm'],
+                     autotest.FindMatchingTestFiles('foo_unittest.mm'))
+
   def test_cc_alt_test(self):
     self.fs.create_file('foo.cc')
     self.create_cc_test('foo_unittest.cc')
@@ -55,6 +60,18 @@
     self.assertRegex(stderr_buf.getvalue(),
                      "foo.cc doesn't look like a test file")
 
+  def test_h_for_cc_test(self):
+    self.fs.create_file('foo.h')
+    self.create_cc_test('foo_unittest.cc')
+    self.assertEqual(['foo_unittest.cc'],
+                     autotest.FindMatchingTestFiles('foo.h'))
+
+  def test_h_for_mm_test(self):
+    self.fs.create_file('foo.h')
+    self.create_cc_test('foo_unittest.mm')
+    self.assertEqual(['foo_unittest.mm'],
+                     autotest.FindMatchingTestFiles('foo.h'))
+
   def test_java(self):
     self.fs.create_file('Foo.java')
     self.assertEqual(['Foo.java'], autotest.FindMatchingTestFiles('Foo.java'))
diff --git a/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py b/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py
index 42b9b26..99320f1 100755
--- a/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py
+++ b/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py
@@ -36,6 +36,14 @@
 
   print("Checking GN build arg configuration ...")
   try:
+    dcheck_cmd = [
+        "gn", "args", "-C", build_dir, "--short", "--list=dcheck_always_on"
+    ]
+    dcheck = subprocess.check_output(dcheck_cmd, text=True)
+    if "true" not in dcheck:
+      print("Set GN arg dcheck_always_on = true", file=sys.stderr)
+      sys.exit(1)
+
     diag_cmd = [
         "gn", "args", "-C", build_dir, "--short",
         "--list=diagnostics_print_source_range_info"
@@ -79,7 +87,7 @@
     print("Files containing unsafe pragmas:")
     print("\n".join(source_files), "\n")
 
-  iffy_cmd = ["grep", "-c", "^#if"] + source_files
+  iffy_cmd = ["grep", "-Pc", "^#if(?! DCHECK_IS_ON\\(\\))"] + source_files
   iffy = subprocess.check_output(iffy_cmd, text=True).strip()
   iffy_lines = iffy.splitlines() if iffy else []
   iffy_files = [x.split(":")[0] for x in iffy_lines if x.split(":")[1] != "1"]
@@ -94,7 +102,7 @@
     sys.exit(1)
 
   if verbose:
-    print("Remaing files:")
+    print("Remaining files after excluding #ifdefs:")
     print("\n".join(source_files), "\n")
 
   # Starting with all files in the directory, find the ones that are
@@ -110,7 +118,7 @@
     ]
 
   if verbose:
-    print("Remaing files:")
+    print("Remaining files after excluding unbuildable:")
     print("\n".join(source_files), "\n")
 
   subprocess.run(
diff --git a/tools/mb/rts_banned_suites.json b/tools/mb/rts_banned_suites.json
index 503cd94..dea891a 100644
--- a/tools/mb/rts_banned_suites.json
+++ b/tools/mb/rts_banned_suites.json
@@ -14,14 +14,12 @@
         "telemetry_gpu_integration_test_android_chrome",
         "telemetry_gpu_integration_test_android_monochrome",
         "telemetry_gpu_integration_test_android_monochrome_bundle",
-        "telemetry_gpu_integration_test_android_weblayer",
         "telemetry_gpu_integration_test_android_webview",
         "telemetry_gpu_unittests",
         "telemetry_perf_unittests",
         "telemetry_perf_unittests_android_chrome",
         "telemetry_perf_unittests_android_monochrome",
         "telemetry_perf_unittests_android_monochrome_bundle",
-        "telemetry_perf_unittests_android_weblayer",
         "telemetry_perf_unittests_android_webview",
         "telemetry_unittests",
         "test_env_py_unittests",
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 436f8d1e..426d473 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -26463,20 +26463,20 @@
 </action>
 
 <action name="MobileReauthFailed">
+  <obsolete>Deprecated as of 08/2025</obsolete>
   <owner>noemies@google.com</owner>
   <description>
-    Reported when reauthentication failed. iOS only. TODO(crbug.com/409680593):
-    This user action was added to investigate a crash. Remove when done with the
-    investigation.
+    Reported when reauthentication failed. iOS only. This user action was added
+    to investigate a crash, see crbug.com/409680593.
   </description>
 </action>
 
 <action name="MobileReauthSuccessful">
+  <obsolete>Deprecated as of 08/2025</obsolete>
   <owner>noemies@google.com</owner>
   <description>
-    Reported when reauthentication succeeded. iOS only.
-    TODO(crbug.com/409680593): This user action was added to investigate a
-    crash. Remove when done with the investigation.
+    Reported when reauthentication succeeded. iOS only. This user action was
+    added to investigate a crash, see crbug.com/409680593.
   </description>
 </action>
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8c55b9c..9cebc3a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10386,6 +10386,7 @@
   <int value="-1382709842"
       label="AutofillEnableDownstreamCardAwarenessIph:enabled"/>
   <int value="-1382671832" label="OmniboxUIExperimentVerticalMargin:enabled"/>
+  <int value="-1382307317" label="AiModeOmniboxEntryPoint:disabled"/>
   <int value="-1381231225" label="OmniboxNumWebZpsMostVisitedUrls:enabled"/>
   <int value="-1379844383" label="MacLoopbackAudioForCast:enabled"/>
   <int value="-1378071979" label="CroshSWA:enabled"/>
@@ -14200,6 +14201,7 @@
   <int value="28182289" label="CastStreamingVp8:disabled"/>
   <int value="29212695" label="OfflineIndicator:enabled"/>
   <int value="29769995" label="DataSharingNonProductionEnvironment:enabled"/>
+  <int value="29924596" label="AiModeOmniboxEntryPoint:enabled"/>
   <int value="31258497"
       label="AutofillEnableSyncingOfPixBankAccounts:disabled"/>
   <int value="31439497" label="ZeroSuggestInMemoryCaching:disabled"/>
@@ -15733,6 +15735,7 @@
   <int value="598926697" label="VrLaunchIntent:disabled"/>
   <int value="600037637" label="AndroidSigninPromos:enabled"/>
   <int value="600643275" label="OobeRecommendAppsScreen:enabled"/>
+  <int value="601020532" label="AutofillShowBubblesBasedOnPriorities:enabled"/>
   <int value="601417094" label="SupportF11AndF12KeyShortcuts:disabled"/>
   <int value="601510870" label="EcheLauncherIconsInMoreAppsButton:disabled"/>
   <int value="601688485" label="EnterpriseFileObfuscation:enabled"/>
@@ -19034,6 +19037,8 @@
   <int value="1786692012"
       label="AssistantEnableMediaSessionIntegration:disabled"/>
   <int value="1786724316" label="OmniboxIgnoreIntermediateResults:enabled"/>
+  <int value="1786896990"
+      label="AutofillShowBubblesBasedOnPriorities:disabled"/>
   <int value="1787171971" label="UserEducationExperienceVersion2:enabled"/>
   <int value="1787279386" label="VirtualKeyboardMultitouch:enabled"/>
   <int value="1787572807" label="PrefixWebAppWindowsWithAppName:enabled"/>
diff --git a/tools/metrics/histograms/metadata/autofill/enums.xml b/tools/metrics/histograms/metadata/autofill/enums.xml
index dfc91dc..0b38e88 100644
--- a/tools/metrics/histograms/metadata/autofill/enums.xml
+++ b/tools/metrics/histograms/metadata/autofill/enums.xml
@@ -155,6 +155,16 @@
   <int value="2" label="Import with section union"/>
 </enum>
 
+<!-- LINT.IfChange(AutofillAiDecryptStatus) -->
+
+<enum name="AutofillAiDecryptStatus">
+  <int value="0" label="Succeeded"/>
+  <int value="1" label="Failed temporarily"/>
+  <int value="2" label="Failed permanently"/>
+</enum>
+
+<!-- LINT.ThenChange(//components/autofill/core/browser/webdata/autofill_ai/entity_table.cc:DecryptionStatus) -->
+
 <!-- LINT.IfChange(AutofillAiEntityType) -->
 
 <enum name="AutofillAiEntityType">
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 3de51d7..b453a41 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1121,6 +1121,19 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.Ai.EntityTable.DecryptStatus2"
+    enum="AutofillAiDecryptStatus" expires_after="2025-12-12">
+  <owner>jihadghanna@google.com</owner>
+  <owner>chrome-autofill-alerts@google.com</owner>
+  <summary>
+    Records whether the decryption stage of reading from the EntityTable was
+    successful or not (and in that case whether it was a permanent failure (key
+    was lost or data was corrupted) or a temporary failure (e.g. the decryption
+    service was unavailable). Emitted every time autofill tries to decrypt a
+    value to read/write to the table.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.Ai.EntityTable.{EncryptionStage}Status"
     enum="Boolean" expires_after="2025-12-12">
   <owner>jihadghanna@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index 2db978b8..e9df891a 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -1861,6 +1861,20 @@
   </summary>
 </histogram>
 
+<histogram name="InfoBar.CountAtShow" units="InfoBars" expires_after="never">
+<!-- expires-never: Required as long as infobars exist. -->
+
+  <owner>koretadaniel@chromium.org</owner>
+  <owner>top-chrome-desktop-ui@google.com</owner>
+  <summary>
+    Records how many infobars were visible at the moment a new infobar was
+    shown. This is recorded any time a new infobar is shown. The maximum bucket
+    for this metric is set to 10. It is less plausible to have 10 infobars at
+    the same time, so this maximum value will help to capture all the lower
+    buckets distinctly.
+  </summary>
+</histogram>
+
 <histogram name="InfoBar.Shown" enum="InfoBarIdentifier" expires_after="never">
 <!-- expires-never: Required as long as infobars exist. -->
 
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 4754dd8..ed61592 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -2104,6 +2104,15 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.Gemini.Session.Time" units="ms" expires_after="2026-07-21">
+  <owner>kanouche@google.com</owner>
+  <owner>bling-alchemy-eng@google.com</owner>
+  <summary>
+    Records the duration of a BWG session. A session starts when the BWG UI
+    appears and ends when the BWG UI disappears. Recorded when a session ends.
+  </summary>
+</histogram>
+
 <histogram name="IOS.Gemini.StartupTime.{FirstRunBool}" units="ms"
     expires_after="2026-07-21">
   <owner>nicolasmacbeth@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 3f4f5f0..4323bf91 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -1266,6 +1266,18 @@
 </histogram>
 
 <histogram
+    name="OptimizationGuide.ModelExecution.OnDeviceResponseTokensTimeToNextToken.{ModelExecutionFeature}"
+    units="ms" expires_after="2026-08-01">
+  <owner>cduvall@chromium.org</owner>
+  <owner>memmottt@chromium.org</owner>
+  <summary>
+    Records the average time between tokens. Recorded on successful completion
+    of for each execution of the on device model.
+  </summary>
+  <token key="ModelExecutionFeature" variants="ModelExecutionFeature"/>
+</histogram>
+
+<histogram
     name="OptimizationGuide.ModelExecution.OnDeviceTextSafetyModelMetadataValidity"
     enum="OnDeviceTextSafetyModelMetadataValidity" expires_after="2025-01-26">
   <owner>holte@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/enums.xml b/tools/metrics/histograms/metadata/page/enums.xml
index 846585f..3f61c2c9 100644
--- a/tools/metrics/histograms/metadata/page/enums.xml
+++ b/tools/metrics/histograms/metadata/page/enums.xml
@@ -299,6 +299,7 @@
   <int value="32" label="Collaboration Messaging"/>
   <int value="33" label="(Deprecated) Change Password"/>
   <int value="34" label="Lens Overlay Homework"/>
+  <int value="35" label="AI Mode"/>
 </enum>
 
 <!-- LINT.ThenChange(//chrome/browser/ui/page_action/page_action_icon_type.h:PageActionIconType) -->
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 180c047..02382f4 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -383,6 +383,7 @@
     visible on a given page, and &quot;Clicked&quot; is logged once per click.
   </summary>
   <token key="PageActionType">
+    <variant name="AiMode"/>
     <variant name="BookmarksStar"/>
     <variant name="ClickToCall"/>
     <variant name="CookieControls"/>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index 2c7abaae..51db29c 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -1000,16 +1000,30 @@
   <token key="RequestType" variants="ClientSideDetectionRequestType"/>
 </histogram>
 
-<histogram name="SBClientPhishing.PhishingImageEmbeddingResult"
+<histogram name="SBClientPhishing.PhishingImageEmbeddingDuration{RequestType}"
+    units="ms" expires_after="2026-08-01">
+  <owner>andysjlim@chromium.org</owner>
+  <owner>chrome-counter-abuse-alerts@google.com</owner>
+  <summary>
+    Records the duration it takes for image embedding requested by {RequestType}
+    to finish. This occurs for ESB enabled users only after the image embedding
+    request has been made.
+  </summary>
+  <token key="RequestType" variants="ClientSideDetectionRequestType"/>
+</histogram>
+
+<histogram name="SBClientPhishing.PhishingImageEmbeddingResult{RequestType}"
     enum="ClientSidePhishingImageEmbeddingResult" expires_after="2025-12-21">
   <owner>andysjlim@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
-    The result enum received from renderer-side image embedder. This is recorded
-    after every renderer image embedding which is expected to happen when the
-    user is subscribed to ESB, has an image embedding model loaded, and the page
-    is deemed phishy by the phishing classification process.
+    The result enum received from renderer-side image embedder when requested by
+    {RequestType}. This is recorded after every renderer image embedding which
+    is expected to happen when the user is subscribed to ESB, has an image
+    embedding model loaded, and the page is deemed phishy by the phishing
+    classification process.
   </summary>
+  <token key="RequestType" variants="ClientSideDetectionRequestType"/>
 </histogram>
 
 <histogram name="SBClientPhishing.PreClassificationCheckResult{RequestType}"
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index eb24c1a0..005689bb 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/361808c959b026d558c9948602ea38bf25d8981e/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "2c35bb44cd2bf306d59d38391d7841aab30351ab",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/1bb8e028baa0cde2ee52f30a583b46da66ce5f11/trace_processor_shell.exe"
+            "hash": "89e617c5bcf0ba7ce1c7177238dd6ce99d784d1d",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/8a4b37d094ba5fce2f2ad87d04078ed9b8b54127/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "ab1a0d9236a63649044414663b6ace711253648f",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "b59410be89b9bd3cb962093b4f8c8a7ccbf2f93e",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/0aaffc1451208a812c75a15bb72941266fd7a62a/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/4c0ba925d3304ab862e4e866d9b1ad6b451cc82f/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/safe_list.txt b/tools/traffic_annotation/safe_list.txt
index 053ecf3..de80e55 100644
--- a/tools/traffic_annotation/safe_list.txt
+++ b/tools/traffic_annotation/safe_list.txt
@@ -2,7 +2,7 @@
 # annotation auditor. Please refer to README.md for more details.
 
 # Low-level networking code is deliberately excluded from the analysis.
-all,tools/*,*test*,*fuzzer*,*mock*,*fake*,weblayer/*
+all,tools/*,*test*,*fuzzer*,*mock*,*fake*
 all,net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java
 missing,remoting/host/token_validator_factory_impl.cc
 missing,components/cronet/cronet_url_request.cc
diff --git a/ui/accelerated_widget_mac/DEPS b/ui/accelerated_widget_mac/DEPS
index b232b78..2f51446 100644
--- a/ui/accelerated_widget_mac/DEPS
+++ b/ui/accelerated_widget_mac/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/metal_util",
+  "+components/viz/common/resources/shared_image_format.h",
   "+gpu/GLES2",
   "+media/base/mac/color_space_util_mac.h",
   "+third_party/skia",
diff --git a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
index 6536eb7..9bbb1102 100644
--- a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
+++ b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
@@ -13,6 +13,7 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "components/metal_util/hdr_copier_layer.h"
+#include "components/viz/common/resources/shared_image_format.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
@@ -131,8 +132,8 @@
     properties.background_color = SkColors::kRed;
     properties.edge_aa_mask = ui::CALayerEdge::kLayerEdgeLeft;
     properties.opacity = 0.5f;
-    properties.io_surface =
-        gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
+    properties.io_surface = gfx::CreateIOSurface(
+        gfx::Size(256, 256), viz::SinglePlaneFormat::kBGRA_8888);
 
     std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree;
     CALayer* root_layer = nil;
@@ -410,7 +411,7 @@
     {
       properties.is_clipped = true;
       properties.io_surface = gfx::CreateIOSurface(
-          gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
+          gfx::Size(256, 256), viz::SinglePlaneFormat::kBGRA_8888);
       UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
 
       // Validate the tree structure.
@@ -574,8 +575,8 @@
   // We'll use the IOSurface contents to identify the content layers.
   gfx::ScopedIOSurface io_surfaces[5];
   for (size_t i = 0; i < 5; ++i) {
-    io_surfaces[i] =
-        gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
+    io_surfaces[i] = gfx::CreateIOSurface(gfx::Size(256, 256),
+                                          viz::SinglePlaneFormat::kBGRA_8888);
   }
 
   // Have 5 transforms:
@@ -657,8 +658,8 @@
   // We'll use the IOSurface contents to identify the content layers.
   gfx::ScopedIOSurface io_surfaces[3];
   for (size_t i = 0; i < 3; ++i) {
-    io_surfaces[i] =
-        gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
+    io_surfaces[i] = gfx::CreateIOSurface(gfx::Size(256, 256),
+                                          viz::SinglePlaneFormat::kBGRA_8888);
   }
 
   int sorting_context_ids[3] = {3, -1, 0};
@@ -763,8 +764,8 @@
   features.InitWithFeatures({ui::kFullscreenLowPowerBackdropMac}, {});
 
   CALayerProperties properties;
-  properties.io_surface =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
+  properties.io_surface = gfx::CreateIOSurface(
+      gfx::Size(256, 256), viz::SinglePlaneFormat::kBGRA_8888);
 
   std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree;
   CALayer* content_layer_old = nil;
@@ -781,8 +782,8 @@
 
   // Pass a YUV 420 frame. This will become an AVSampleBufferDisplayLayer
   // because it is in fullscreen low power mode.
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(256, 256), viz::MultiPlaneFormat::kNV12);
   {
     UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
     content_layer_new = GetOnlyContentLayer();
@@ -793,8 +794,8 @@
   content_layer_old = content_layer_new;
 
   // Pass a similar frame. Nothing should change.
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(256, 128), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(256, 128), viz::MultiPlaneFormat::kNV12);
   {
     UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
     content_layer_new = GetOnlyContentLayer();
@@ -819,7 +820,7 @@
   // Now try a P010 frame. Because this may be HDR, we should jump back to
   // having an AVSampleBufferDisplayLayer.
   properties.io_surface =
-      gfx::CreateIOSurface(gfx::Size(128, 256), gfx::BufferFormat::P010);
+      gfx::CreateIOSurface(gfx::Size(128, 256), viz::MultiPlaneFormat::kP010);
   {
     UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
     content_layer_new = GetOnlyContentLayer();
@@ -834,8 +835,8 @@
 
   // Pass a frame with a CVPixelBuffer which, when scaled down, will have a
   // fractional dimension.
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(513, 512), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(513, 512), viz::MultiPlaneFormat::kNV12);
   properties.cv_pixel_buffer = CreateCVPixelBuffer(properties.io_surface);
   properties.color_space = gfx::ColorSpace::CreateREC709();
   {
@@ -852,8 +853,8 @@
 
   // Pass a frame that is clipped.
   properties.contents_rect = gfx::RectF(0, 0, 1, 0.9);
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(256, 256), viz::MultiPlaneFormat::kNV12);
   {
     UpdateCALayerTree(ca_layer_tree, &properties, superlayer_);
     content_layer_new = GetOnlyContentLayer();
@@ -870,8 +871,8 @@
   features.InitWithFeatures({ui::kFullscreenLowPowerBackdropMac}, {});
 
   CALayerProperties properties;
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(256, 256), viz::MultiPlaneFormat::kNV12);
 
   std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree;
   CALayer* root_layer = nil;
@@ -930,8 +931,8 @@
   features.InitWithFeatures({ui::kFullscreenLowPowerBackdropMac}, {});
 
   CALayerProperties properties;
-  properties.io_surface = gfx::CreateIOSurface(
-      gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR);
+  properties.io_surface =
+      gfx::CreateIOSurface(gfx::Size(256, 256), viz::MultiPlaneFormat::kNV12);
   properties.cv_pixel_buffer = CreateCVPixelBuffer(properties.io_surface);
   properties.color_space = gfx::ColorSpace::CreateREC709();
   properties.is_clipped = false;
@@ -1075,12 +1076,12 @@
   bool result = false;
 
   // We only copy images that have both high-bit-depth and an HDR color space.
-  auto sdr_image =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
-  auto tricky_sdr_image =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
-  auto hdr_image =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::RGBA_F16);
+  auto sdr_image = gfx::CreateIOSurface(gfx::Size(256, 256),
+                                        viz::SinglePlaneFormat::kBGRA_8888);
+  auto tricky_sdr_image = gfx::CreateIOSurface(
+      gfx::Size(256, 256), viz::SinglePlaneFormat::kBGRA_8888);
+  auto hdr_image = gfx::CreateIOSurface(gfx::Size(256, 256),
+                                        viz::SinglePlaneFormat::kRGBA_F16);
 
   // Schedule and commit the HDR layer.
   properties.io_surface = hdr_image;
@@ -1152,10 +1153,10 @@
 
 TEST(HDRCoperLayerTest, Formats) {
   gfx::HDRMetadata metadata_empty;
-  auto io_surface_8888 =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888);
-  auto io_surface_f16 =
-      gfx::CreateIOSurface(gfx::Size(256, 256), gfx::BufferFormat::RGBA_F16);
+  auto io_surface_8888 = gfx::CreateIOSurface(
+      gfx::Size(256, 256), viz::SinglePlaneFormat::kBGRA_8888);
+  auto io_surface_f16 = gfx::CreateIOSurface(gfx::Size(256, 256),
+                                             viz::SinglePlaneFormat::kRGBA_F16);
   auto cs_extended_linear = gfx::ColorSpace(
       gfx::ColorSpace::PrimaryID::P3, gfx::ColorSpace::TransferID::LINEAR_HDR);
   auto cs_g22 = gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT709,
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index d709dd7..a319377dd 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -26,6 +26,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "components/metal_util/hdr_copier_layer.h"
+#include "components/viz/common/resources/shared_image_format.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/cocoa/animation_utils.h"
@@ -248,7 +249,7 @@
     return found->second;
 
   const gfx::Size size(kSolidColorContentsSize, kSolidColorContentsSize);
-  gfx::BufferFormat buffer_format = gfx::BufferFormat::BGRA_8888;
+  viz::SharedImageFormat si_format = viz::SinglePlaneFormat::kBGRA_8888;
   SkColorType color_type = kBGRA_8888_SkColorType;
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
 
@@ -260,7 +261,7 @@
   }
 
   base::apple::ScopedCFTypeRef<IOSurfaceRef> io_surface =
-      CreateIOSurface(size, buffer_format);
+      CreateIOSurface(size, si_format);
   if (!io_surface)
     return nullptr;
   IOSurfaceSetColorSpace(io_surface.get(), color_space);
diff --git a/ui/anchor/BUILD.gn b/ui/anchor/BUILD.gn
new file mode 100644
index 0000000..3807f1d
--- /dev/null
+++ b/ui/anchor/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("anchor") {
+  sources = [ "anchor.h" ]
+  public_deps = [
+    "//base",
+    "//ui/gfx/geometry",
+  ]
+}
+
+config("impl_config") {
+  defines = [ "IS_UI_ANCHOR_IMPL" ]
+}
+
+source_set("impl") {
+  sources = [ "anchor.cc" ]
+  deps = [ ":anchor" ]
+  public_configs = [ ":impl_config" ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [ "anchor_unittest.cc" ]
+
+  deps = [
+    ":anchor",
+    ":impl",
+    "//base",
+    "//testing/gtest",
+    "//ui/gfx/geometry",
+  ]
+}
diff --git a/ui/anchor/OWNERS b/ui/anchor/OWNERS
new file mode 100644
index 0000000..391addf1
--- /dev/null
+++ b/ui/anchor/OWNERS
@@ -0,0 +1 @@
+file://ui/views/OWNERS
diff --git a/ui/anchor/anchor.cc b/ui/anchor/anchor.cc
new file mode 100644
index 0000000..26cd0c3
--- /dev/null
+++ b/ui/anchor/anchor.cc
@@ -0,0 +1,80 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/anchor/anchor.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/check.h"
+
+namespace {
+
+class EmptyAnchor : public ui::AnchorImpl {
+ public:
+  ~EmptyAnchor() override = default;
+
+  // ui::AnchorImpl:
+  std::unique_ptr<AnchorImpl> Clone() const override {
+    return std::make_unique<EmptyAnchor>();
+  }
+  bool IsEmpty() const override { return true; }
+  gfx::Rect GetScreenBounds() const override { return gfx::Rect(); }
+  views::Widget* GetWidget() override { return nullptr; }
+  bool IsView() const override { return false; }
+  views::View* GetView() override { return nullptr; }
+};
+
+}  // namespace
+
+namespace ui {
+
+Anchor::Anchor() : impl_(std::make_unique<EmptyAnchor>()) {}
+
+Anchor::Anchor(std::unique_ptr<AnchorImpl> impl) : impl_(std::move(impl)) {
+  CHECK(impl_);
+}
+
+Anchor::Anchor(const Anchor& other) : impl_(other.impl_->Clone()) {}
+
+Anchor::Anchor(Anchor&& other) noexcept
+    : impl_(std::exchange(other.impl_, std::make_unique<EmptyAnchor>())) {}
+
+Anchor& Anchor::operator=(const Anchor& other) {
+  if (this != &other) {
+    impl_ = other.impl_->Clone();
+  }
+  return *this;
+}
+
+Anchor& Anchor::operator=(Anchor&& other) noexcept {
+  if (this != &other) {
+    impl_ = std::exchange(other.impl_, std::make_unique<EmptyAnchor>());
+  }
+  return *this;
+}
+
+Anchor::~Anchor() = default;
+
+bool Anchor::IsView() const {
+  return impl_->IsView();
+}
+
+views::View* Anchor::GetView() {
+  return impl_->GetView();
+}
+
+bool Anchor::IsEmpty() const {
+  return impl_->IsEmpty();
+}
+
+gfx::Rect Anchor::GetScreenBounds() const {
+  return impl_->GetScreenBounds();
+}
+
+views::Widget* Anchor::GetWidget() {
+  return impl_->GetWidget();
+}
+
+}  // namespace ui
diff --git a/ui/anchor/anchor.h b/ui/anchor/anchor.h
new file mode 100644
index 0000000..7b54a0a6
--- /dev/null
+++ b/ui/anchor/anchor.h
@@ -0,0 +1,80 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ANCHOR_ANCHOR_H_
+#define UI_ANCHOR_ANCHOR_H_
+
+#include <memory>
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace views {
+class View;
+class Widget;
+}  // namespace views
+
+namespace ui {
+
+class AnchorImpl;
+
+// ui::Anchor is a generic reference to a UI element that can be used to
+// position other UI elements. It can be backed by a view or a DOM element in
+// WebUI.
+//
+// This is designed to be transparently constructed from a views::View*, so that
+// code that previously uses an anchor view can easily migrate to accept a WebUI
+// anchor.
+//
+// This class assumes that the anchor is hosted in a views::Widget window.
+class COMPONENT_EXPORT(UI_ANCHOR) Anchor {
+ public:
+  // Creates an empty anchor.
+  Anchor();
+
+  Anchor(const Anchor& other);
+  Anchor(Anchor&& other) noexcept;
+  Anchor& operator=(const Anchor& other);
+  Anchor& operator=(Anchor&& other) noexcept;
+  ~Anchor();
+
+  // Deliberately implicit.
+  // A ui::Anchor can be transparently constructed from a views::View*.
+  // Your code must depend on //ui/views to use this constructor.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Anchor(views::View* anchor_view);
+
+  // Returns true if the anchor is backed by a views::View.
+  bool IsView() const;
+  views::View* GetView();
+
+  // Returns the widget hosting the anchor.
+  views::Widget* GetWidget();
+
+  bool IsEmpty() const;
+  explicit operator bool() const { return !IsEmpty(); }
+
+  // Returns the bounds of the anchor in screen coordinates.
+  gfx::Rect GetScreenBounds() const;
+
+ protected:
+  explicit Anchor(std::unique_ptr<AnchorImpl> impl);
+
+ private:
+  std::unique_ptr<AnchorImpl> impl_;
+};
+
+class AnchorImpl {
+ public:
+  virtual ~AnchorImpl() = default;
+  virtual std::unique_ptr<AnchorImpl> Clone() const = 0;
+  virtual bool IsEmpty() const = 0;
+  virtual gfx::Rect GetScreenBounds() const = 0;
+  virtual views::Widget* GetWidget() = 0;
+  virtual bool IsView() const = 0;
+  virtual views::View* GetView() = 0;
+};
+
+}  // namespace ui
+
+#endif  // UI_ANCHOR_ANCHOR_H_
diff --git a/ui/anchor/anchor_unittest.cc b/ui/anchor/anchor_unittest.cc
new file mode 100644
index 0000000..aff8ac2b
--- /dev/null
+++ b/ui/anchor/anchor_unittest.cc
@@ -0,0 +1,112 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/anchor/anchor.h"
+
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+namespace {
+
+class TestAnchorImpl : public AnchorImpl {
+ public:
+  TestAnchorImpl() = default;
+  ~TestAnchorImpl() override = default;
+
+  // AnchorImpl:
+  std::unique_ptr<AnchorImpl> Clone() const override {
+    return std::make_unique<TestAnchorImpl>();
+  }
+  bool IsEmpty() const override { return false; }
+  gfx::Rect GetScreenBounds() const override { return gfx::Rect(1, 2, 3, 4); }
+  views::Widget* GetWidget() override { return nullptr; }
+  bool IsView() const override { return false; }
+  views::View* GetView() override { return nullptr; }
+};
+
+// A derived class to access the protected constructor of Anchor.
+class TestAnchor : public Anchor {
+ public:
+  TestAnchor() : Anchor(std::make_unique<TestAnchorImpl>()) {}
+};
+
+}  // namespace
+
+TEST(AnchorTest, EmptyAnchor) {
+  Anchor empty_anchor;
+  EXPECT_TRUE(empty_anchor.IsEmpty());
+  EXPECT_FALSE(empty_anchor);
+  EXPECT_FALSE(empty_anchor.IsView());
+  EXPECT_EQ(nullptr, empty_anchor.GetView());
+  EXPECT_EQ(gfx::Rect(), empty_anchor.GetScreenBounds());
+  EXPECT_EQ(nullptr, empty_anchor.GetWidget());
+}
+
+TEST(AnchorTest, CopyConstructor) {
+  // Copy empty anchor.
+  Anchor empty_anchor;
+  Anchor empty_anchor_copy(empty_anchor);
+  EXPECT_TRUE(empty_anchor_copy.IsEmpty());
+
+  // Copy non-empty anchor.
+  TestAnchor test_anchor;
+  Anchor test_anchor_copy(test_anchor);
+  EXPECT_FALSE(test_anchor_copy.IsEmpty());
+  EXPECT_EQ(test_anchor.GetScreenBounds(), test_anchor_copy.GetScreenBounds());
+}
+
+TEST(AnchorTest, MoveConstructor) {
+  // Move empty anchor.
+  Anchor empty_anchor;
+  Anchor empty_anchor_moved(std::move(empty_anchor));
+  EXPECT_TRUE(empty_anchor_moved.IsEmpty());
+
+  // Move non-empty anchor.
+  TestAnchor test_anchor;
+  gfx::Rect bounds = test_anchor.GetScreenBounds();
+  Anchor test_anchor_moved(std::move(test_anchor));
+  EXPECT_FALSE(test_anchor_moved.IsEmpty());
+  EXPECT_EQ(bounds, test_anchor_moved.GetScreenBounds());
+
+  // Test that the moved-from anchor is now empty.
+  EXPECT_TRUE(test_anchor.IsEmpty());
+  EXPECT_EQ(gfx::Rect(), test_anchor.GetScreenBounds());
+}
+
+TEST(AnchorTest, CopyAssignment) {
+  // Copy-assign empty anchor to non-empty.
+  Anchor test_anchor = TestAnchor();
+  Anchor empty_anchor;
+  test_anchor = empty_anchor;
+  EXPECT_TRUE(test_anchor.IsEmpty());
+
+  // Copy-assign non-empty anchor to empty.
+  TestAnchor test_anchor2;
+  empty_anchor = test_anchor2;
+  EXPECT_FALSE(empty_anchor.IsEmpty());
+  EXPECT_EQ(test_anchor2.GetScreenBounds(), empty_anchor.GetScreenBounds());
+}
+
+TEST(AnchorTest, MoveAssignment) {
+  // Move-assign empty anchor to non-empty.
+  Anchor test_anchor = TestAnchor();
+  Anchor empty_anchor;
+  test_anchor = std::move(empty_anchor);
+  EXPECT_TRUE(test_anchor.IsEmpty());
+
+  // Move-assign non-empty anchor to empty.
+  Anchor empty_anchor2;
+  TestAnchor test_anchor2;
+  gfx::Rect bounds = test_anchor2.GetScreenBounds();
+  empty_anchor2 = std::move(test_anchor2);
+  EXPECT_FALSE(empty_anchor2.IsEmpty());
+  EXPECT_EQ(bounds, empty_anchor2.GetScreenBounds());
+  EXPECT_TRUE(test_anchor2.IsEmpty());
+}
+
+}  // namespace ui
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
index 5d10b10..bbf2ee7 100644
--- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -38,6 +38,7 @@
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
+import org.chromium.base.AconfigFlaggedApiDelegate;
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
@@ -45,6 +46,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.PackageManagerUtils;
+import org.chromium.base.ServiceLoaderUtil;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.UnownedUserDataHost;
 import org.chromium.base.lifetime.Destroyable;
@@ -210,6 +212,8 @@
     private boolean mIsTopResumedActivity;
     private final boolean mActivityTopResumedSupported;
 
+    private @Nullable AconfigFlaggedApiDelegate mAconfigFlaggedApiDelegate;
+
     /**
      * @param context The application {@link Context}.
      * @param trackOcclusion Whether to track occlusion of the window.
@@ -1350,6 +1354,18 @@
         mPointerLockingViewPrvFocusChangeListener = null;
     }
 
+    @CalledByNative
+    private boolean setHasKeyboardCapture(boolean hasCapture) {
+        Window window = getWindow();
+        if (window == null) return false;
+        if (mAconfigFlaggedApiDelegate == null) {
+            mAconfigFlaggedApiDelegate =
+                    ServiceLoaderUtil.maybeCreate(AconfigFlaggedApiDelegate.class);
+            if (mAconfigFlaggedApiDelegate == null) return false;
+        }
+        return mAconfigFlaggedApiDelegate.setKeyboardCaptureEnabled(window, hasCapture);
+    }
+
     @NativeMethods
     interface Natives {
         long init(
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index bf4f40d..0d918bf 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -361,6 +361,12 @@
   pointer_locking_view_ = nullptr;
 }
 
+bool WindowAndroid::SetHasKeyboardCapture(bool keyboard_capture) {
+  JNIEnv* env = AttachCurrentThread();
+  return Java_WindowAndroid_setHasKeyboardCapture(env, GetJavaObject(),
+                                                  keyboard_capture);
+}
+
 void WindowAndroid::SetTestHooks(TestHooks* hooks) {
   test_hooks_ = hooks;
   if (!test_hooks_)
diff --git a/ui/android/window_android.h b/ui/android/window_android.h
index e0ed406..efe6b3a 100644
--- a/ui/android/window_android.h
+++ b/ui/android/window_android.h
@@ -154,6 +154,8 @@
 
   void ReleasePointerLock(ViewAndroid& view_android);
 
+  bool SetHasKeyboardCapture(bool keyboard_capture);
+
   class TestHooks {
    public:
     virtual ~TestHooks() = default;
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 20361d4..b127b90a 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -215,7 +215,6 @@
     "ui_base_exports.cc",
     "ui_base_paths.cc",
     "ui_base_paths.h",
-    "ui_base_switches.cc",
     "ui_base_switches.h",
     "ui_base_switches_util.cc",
     "ui_base_switches_util.h",
@@ -270,7 +269,6 @@
       "win/hwnd_metrics.h",
       "win/hwnd_subclass.cc",
       "win/hwnd_subclass.h",
-      "win/internal_constants.cc",
       "win/internal_constants.h",
       "win/lock_state.cc",
       "win/lock_state.h",
@@ -348,7 +346,6 @@
       "cocoa/user_interface_item_command_handler.h",
       "cocoa/views_hostable.h",
       "cocoa/window_size_constants.h",
-      "cocoa/window_size_constants.mm",
       "dragdrop/os_exchange_data_provider_builder_mac.h",
       "dragdrop/os_exchange_data_provider_builder_mac.mm",
       "dragdrop/os_exchange_data_provider_mac.h",
@@ -1370,10 +1367,7 @@
   # This source set defines linux wm role names and must not have any external
   # dependencies and be kept as minimal as possible.
   source_set("wm_role_names") {
-    sources = [
-      "wm_role_names_linux.cc",
-      "wm_role_names_linux.h",
-    ]
+    sources = [ "wm_role_names_linux.h" ]
   }
 }
 
diff --git a/ui/base/accelerators/media_keys_util.cc b/ui/base/accelerators/media_keys_util.cc
index cacb972..cb6e883 100644
--- a/ui/base/accelerators/media_keys_util.cc
+++ b/ui/base/accelerators/media_keys_util.cc
@@ -8,8 +8,6 @@
 
 namespace ui {
 
-const char kMediaHardwareKeyActionHistogramName[] = "Media.HardwareKeyPressed";
-
 void RecordMediaHardwareKeyAction(ui::MediaHardwareKeyAction action) {
   UMA_HISTOGRAM_ENUMERATION(kMediaHardwareKeyActionHistogramName, action);
 }
diff --git a/ui/base/accelerators/media_keys_util.h b/ui/base/accelerators/media_keys_util.h
index 1a03eb5f..06922b80 100644
--- a/ui/base/accelerators/media_keys_util.h
+++ b/ui/base/accelerators/media_keys_util.h
@@ -24,8 +24,8 @@
 };
 
 // The name of the histogram that records |MediaHardwareKeyAction|.
-COMPONENT_EXPORT(UI_BASE)
-extern const char kMediaHardwareKeyActionHistogramName[];
+inline constexpr char kMediaHardwareKeyActionHistogramName[] =
+    "Media.HardwareKeyPressed";
 
 // Records a media hardware key action to the
 // |kMediaHardwareKeyActionHistogramName| histogram.
diff --git a/ui/base/cocoa/window_size_constants.h b/ui/base/cocoa/window_size_constants.h
index c521b15..2be7d46 100644
--- a/ui/base/cocoa/window_size_constants.h
+++ b/ui/base/cocoa/window_size_constants.h
@@ -5,14 +5,12 @@
 #ifndef UI_BASE_COCOA_WINDOW_SIZE_CONSTANTS_H_
 #define UI_BASE_COCOA_WINDOW_SIZE_CONSTANTS_H_
 
-#include "base/component_export.h"
-
 #import <Foundation/Foundation.h>
 
 namespace ui {
 
 // It is not valid to make a zero-sized window. Use this constant instead.
-COMPONENT_EXPORT(UI_BASE) extern const NSRect kWindowSizeDeterminedLater;
+inline constexpr NSRect kWindowSizeDeterminedLater = {{0, 0}, {1, 1}};
 
 }  // namespace ui
 
diff --git a/ui/base/cocoa/window_size_constants.mm b/ui/base/cocoa/window_size_constants.mm
deleted file mode 100644
index 49606b173..0000000
--- a/ui/base/cocoa/window_size_constants.mm
+++ /dev/null
@@ -1,11 +0,0 @@
-// 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.
-
-#include "ui/base/cocoa/window_size_constants.h"
-
-namespace ui {
-
-const NSRect kWindowSizeDeterminedLater = { {0, 0}, {1, 1} };
-
-}  // namespace ui
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn
index d24d946..63e2515f 100644
--- a/ui/base/ime/BUILD.gn
+++ b/ui/base/ime/BUILD.gn
@@ -60,7 +60,6 @@
 component("ime") {
   output_name = "ui_base_ime"
   sources = [
-    "constants.cc",
     "constants.h",
     "events.cc",
     "events.h",
diff --git a/ui/base/ime/ash/extension_ime_util.cc b/ui/base/ime/ash/extension_ime_util.cc
index 4ee5aec8..82e15f0 100644
--- a/ui/base/ime/ash/extension_ime_util.cc
+++ b/ui/base/ime/ash/extension_ime_util.cc
@@ -29,33 +29,6 @@
 
 namespace extension_ime_util {
 
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-const char kXkbExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kM17nExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kHangulExtensionId[] = "bdgdidmhaijohebebipajioienkglgfo";
-const char kMozcExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kT13nExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kChinesePinyinExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kChineseZhuyinExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-const char kChineseCangjieExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
-#else
-const char kXkbExtensionId[] = "fgoepimhcoialccpbmpnnblemnepkkao";
-const char kM17nExtensionId[] = "jhffeifommiaekmbkkjlpmilogcfdohp";
-const char kHangulExtensionId[] = "bdgdidmhaijohebebipajioienkglgfo";
-const char kMozcExtensionId[] = "bbaiamgfapehflhememkfglaehiobjnk";
-const char kT13nExtensionId[] = "gjaehgfemfahhmlgpdfknkhdnemmolop";
-const char kChinesePinyinExtensionId[] = "cpgalbafkoofkjmaeonnfijgpfennjjn";
-const char kChineseZhuyinExtensionId[] = "ekbifjdfhkmdeeajnolmgdlmkllopefi";
-const char kChineseCangjieExtensionId[] = "aeebooiibjahgpgmhkeocbeekccfknbj";
-#endif
-
-const char kBrailleImeExtensionId[] = "jddehjeebkoimngcbdkaahpobgicbffp";
-const char kBrailleImeExtensionPath[] = "chromeos/accessibility/braille_ime";
-const char kBrailleImeEngineId[] =
-    "_comp_ime_jddehjeebkoimngcbdkaahpobgicbffpbraille";
-
-const char kArcImeLanguage[] = "_arc_ime_language_";
-
 std::string GetInputMethodID(const std::string& extension_id,
                              const std::string& engine_id) {
   DCHECK(!extension_id.empty());
diff --git a/ui/base/ime/ash/extension_ime_util.h b/ui/base/ime/ash/extension_ime_util.h
index ff46ce50..905a96f 100644
--- a/ui/base/ime/ash/extension_ime_util.h
+++ b/ui/base/ime/ash/extension_ime_util.h
@@ -9,34 +9,48 @@
 
 #include "base/auto_reset.h"
 #include "base/component_export.h"
-
-namespace ash {
+#include "build/branding_buildflags.h"
 
 // Extension IME related utilities.
-namespace extension_ime_util {
+namespace ash::extension_ime_util {
 
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kXkbExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kM17nExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kHangulExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kMozcExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kT13nExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH)
-extern const char kChinesePinyinExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH)
-extern const char kChineseZhuyinExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH)
-extern const char kChineseCangjieExtensionId[];
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+inline constexpr char kXkbExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kM17nExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kHangulExtensionId[] = "bdgdidmhaijohebebipajioienkglgfo";
+inline constexpr char kMozcExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kT13nExtensionId[] = "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kChinesePinyinExtensionId[] =
+    "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kChineseZhuyinExtensionId[] =
+    "jkghodnilhceideoidjikpgommlajknk";
+inline constexpr char kChineseCangjieExtensionId[] =
+    "jkghodnilhceideoidjikpgommlajknk";
+#else
+inline constexpr char kXkbExtensionId[] = "fgoepimhcoialccpbmpnnblemnepkkao";
+inline constexpr char kM17nExtensionId[] = "jhffeifommiaekmbkkjlpmilogcfdohp";
+inline constexpr char kHangulExtensionId[] = "bdgdidmhaijohebebipajioienkglgfo";
+inline constexpr char kMozcExtensionId[] = "bbaiamgfapehflhememkfglaehiobjnk";
+inline constexpr char kT13nExtensionId[] = "gjaehgfemfahhmlgpdfknkhdnemmolop";
+inline constexpr char kChinesePinyinExtensionId[] =
+    "cpgalbafkoofkjmaeonnfijgpfennjjn";
+inline constexpr char kChineseZhuyinExtensionId[] =
+    "ekbifjdfhkmdeeajnolmgdlmkllopefi";
+inline constexpr char kChineseCangjieExtensionId[] =
+    "aeebooiibjahgpgmhkeocbeekccfknbj";
+#endif
 
 // Extension id, path (relative to |chrome::DIR_RESOURCES|) and IME engine
 // id for the builtin-in Braille IME extension.
-COMPONENT_EXPORT(UI_BASE_IME_ASH)
-extern const char kBrailleImeExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH)
-extern const char kBrailleImeExtensionPath[];
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kBrailleImeEngineId[];
+inline constexpr char kBrailleImeExtensionId[] =
+    "jddehjeebkoimngcbdkaahpobgicbffp";
+inline constexpr char kBrailleImeExtensionPath[] =
+    "chromeos/accessibility/braille_ime";
+inline constexpr char kBrailleImeEngineId[] =
+    "_comp_ime_jddehjeebkoimngcbdkaahpobgicbffpbraille";
 
 // The fake language name used for ARC IMEs.
-COMPONENT_EXPORT(UI_BASE_IME_ASH) extern const char kArcImeLanguage[];
+inline constexpr char kArcImeLanguage[] = "_arc_ime_language_";
 
 // Returns InputMethodID for |engine_id| in |extension_id| of extension IME.
 // This function does not check |extension_id| is installed extension IME nor
@@ -102,7 +116,6 @@
 bool COMPONENT_EXPORT(UI_BASE_IME_ASH)
     IsCros1pKorean(const std::string& input_method_id);
 
-}  // namespace extension_ime_util
-}  // namespace ash
+}  // namespace ash::extension_ime_util
 
 #endif  // UI_BASE_IME_ASH_EXTENSION_IME_UTIL_H_
diff --git a/ui/base/ime/constants.cc b/ui/base/ime/constants.cc
deleted file mode 100644
index 7f64355..0000000
--- a/ui/base/ime/constants.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/ime/constants.h"
-
-namespace ui {
-
-// Here, we define attributes of ui::Event::Properties objects
-// kPropertyFromVK
-const char kPropertyFromVK[] = "from_vk";
-
-// Properties of the kPropertyFromVK attribute
-
-// kFromVKIsMirroring is the index of the isMirrorring property on the
-// kPropertyFromVK attribute. This is non-zero if mirroring and zero if not
-// mirroring
-const size_t kPropertyFromVKIsMirroringIndex = 0;
-// kFromVKSize is the size of the kPropertyFromVK attribute
-// It is equal to the number of kPropertyFromVK
-const size_t kPropertyFromVKSize = 1;
-
-}  // namespace ui
diff --git a/ui/base/ime/constants.h b/ui/base/ime/constants.h
index 83416ff..184d276e 100644
--- a/ui/base/ime/constants.h
+++ b/ui/base/ime/constants.h
@@ -12,16 +12,21 @@
 
 // The name of the property that is attach to the key event and indicates
 // whether it was from the virtual keyboard.
+//
 // This is used where the key event is simulated by the virtual keyboard
 // (e.g. IME extension API) as well as the input field implementation (e.g.
 // Textfield).
-COMPONENT_EXPORT(UI_BASE_IME) extern const char kPropertyFromVK[];
+inline constexpr char kPropertyFromVK[] = "from_vk";
 
-// kPropertyFromVKIsMirroringIndex is an index into kPropertyFromVK
-// and is used when the key event occurs when mirroring is detected.
-COMPONENT_EXPORT(UI_BASE_IME)
-extern const size_t kPropertyFromVKIsMirroringIndex;
-COMPONENT_EXPORT(UI_BASE_IME) extern const size_t kPropertyFromVKSize;
+// Properties of the kPropertyFromVK attribute
+
+// kFromVKIsMirroring is the index of the isMirroring property on the
+// kPropertyFromVK attribute. This is non-zero if mirroring and zero if not
+// mirroring.
+inline constexpr size_t kPropertyFromVKIsMirroringIndex = 0;
+// kFromVKSize is the size of the kPropertyFromVK attribute
+// It is equal to the number of kPropertyFromVK
+inline constexpr size_t kPropertyFromVKSize = 1;
 
 }  // namespace ui
 
diff --git a/ui/base/interaction/interactive_test_internal.cc b/ui/base/interaction/interactive_test_internal.cc
index 1e85867..2f6b01d 100644
--- a/ui/base/interaction/interactive_test_internal.cc
+++ b/ui/base/interaction/interactive_test_internal.cc
@@ -29,9 +29,6 @@
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kInteractiveTestPivotElementId);
 DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kInteractiveTestPivotEventType);
 
-const char kInteractiveTestFailedMessagePrefix[] = "Interactive test failed ";
-const char kNoCheckDescriptionSpecified[] = "[no description specified]";
-
 StateObserverElement::StateObserverElement(ElementIdentifier id,
                                            ElementContext context)
     : TestElementBase(id, context) {}
diff --git a/ui/base/interaction/interactive_test_internal.h b/ui/base/interaction/interactive_test_internal.h
index 21d3c283..9d8bba2 100644
--- a/ui/base/interaction/interactive_test_internal.h
+++ b/ui/base/interaction/interactive_test_internal.h
@@ -55,8 +55,10 @@
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kInteractiveTestPivotElementId);
 DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kInteractiveTestPivotEventType);
 
-extern const char kInteractiveTestFailedMessagePrefix[];
-extern const char kNoCheckDescriptionSpecified[];
+inline constexpr char kInteractiveTestFailedMessagePrefix[] =
+    "Interactive test failed ";
+inline constexpr char kNoCheckDescriptionSpecified[] =
+    "[no description specified]";
 
 class StateObserverElement;
 
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 5d621a2c..6ec0566 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -42,16 +42,6 @@
 // Field trial param name for `kApplyNativeOcclusionToCompositor`.
 const base::FeatureParam<std::string> kApplyNativeOcclusionToCompositorType{
     &kApplyNativeOcclusionToCompositor, "type", /*default=*/""};
-
-// When the WindowTreeHost is occluded or hidden, resources are released and
-// the compositor is hidden. See WindowTreeHost for specifics on what this
-// does.
-const char kApplyNativeOcclusionToCompositorTypeRelease[] = "release";
-// When the WindowTreeHost is occluded the frame rate is throttled.
-const char kApplyNativeOcclusionToCompositorTypeThrottle[] = "throttle";
-// Release when hidden, throttle when occluded.
-const char kApplyNativeOcclusionToCompositorTypeThrottleAndRelease[] =
-    "throttle_and_release";
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -339,21 +329,6 @@
              "ResamplingScrollEventsExperimentalPrediction",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-const char kPredictorNameLsq[] = "lsq";
-const char kPredictorNameKalman[] = "kalman";
-const char kPredictorNameLinearFirst[] = "linear_first";
-const char kPredictorNameLinearSecond[] = "linear_second";
-const char kPredictorNameLinearResampling[] = "linear_resampling";
-const char kPredictorNameEmpty[] = "empty";
-
-const char kFilterNameEmpty[] = "empty_filter";
-const char kFilterNameOneEuro[] = "one_euro_filter";
-
-const char kPredictionTypeFramesBased[] = "frames";
-const char kPredictionTypeDefaultFramesVariation1[] = "0.25";
-const char kPredictionTypeDefaultFramesVariation2[] = "0.375";
-const char kPredictionTypeDefaultFramesVariation3[] = "0.5";
-
 BASE_FEATURE(kSwipeToMoveCursor,
              "SwipeToMoveCursor",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index c50aece..348bb31 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -49,12 +49,19 @@
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::FeatureParam<std::string>
     kApplyNativeOcclusionToCompositorType;
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kApplyNativeOcclusionToCompositorTypeRelease[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kApplyNativeOcclusionToCompositorTypeThrottle[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kApplyNativeOcclusionToCompositorTypeThrottleAndRelease[];
+
+// When the WindowTreeHost is occluded or hidden, resources are released and
+// the compositor is hidden. See WindowTreeHost for specifics on what this
+// does.
+inline constexpr char kApplyNativeOcclusionToCompositorTypeRelease[] =
+    "release";
+// When the WindowTreeHost is occluded the frame rate is throttled.
+inline constexpr char kApplyNativeOcclusionToCompositorTypeThrottle[] =
+    "throttle";
+// Release when hidden, throttle when occluded.
+inline constexpr char
+    kApplyNativeOcclusionToCompositorTypeThrottleAndRelease[] =
+        "throttle_and_release";
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -144,15 +151,12 @@
 // The type of predictor to use for the resampling events. These values are
 // used as the 'predictor' feature param for
 // |blink::features::kResamplingScrollEvents|.
-COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictorNameLsq[];
-COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictorNameKalman[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictorNameLinearFirst[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictorNameLinearSecond[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictorNameLinearResampling[];
-COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictorNameEmpty[];
+inline constexpr char kPredictorNameLsq[] = "lsq";
+inline constexpr char kPredictorNameKalman[] = "kalman";
+inline constexpr char kPredictorNameLinearFirst[] = "linear_first";
+inline constexpr char kPredictorNameLinearSecond[] = "linear_second";
+inline constexpr char kPredictorNameLinearResampling[] = "linear_resampling";
+inline constexpr char kPredictorNameEmpty[] = "empty";
 
 // Enables resampling of scroll events using an experimental latency of +3.3ms
 // instead of the original -5ms.
@@ -161,19 +165,15 @@
 
 // Uses a ratio of the vsync refresh rate. The timing/ratio can be changed on
 // the command line through a `latency` param.
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictionTypeFramesBased[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictionTypeDefaultFramesVariation1[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictionTypeDefaultFramesVariation2[];
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const char kPredictionTypeDefaultFramesVariation3[];
+inline constexpr char kPredictionTypeFramesBased[] = "frames";
+inline constexpr char kPredictionTypeDefaultFramesVariation1[] = "0.25";
+inline constexpr char kPredictionTypeDefaultFramesVariation2[] = "0.375";
+inline constexpr char kPredictionTypeDefaultFramesVariation3[] = "0.5";
 
 // The type of filter to use for filtering events. These values are used as the
 // 'filter' feature param for |blink::features::kFilteringScrollPrediction|.
-COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameEmpty[];
-COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameOneEuro[];
+inline constexpr char kFilterNameEmpty[] = "empty_filter";
+inline constexpr char kFilterNameOneEuro[] = "one_euro_filter";
 
 // Android only feature, for swipe to move cursor.
 COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSwipeToMoveCursor);
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc
deleted file mode 100644
index e7ffbbf..0000000
--- a/ui/base/ui_base_switches.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-#include "ui/base/ui_base_switches.h"
-
-#include "build/build_config.h"
-
-namespace switches {
-
-#if BUILDFLAG(IS_ANDROID)
-// Disable overscroll edge effects like those found in Android views.
-const char kDisableOverscrollEdgeEffect[] = "disable-overscroll-edge-effect";
-
-// Disable the pull-to-refresh effect when vertically overscrolling content.
-const char kDisablePullToRefreshEffect[] = "disable-pull-to-refresh-effect";
-#endif
-
-#if BUILDFLAG(IS_MAC)
-// Disable animations for showing and hiding modal dialogs.
-const char kDisableModalAnimations[] = "disable-modal-animations";
-
-// Show borders around CALayers corresponding to overlays and partial damage.
-const char kShowMacOverlayBorders[] = "show-mac-overlay-borders";
-#endif
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-// Specifies system font family name. Improves determenism when rendering
-// pages in headless mode.
-const char kSystemFontFamily[] = "system-font-family";
-#endif
-
-#if BUILDFLAG(IS_LINUX)
-// Specify the toolkit used to construct the Linux GUI.
-const char kUiToolkitFlag[] = "ui-toolkit";
-// Specify the GTK version to be loaded.
-const char kGtkVersionFlag[] = "gtk-version";
-// Specify the QT version to be loaded.
-const char kQtVersionFlag[] = "qt-version";
-// Disables GTK IME integration.
-const char kDisableGtkIme[] = "disable-gtk-ime";
-#endif
-
-// Disable re-use of non-exact resources to fulfill ResourcePool requests.
-// Intended only for use in layout or pixel tests to reduce noise.
-const char kDisallowNonExactResourceReuse[] =
-    "disallow-non-exact-resource-reuse";
-
-// Treats DRM virtual connector as external to enable display mode change in VM.
-const char kDRMVirtualConnectorIsExternal[] =
-    "drm-virtual-connector-is-external";
-
-// Forces the caption style for WebVTT captions.
-const char kForceCaptionStyle[] = "force-caption-style";
-
-// Forces dark mode in UI for platforms that support it.
-const char kForceDarkMode[] = "force-dark-mode";
-
-// Forces high-contrast mode in native UI drawing, regardless of system
-// settings. Note that this has limited effect on Windows: only Aura colors will
-// be switched to high contrast, not other system colors.
-const char kForceHighContrast[] = "force-high-contrast";
-
-// The language file that we want to try to open. Of the form
-// language[-country] where language is the 2 letter code from ISO-639.
-// On Linux, this flag does not work; use the LC_*/LANG environment variables
-// instead.
-const char kLang[] = "lang";
-
-// Transform localized strings to be longer, with beginning and end markers to
-// make truncation visually apparent.
-const char kMangleLocalizedStrings[] = "mangle-localized-strings";
-
-// Visualize overdraw by color-coding elements based on if they have other
-// elements drawn underneath. This is good for showing where the UI might be
-// doing more rendering work than necessary. The colors are hinting at the
-// amount of overdraw on your screen for each pixel, as follows:
-//
-// True color: No overdraw.
-// Blue: Overdrawn once.
-// Green: Overdrawn twice.
-// Pink: Overdrawn three times.
-// Red: Overdrawn four or more times.
-const char kShowOverdrawFeedback[] = "show-overdraw-feedback";
-
-// Re-draw everything multiple times to simulate a much slower machine.
-// Give a slow down factor to cause renderer to take that many times longer to
-// complete, such as --slow-down-compositing-scale-factor=2.
-const char kSlowDownCompositingScaleFactor[] =
-    "slow-down-compositing-scale-factor";
-
-// Tint composited color.
-const char kTintCompositedContent[] = "tint-composited-content";
-
-// Controls touch-optimized UI layout for top chrome.
-const char kTopChromeTouchUi[] = "top-chrome-touch-ui";
-const char kTopChromeTouchUiAuto[] = "auto";
-const char kTopChromeTouchUiDisabled[] = "disabled";
-const char kTopChromeTouchUiEnabled[] = "enabled";
-
-// Disable partial swap which is needed for some OpenGL drivers / emulators.
-const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
-
-// Enables the ozone x11 clipboard for linux-chromeos.
-const char kUseSystemClipboard[] = "use-system-clipboard";
-
-}  // namespace switches
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h
index 581965d..6502c786 100644
--- a/ui/base/ui_base_switches.h
+++ b/ui/base/ui_base_switches.h
@@ -13,46 +13,103 @@
 namespace switches {
 
 #if BUILDFLAG(IS_ANDROID)
-COMPONENT_EXPORT(UI_BASE) extern const char kDisableOverscrollEdgeEffect[];
-COMPONENT_EXPORT(UI_BASE) extern const char kDisablePullToRefreshEffect[];
+// Disable overscroll edge effects like those found in Android views.
+inline constexpr char kDisableOverscrollEdgeEffect[] =
+    "disable-overscroll-edge-effect";
+
+// Disable the pull-to-refresh effect when vertically overscrolling content.
+inline constexpr char kDisablePullToRefreshEffect[] =
+    "disable-pull-to-refresh-effect";
 #endif
 
 #if BUILDFLAG(IS_MAC)
-COMPONENT_EXPORT(UI_BASE) extern const char kDisableModalAnimations[];
-COMPONENT_EXPORT(UI_BASE) extern const char kShowMacOverlayBorders[];
+// Disable animations for showing and hiding modal dialogs.
+inline constexpr char kDisableModalAnimations[] = "disable-modal-animations";
+
+// Show borders around CALayers corresponding to overlays and partial damage.
+inline constexpr char kShowMacOverlayBorders[] = "show-mac-overlay-borders";
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-COMPONENT_EXPORT(UI_BASE) extern const char kSystemFontFamily[];
+// Specifies system font family name. Improves determinism when rendering pages
+// in headless mode.
+inline constexpr char kSystemFontFamily[] = "system-font-family";
 #endif
 
 #if BUILDFLAG(IS_LINUX)
-COMPONENT_EXPORT(UI_BASE) extern const char kUiToolkitFlag[];
-COMPONENT_EXPORT(UI_BASE) extern const char kGtkVersionFlag[];
-COMPONENT_EXPORT(UI_BASE) extern const char kQtVersionFlag[];
-COMPONENT_EXPORT(UI_BASE) extern const char kDisableGtkIme[];
+// Specify the toolkit used to construct the Linux GUI.
+inline constexpr char kUiToolkitFlag[] = "ui-toolkit";
+// Specify the GTK version to be loaded.
+inline constexpr char kGtkVersionFlag[] = "gtk-version";
+// Specify the QT version to be loaded.
+inline constexpr char kQtVersionFlag[] = "qt-version";
+// Disables GTK IME integration.
+inline constexpr char kDisableGtkIme[] = "disable-gtk-ime";
 #endif
 
-COMPONENT_EXPORT(UI_BASE) extern const char kDisableTouchDragDrop[];
-COMPONENT_EXPORT(UI_BASE) extern const char kDRMVirtualConnectorIsExternal[];
-COMPONENT_EXPORT(UI_BASE) extern const char kEnableTouchDragDrop[];
-COMPONENT_EXPORT(UI_BASE) extern const char kForceCaptionStyle[];
-COMPONENT_EXPORT(UI_BASE) extern const char kForceDarkMode[];
-COMPONENT_EXPORT(UI_BASE) extern const char kForceHighContrast[];
-COMPONENT_EXPORT(UI_BASE) extern const char kLang[];
-COMPONENT_EXPORT(UI_BASE) extern const char kShowOverdrawFeedback[];
-COMPONENT_EXPORT(UI_BASE) extern const char kSlowDownCompositingScaleFactor[];
-COMPONENT_EXPORT(UI_BASE) extern const char kTintCompositedContent[];
-COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUi[];
-COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiAuto[];
-COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiDisabled[];
-COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiEnabled[];
-COMPONENT_EXPORT(UI_BASE) extern const char kUIDisablePartialSwap[];
-COMPONENT_EXPORT(UI_BASE) extern const char kUseSystemClipboard[];
+// Treats DRM virtual connector as external to enable display mode change in VM.
+inline constexpr char kDRMVirtualConnectorIsExternal[] =
+    "drm-virtual-connector-is-external";
+
+// Forces the caption style for WebVTT captions.
+inline constexpr char kForceCaptionStyle[] = "force-caption-style";
+
+// Forces dark mode in UI for platforms that support it.
+inline constexpr char kForceDarkMode[] = "force-dark-mode";
+
+// Forces high-contrast mode in native UI drawing, regardless of system
+// settings. Note that this has limited effect on Windows: only Aura colors will
+// be switched to high contrast, not other system colors.
+inline constexpr char kForceHighContrast[] = "force-high-contrast";
+
+// The language file that we want to try to open. Of the form
+// language[-country] where language is the 2 letter code from ISO-639.
+// On Linux, this flag does not work; use the LC_*/LANG environment variables
+// instead.
+inline constexpr char kLang[] = "lang";
+
+// Visualize overdraw by color-coding elements based on if they have other
+// elements drawn underneath. This is good for showing where the UI might be
+// doing more rendering work than necessary. The colors are hinting at the
+// amount of overdraw on your screen for each pixel, as follows:
+//
+// True color: No overdraw.
+// Blue: Overdrawn once.
+// Green: Overdrawn twice.
+// Pink: Overdrawn three times.
+// Red: Overdrawn four or more times.
+inline constexpr char kShowOverdrawFeedback[] = "show-overdraw-feedback";
+
+// Re-draw everything multiple times to simulate a much slower machine.
+// Give a slow down factor to cause renderer to take that many times longer to
+// complete, such as --slow-down-compositing-scale-factor=2.
+inline constexpr char kSlowDownCompositingScaleFactor[] =
+    "slow-down-compositing-scale-factor";
+
+// Tint composited color.
+inline constexpr char kTintCompositedContent[] = "tint-composited-content";
+
+// Controls touch-optimized UI layout for top chrome.
+inline constexpr char kTopChromeTouchUi[] = "top-chrome-touch-ui";
+inline constexpr char kTopChromeTouchUiAuto[] = "auto";
+inline constexpr char kTopChromeTouchUiDisabled[] = "disabled";
+inline constexpr char kTopChromeTouchUiEnabled[] = "enabled";
+
+// Disable partial swap which is needed for some OpenGL drivers / emulators.
+inline constexpr char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
+
+// Enables the ozone x11 clipboard for linux-chromeos.
+inline constexpr char kUseSystemClipboard[] = "use-system-clipboard";
 
 // Test related.
-COMPONENT_EXPORT(UI_BASE) extern const char kDisallowNonExactResourceReuse[];
-COMPONENT_EXPORT(UI_BASE) extern const char kMangleLocalizedStrings[];
+// Disable re-use of non-exact resources to fulfill ResourcePool requests.
+// Intended only for use in layout or pixel tests to reduce noise.
+inline constexpr char kDisallowNonExactResourceReuse[] =
+    "disallow-non-exact-resource-reuse";
+
+// Transform localized strings to be longer, with beginning and end markers to
+// make truncation visually apparent.
+inline constexpr char kMangleLocalizedStrings[] = "mangle-localized-strings";
 
 }  // namespace switches
 
diff --git a/ui/base/win/internal_constants.cc b/ui/base/win/internal_constants.cc
deleted file mode 100644
index eece3947..0000000
--- a/ui/base/win/internal_constants.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-#include "ui/base/win/internal_constants.h"
-
-namespace ui {
-
-const wchar_t kIgnoreTouchMouseActivateForWindow[] =
-    L"Chrome.IgnoreMouseActivate";
-
-const wchar_t kLegacyRenderWidgetHostHwnd[] = L"Chrome_RenderWidgetHostHWND";
-
-const wchar_t kWindowTranslucent[] = L"Chrome.WindowTranslucent";
-
-}  // namespace ui
-
diff --git a/ui/base/win/internal_constants.h b/ui/base/win/internal_constants.h
index fb5bb04f..3b57ebe 100644
--- a/ui/base/win/internal_constants.h
+++ b/ui/base/win/internal_constants.h
@@ -11,20 +11,19 @@
 
 // This window property if set on the window does not activate the window for a
 // touch based WM_MOUSEACTIVATE message.
-COMPONENT_EXPORT(UI_BASE)
-extern const wchar_t kIgnoreTouchMouseActivateForWindow[];
+inline constexpr wchar_t kIgnoreTouchMouseActivateForWindow[] =
+    L"Chrome.IgnoreMouseActivate";
 
 // This class name is assigned to legacy windows created for screen readers that
 // expect each web content container to be in its own HWNDs.
-COMPONENT_EXPORT(UI_BASE) extern const wchar_t kLegacyRenderWidgetHostHwnd[];
+inline constexpr wchar_t kLegacyRenderWidgetHostHwnd[] =
+    L"Chrome_RenderWidgetHostHWND";
 
 // This property is put on an HWND so the compositor output knows to treat it
 // as transparent and draw to it using WS_EX_LAYERED (if using the software
 // compositor).
-COMPONENT_EXPORT(UI_BASE) extern const wchar_t kWindowTranslucent[];
+inline constexpr wchar_t kWindowTranslucent[] = L"Chrome.WindowTranslucent";
 
 }  // namespace ui
 
 #endif  // UI_BASE_WIN_INTERNAL_CONSTANTS_H_
-
-
diff --git a/ui/base/wm_role_names_linux.cc b/ui/base/wm_role_names_linux.cc
deleted file mode 100644
index 72bde377..0000000
--- a/ui/base/wm_role_names_linux.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/wm_role_names_linux.h"
-
-namespace ui {
-
-const char kStatusIconWmRoleName[] = "status-icon";
-
-}  // namespace ui
diff --git a/ui/base/wm_role_names_linux.h b/ui/base/wm_role_names_linux.h
index 3b861103..f2e7717 100644
--- a/ui/base/wm_role_names_linux.h
+++ b/ui/base/wm_role_names_linux.h
@@ -9,7 +9,7 @@
 
 // Return the status-icon wm_role_name. Only used to construct status-icon
 // windows for x11.
-extern const char kStatusIconWmRoleName[];
+inline constexpr char kStatusIconWmRoleName[] = "status-icon";
 
 }  // namespace ui
 
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc
index 7ae2ba1b..42f85897 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -18,25 +18,21 @@
 
 namespace ui {
 
-const char kIncr[] = "INCR";
-const char kSaveTargets[] = "SAVE_TARGETS";
-const char kTargets[] = "TARGETS";
-
 namespace {
 
-const char kAtomPair[] = "ATOM_PAIR";
-const char kMultiple[] = "MULTIPLE";
-const char kTimestamp[] = "TIMESTAMP";
+constexpr char kAtomPair[] = "ATOM_PAIR";
+constexpr char kMultiple[] = "MULTIPLE";
+constexpr char kTimestamp[] = "TIMESTAMP";
 
 // The period of |incremental_transfer_abort_timer_|. Arbitrary but must be <=
 // than kIncrementalTransferTimeoutMs.
-const int KSelectionOwnerTimerPeriodMs = 1000;
+constexpr int kSelectionOwnerTimerPeriodMs = 1000;
 
 // The amount of time to wait for the selection requestor to process the data
 // sent by the selection owner before aborting an incremental data transfer.
-const int kIncrementalTransferTimeoutMs = 10000;
+constexpr int kIncrementalTransferTimeoutMs = 10000;
 
-static_assert(KSelectionOwnerTimerPeriodMs <= kIncrementalTransferTimeoutMs,
+static_assert(kSelectionOwnerTimerPeriodMs <= kIncrementalTransferTimeoutMs,
               "timer period must be <= transfer timeout");
 
 size_t GetMaxIncrementalTransferSize() {
@@ -250,7 +246,7 @@
       // the data transfer.
       if (!incremental_transfer_abort_timer_.IsRunning()) {
         incremental_transfer_abort_timer_.Start(
-            FROM_HERE, base::Milliseconds(KSelectionOwnerTimerPeriodMs), this,
+            FROM_HERE, base::Milliseconds(kSelectionOwnerTimerPeriodMs), this,
             &SelectionOwner::AbortStaleIncrementalTransfers);
       }
     } else {
diff --git a/ui/base/x/selection_owner.h b/ui/base/x/selection_owner.h
index a4859f8..c952269 100644
--- a/ui/base/x/selection_owner.h
+++ b/ui/base/x/selection_owner.h
@@ -24,9 +24,9 @@
 
 namespace ui {
 
-COMPONENT_EXPORT(UI_BASE_X) extern const char kIncr[];
-COMPONENT_EXPORT(UI_BASE_X) extern const char kSaveTargets[];
-COMPONENT_EXPORT(UI_BASE_X) extern const char kTargets[];
+inline constexpr char kIncr[] = "INCR";
+inline constexpr char kSaveTargets[] = "SAVE_TARGETS";
+inline constexpr char kTargets[] = "TARGETS";
 
 // Owns a specific X11 selection on an X window.
 //
diff --git a/ui/base/x/x11_drag_drop_client.cc b/ui/base/x/x11_drag_drop_client.cc
index f1c4300..ef2a3efc 100644
--- a/ui/base/x/x11_drag_drop_client.cc
+++ b/ui/base/x/x11_drag_drop_client.cc
@@ -33,19 +33,6 @@
 
 namespace ui {
 
-// Window property on the source window and message used by the XDS protocol.
-// This atom name intentionally includes the XDS protocol version (0).
-// After the source sends the XdndDrop message, this property stores the
-// (path-less) name of the file to be saved, and has the type text/plain, with
-// an optional charset attribute.
-// When receiving an XdndDrop event, the target needs to check for the
-// XdndDirectSave property on the source window. The target then modifies the
-// XdndDirectSave on the source window, and sends an XdndDirectSave message to
-// the source.
-// After the target sends the XdndDirectSave message, this property stores an
-// URL indicating the location where the source should save the file.
-const char kXdndDirectSave0[] = "XdndDirectSave0";
-
 namespace {
 
 using mojom::DragOperation;
@@ -66,47 +53,47 @@
 constexpr int kMaxXdndVersion = 5;
 
 // Window property that tells other applications the window understands XDND.
-const char kXdndAware[] = "XdndAware";
+constexpr char kXdndAware[] = "XdndAware";
 
 // Window property that holds the supported drag and drop data types.
 // This property is set on the XDND source window when the drag and drop data
 // can be converted to more than 3 types.
-const char kXdndTypeList[] = "XdndTypeList";
+constexpr char kXdndTypeList[] = "XdndTypeList";
 
 // These actions have the same meaning as in the W3C Drag and Drop spec.
-const char kXdndActionCopy[] = "XdndActionCopy";
-const char kXdndActionMove[] = "XdndActionMove";
-const char kXdndActionLink[] = "XdndActionLink";
+constexpr char kXdndActionCopy[] = "XdndActionCopy";
+constexpr char kXdndActionMove[] = "XdndActionMove";
+constexpr char kXdndActionLink[] = "XdndActionLink";
 
 // Triggers the XDS protocol.
-const char kXdndActionDirectSave[] = "XdndActionDirectSave";
+constexpr char kXdndActionDirectSave[] = "XdndActionDirectSave";
 
 // Window property that contains the possible actions that will be presented to
 // the user when the drag and drop action is kXdndActionAsk.
-const char kXdndActionList[] = "XdndActionList";
+constexpr char kXdndActionList[] = "XdndActionList";
 
 // Window property pointing to a proxy window to receive XDND target messages.
 // The XDND source must check the proxy window must for the XdndAware property,
 // and must send all XDND messages to the proxy instead of the target. However,
 // the target field in the messages must still represent the original target
 // window (the window pointed to by the cursor).
-const char kXdndProxy[] = "XdndProxy";
+constexpr char kXdndProxy[] = "XdndProxy";
 
 // Message sent from an XDND source to the target when the user confirms the
 // drag and drop operation.
-const char kXdndDrop[] = "XdndDrop";
+constexpr char kXdndDrop[] = "XdndDrop";
 
 // Message sent from an XDND source to the target to start the XDND protocol.
 // The target must wait for an XDndPosition event before querying the data.
-const char kXdndEnter[] = "XdndEnter";
+constexpr char kXdndEnter[] = "XdndEnter";
 
 // Message sent from an XDND target to the source in response to an XdndDrop.
 // The message must be sent whether the target acceepts the drop or not.
-const char kXdndFinished[] = "XdndFinished";
+constexpr char kXdndFinished[] = "XdndFinished";
 
 // Message sent from an XDND source to the target when the user cancels the drag
 // and drop operation.
-const char kXdndLeave[] = "XdndLeave";
+constexpr char kXdndLeave[] = "XdndLeave";
 
 // Message sent by the XDND source when the cursor position changes.
 // The source will also send an XdndPosition event right after the XdndEnter
@@ -116,12 +103,12 @@
 // information.
 // After the target optionally acquires selection information, it must tell the
 // source if it can accept the drop via an XdndStatus message.
-const char kXdndPosition[] = "XdndPosition";
+constexpr char kXdndPosition[] = "XdndPosition";
 
 // Message sent by the XDND target in response to an XdndPosition message.
 // The message informs the source if the target will accept the drop, and what
 // action will be taken if the drop is accepted.
-const char kXdndStatus[] = "XdndStatus";
+constexpr char kXdndStatus[] = "XdndStatus";
 
 std::map<x11::Window, XDragDropClient*>& GetLiveClientMap() {
   static base::NoDestructor<std::map<x11::Window, XDragDropClient*>> map;
diff --git a/ui/base/x/x11_drag_drop_client.h b/ui/base/x/x11_drag_drop_client.h
index f9379a2..2959ba2 100644
--- a/ui/base/x/x11_drag_drop_client.h
+++ b/ui/base/x/x11_drag_drop_client.h
@@ -22,7 +22,18 @@
 class OSExchangeData;
 class XOSExchangeDataProvider;
 
-extern const char kXdndDirectSave0[];
+// Window property on the source window and message used by the XDS protocol.
+// This atom name intentionally includes the XDS protocol version (0).
+// After the source sends the XdndDrop message, this property stores the
+// (path-less) name of the file to be saved, and has the type text/plain, with
+// an optional charset attribute.
+// When receiving an XdndDrop event, the target needs to check for the
+// XdndDirectSave property on the source window. The target then modifies the
+// XdndDirectSave on the source window, and sends an XdndDirectSave message to
+// the source.
+// After the target sends the XdndDirectSave message, this property stores an
+// URL indicating the location where the source should save the file.
+inline constexpr char kXdndDirectSave0[] = "XdndDirectSave0";
 
 // Converts the current set of X masks into the set of ui::EventFlags.
 COMPONENT_EXPORT(UI_BASE_X) int XGetMaskAsEventFlags();
diff --git a/ui/compositor/compositor_animation_observer.cc b/ui/compositor/compositor_animation_observer.cc
index 44fca12..6323dfa 100644
--- a/ui/compositor/compositor_animation_observer.cc
+++ b/ui/compositor/compositor_animation_observer.cc
@@ -62,10 +62,9 @@
     TRACE_EVENT_BEGIN("ui", "LongCompositorAnimationObserved",
                       perfetto::ThreadTrack::Current(), *start_);
     TRACE_EVENT_END("ui");
-    LOG(DFATAL_OR_WARNING)
-        << "CompositorAnimationObserver is active for too long ("
-        << (base::TimeTicks::Now() - *start_).InSecondsF()
-        << "s) location=" << location_.ToString();
+    LOG(ERROR) << "CompositorAnimationObserver is active for too long ("
+               << (base::TimeTicks::Now() - *start_).InSecondsF()
+               << "s) location=" << location_.ToString();
   }
 }
 
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 1a7b1e3..4c93aa57 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -669,7 +669,10 @@
       "mac/io_surface.h",
     ]
 
-    public_deps += [ "//ui/gfx:color_space" ]
+    public_deps += [
+      "//components/viz/common:shared_image_format",
+      "//ui/gfx:color_space",
+    ]
   }
 
   if (is_win) {
diff --git a/ui/gfx/DEPS b/ui/gfx/DEPS
index a7eb37a..a890c87 100644
--- a/ui/gfx/DEPS
+++ b/ui/gfx/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+base",
+  "+components/viz/common/resources/shared_image_format.h",
   "+cc/base",
   "+cc/paint",
   "+device/vr/buildflags/buildflags.h",
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index bfb59ff..29c23a28 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -11,6 +11,7 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/compiler_specific.h"
+#include "base/debug/crash_logging.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/notreached.h"
@@ -110,9 +111,15 @@
     SetCustomTransferFunction(fn, is_hdr);
   } else if (skcms_TransferFunction_isHLGish(&fn)) {
     transfer_ = TransferID::HLG;
+    transfer_params_[0] = 203.f;
+    transfer_params_[1] = 1000.f;
+    transfer_params_[2] = 1.2f;
   } else if (skcms_TransferFunction_isPQish(&fn)) {
     transfer_ = TransferID::PQ;
     transfer_params_[0] = GetSDRWhiteLevelFromPQSkTransferFunction(fn);
+    if (transfer_params_[0] == 10000.f) {
+      transfer_params_[0] = 203.f;
+    }
   } else if (skcms_TransferFunction_isHLG(&fn)) {
     transfer_ = TransferID::HLG;
     transfer_params_[0] = fn.a;
@@ -1127,6 +1134,9 @@
 }
 
 bool ColorSpace::ToSkYUVColorSpace(int bit_depth, SkYUVColorSpace* out) const {
+  // There should be no usages of RGB matrix for YUV conversion.
+  SCOPED_CRASH_KEY_STRING32("ToSkYUVColorSpace", "ColorSpace", ToString());
+  CHECK(matrix_ != gfx::ColorSpace::MatrixID::RGB, base::NotFatalUntil::M141);
   switch (matrix_) {
     case MatrixID::BT709:
       *out = range_ == RangeID::FULL ? kRec709_Full_SkYUVColorSpace
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index c69eb36..c209fd97 100644
--- a/ui/gfx/mac/io_surface.cc
+++ b/ui/gfx/mac/io_surface.cc
@@ -22,6 +22,7 @@
 #include "base/mac/mac_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
+#include "components/viz/common/resources/shared_image_format.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/icc_profile.h"
@@ -39,92 +40,43 @@
   CFDictionaryAddValue(dictionary, key, number.get());
 }
 
-int32_t BytesPerElement(gfx::BufferFormat format, int plane) {
-  switch (format) {
-    case gfx::BufferFormat::R_8:
-      DCHECK_EQ(plane, 0);
-      return 1;
-    case gfx::BufferFormat::R_16:
-      DCHECK_EQ(plane, 0);
-      return 2;
-    case gfx::BufferFormat::RG_88:
-      DCHECK_EQ(plane, 0);
-      return 2;
-    case gfx::BufferFormat::RG_1616:
-      DCHECK_EQ(plane, 0);
-      return 4;
-    case gfx::BufferFormat::BGRA_8888:
-    case gfx::BufferFormat::BGRX_8888:
-    case gfx::BufferFormat::RGBA_8888:
-    case gfx::BufferFormat::RGBX_8888:
-    case gfx::BufferFormat::BGRA_1010102:
-      DCHECK_EQ(plane, 0);
-      return 4;
-    case gfx::BufferFormat::RGBA_F16:
-      DCHECK_EQ(plane, 0);
-      return 8;
-    case gfx::BufferFormat::YUV_420_BIPLANAR: {
-      constexpr int32_t bytes_per_element[] = {1, 2};
-      DCHECK_LT(static_cast<size_t>(plane), std::size(bytes_per_element));
-      return bytes_per_element[plane];
-    }
-    case gfx::BufferFormat::YUVA_420_TRIPLANAR: {
-      constexpr int32_t bytes_per_element[] = {1, 2, 1};
-      DCHECK_LT(static_cast<size_t>(plane), std::size(bytes_per_element));
-      return bytes_per_element[plane];
-    }
-    case gfx::BufferFormat::P010: {
-      constexpr int32_t bytes_per_element[] = {2, 4};
-      DCHECK_LT(static_cast<size_t>(plane), std::size(bytes_per_element));
-      return bytes_per_element[plane];
-    }
-    case gfx::BufferFormat::BGR_565:
-    case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBA_1010102:
-    case gfx::BufferFormat::YVU_420:
-      NOTREACHED();
+// Return the expected four character code pixel format for an IOSurface with
+// the specified viz::SharedImageFormat.
+uint32_t SharedImageFormatToIOSurfacePixelFormat(viz::SharedImageFormat format,
+                                                 bool override_rgba_to_bgra) {
+  if (format == viz::SinglePlaneFormat::kR_8) {
+    return 'L008';
+  } else if (format == viz::SinglePlaneFormat::kRG_88) {
+    return '2C08';
+  } else if (format == viz::SinglePlaneFormat::kR_16) {
+    return 'L016';
+  } else if (format == viz::SinglePlaneFormat::kRG_1616) {
+    return '2C16';
+  } else if (format == viz::SinglePlaneFormat::kBGRA_1010102) {
+    return 'l10r';  // little-endian ARGB2101010 full-range ARGB
+  } else if (format == viz::SinglePlaneFormat::kBGRA_8888 ||
+             format == viz::SinglePlaneFormat::kBGRX_8888) {
+    return 'BGRA';
+  } else if (format == viz::SinglePlaneFormat::kRGBA_8888 ||
+             format == viz::SinglePlaneFormat::kRGBX_8888) {
+    return override_rgba_to_bgra ? 'BGRA' : 'RGBA';
+  } else if (format == viz::SinglePlaneFormat::kRGBA_F16) {
+    return 'RGhA';
+  } else if (format == viz::MultiPlaneFormat::kNV12) {
+    return '420v';
+  } else if (format == viz::MultiPlaneFormat::kNV12A) {
+    return 'v0a8';
+  } else if (format == viz::MultiPlaneFormat::kP010) {
+    return 'x420';
+  } else {
+    // Technically RGBA_1010102 should be accepted as 'R10k', but then it won't
+    // be supported by CGLTexImageIOSurface2D(), so it's best to reject it here.
+    NOTREACHED();
   }
 }
 
 }  // namespace
 
-uint32_t BufferFormatToIOSurfacePixelFormat(gfx::BufferFormat format,
-                                            bool override_rgba_to_bgra) {
-  switch (format) {
-    case gfx::BufferFormat::R_8:
-      return 'L008';
-    case gfx::BufferFormat::RG_88:
-      return '2C08';
-    case gfx::BufferFormat::R_16:
-      return 'L016';
-    case gfx::BufferFormat::RG_1616:
-      return '2C16';
-    case gfx::BufferFormat::BGRA_1010102:
-      return 'l10r';  // little-endian ARGB2101010 full-range ARGB
-    case gfx::BufferFormat::BGRA_8888:
-    case gfx::BufferFormat::BGRX_8888:
-      return 'BGRA';
-    case gfx::BufferFormat::RGBA_8888:
-    case gfx::BufferFormat::RGBX_8888:
-      return override_rgba_to_bgra ? 'BGRA' : 'RGBA';
-    case gfx::BufferFormat::RGBA_F16:
-      return 'RGhA';
-    case gfx::BufferFormat::YUV_420_BIPLANAR:
-      return '420v';
-    case gfx::BufferFormat::YUVA_420_TRIPLANAR:
-      return 'v0a8';
-    case gfx::BufferFormat::P010:
-      return 'x420';
-    case gfx::BufferFormat::BGR_565:
-    case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBA_1010102:
-    // Technically RGBA_1010102 should be accepted as 'R10k', but then it won't
-    // be supported by CGLTexImageIOSurface2D(), so it's best to reject it here.
-    case gfx::BufferFormat::YVU_420:
-      return 0;
-  }
-}
-
 namespace internal {
 
 // static
@@ -234,7 +186,7 @@
 }  // namespace internal
 
 ScopedIOSurface CreateIOSurface(const gfx::Size& size,
-                                gfx::BufferFormat format,
+                                viz::SharedImageFormat format,
                                 bool should_clear,
                                 bool override_rgba_to_bgra) {
   TRACE_EVENT0("ui", "CreateIOSurface");
@@ -248,22 +200,25 @@
   AddIntegerValue(properties.get(), kIOSurfaceHeight, size.height());
   AddIntegerValue(
       properties.get(), kIOSurfacePixelFormat,
-      BufferFormatToIOSurfacePixelFormat(format, override_rgba_to_bgra));
+      SharedImageFormatToIOSurfacePixelFormat(format, override_rgba_to_bgra));
 
   // Don't specify plane information unless there are indeed multiple planes
   // because DisplayLink drivers do not support this.
   // http://crbug.com/527556
-  size_t num_planes = gfx::NumberOfPlanesForLinearBufferFormat(format);
+  size_t num_planes = format.NumberOfPlanes();
   if (num_planes > 1) {
     base::apple::ScopedCFTypeRef<CFMutableArrayRef> planes(CFArrayCreateMutable(
         kCFAllocatorDefault, num_planes, &kCFTypeArrayCallBacks));
     size_t total_bytes_alloc = 0;
     for (size_t plane = 0; plane < num_planes; ++plane) {
-      const size_t factor =
-          gfx::SubsamplingFactorForBufferFormat(format, plane);
-      const size_t plane_width = (size.width() + factor - 1) / factor;
-      const size_t plane_height = (size.height() + factor - 1) / factor;
-      const size_t plane_bytes_per_element = BytesPerElement(format, plane);
+      const gfx::Size plane_size = format.GetPlaneSize(plane, size);
+      const size_t plane_width = plane_size.width();
+      const size_t plane_height = plane_size.height();
+      size_t plane_bytes_per_element = format.NumChannelsInPlane(plane);
+      if (format.channel_format() !=
+          viz::SharedImageFormat::ChannelFormat::k8) {
+        plane_bytes_per_element *= 2;
+      }
       const size_t plane_bytes_per_row =
           IOSurfaceAlignProperty(kIOSurfacePlaneBytesPerRow,
                                  base::bits::AlignUp(plane_width, size_t{2}) *
@@ -295,7 +250,7 @@
         IOSurfaceAlignProperty(kIOSurfaceAllocSize, total_bytes_alloc);
     AddIntegerValue(properties.get(), kIOSurfaceAllocSize, total_bytes_alloc);
   } else {
-    const size_t bytes_per_element = BytesPerElement(format, 0);
+    const size_t bytes_per_element = format.BitsPerPixel() / 8;
     const size_t bytes_per_row = IOSurfaceAlignProperty(
         kIOSurfaceBytesPerRow,
         base::bits::AlignUp(static_cast<size_t>(size.width()), size_t{2}) *
diff --git a/ui/gfx/mac/io_surface.h b/ui/gfx/mac/io_surface.h
index 630b8301..a002637 100644
--- a/ui/gfx/mac/io_surface.h
+++ b/ui/gfx/mac/io_surface.h
@@ -16,6 +16,10 @@
 #include "ui/gfx/generic_shared_memory_id.h"
 #include "ui/gfx/geometry/size.h"
 
+namespace viz {
+class SharedImageFormat;
+}
+
 namespace gfx {
 
 namespace internal {
@@ -67,14 +71,14 @@
 // The surface is zero-initialized if |should_clear| is true. This is not
 // necessary for anonymous surfaces that are not exported to renderers and used
 // as render targets only. If |override_rgba_to_bgra| is true (default) a BGRA
-// IOSurface is created for RGBA/X_8888 BufferFormat. This is needed for GL
+// IOSurface is created for RGBA/X_8888 format. This is needed for GL
 // usage since neither ANGLE Metal nor CGL support importing RGBA IOSurfaces,
 // whereas for non-GL backends (Dawn and Metal) we want the formats to match.
 // TODO(sunnyps): Revisit this when we switch to ANGLE Metal completely since
 // wrapping RGBA_8888 can be implemented with Metal quite easily.
 COMPONENT_EXPORT(GFX)
 ScopedIOSurface CreateIOSurface(const Size& size,
-                                BufferFormat format,
+                                viz::SharedImageFormat format,
                                 bool should_clear = true,
 #if BUILDFLAG(IS_IOS)
                                 bool override_rgba_to_bgra = false
@@ -103,12 +107,6 @@
 void IOSurfaceSetColorSpace(IOSurfaceRef io_surface,
                             const gfx::ColorSpace& color_space);
 
-// Return the expected four character code pixel format for an IOSurface with
-// the specified gfx::BufferFormat.
-COMPONENT_EXPORT(GFX)
-uint32_t BufferFormatToIOSurfacePixelFormat(gfx::BufferFormat format,
-                                            bool override_rgba_to_bgra = true);
-
 // Return an IOSurface consuming |io_surface_mach_port|.
 COMPONENT_EXPORT(GFX)
 ScopedIOSurface IOSurfaceMachPortToIOSurface(
diff --git a/ui/gfx/mac/io_surface_unittest.cc b/ui/gfx/mac/io_surface_unittest.cc
index 7d301f5..51d4439 100644
--- a/ui/gfx/mac/io_surface_unittest.cc
+++ b/ui/gfx/mac/io_surface_unittest.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "ui/gfx/mac/io_surface.h"
+
+#include "components/viz/common/resources/shared_image_format.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gfx {
@@ -11,7 +13,7 @@
 
 TEST(IOSurface, OddSizeMultiPlanar) {
   base::apple::ScopedCFTypeRef<IOSurfaceRef> io_surface =
-      CreateIOSurface(gfx::Size(101, 99), gfx::BufferFormat::YUV_420_BIPLANAR);
+      CreateIOSurface(gfx::Size(101, 99), viz::MultiPlaneFormat::kNV12);
   DCHECK(io_surface);
   // Plane sizes are rounded up.
   // https://crbug.com/1226056
diff --git a/ui/resources/ui_lottie_resources.grd b/ui/resources/ui_lottie_resources.grd
index 407e3b5..0d54445 100644
--- a/ui/resources/ui_lottie_resources.grd
+++ b/ui/resources/ui_lottie_resources.grd
@@ -12,6 +12,7 @@
         <structure type="lottie" name="IDR_AURA_CURSOR_PTR_LOTTIE" file="vector/common/pointers/left_ptr.json" compress="gzip" />
         <structure type="lottie" name="IDR_AURA_CURSOR_ALIAS_LOTTIE" file="vector/common/pointers/alias.json" compress="gzip" />
         <structure type="lottie" name="IDR_AURA_CURSOR_CELL_LOTTIE" file="vector/common/pointers/cell.json" compress="gzip" />
+        <structure type="lottie" name="IDR_AURA_CURSOR_COPY_LOTTIE" file="vector/common/pointers/copy.json" compress="gzip" />
         <structure type="lottie" name="IDR_AURA_CURSOR_IBEAM_LOTTIE" file="vector/common/pointers/xterm.json" compress="gzip" />
         <structure type="lottie" name="IDR_AURA_CURSOR_THROBBER_LOTTIE" file="vector/common/pointers/throbber.json" compress="gzip" />
       </if>
diff --git a/ui/resources/vector/common/pointers/copy.json b/ui/resources/vector/common/pointers/copy.json
new file mode 100644
index 0000000..3993df6
--- /dev/null
+++ b/ui/resources/vector/common/pointers/copy.json
@@ -0,0 +1 @@
+{"v":"5.9.3","fr":60,"ip":0,"op":120,"w":25,"h":25,"nm":"31","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"31 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12.5,12.5,0],"ix":2,"l":2},"a":{"a":0,"k":[12.5,12.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":51,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":171,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":1,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":1,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":51,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":171,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":1,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.5,-0.5],[2.5,-0.5],[2.5,0.5],[0.5,0.5],[0.5,2.5],[-0.5,2.5],[-0.5,0.5],[-2.5,0.5],[-2.5,-0.5],[-0.5,-0.5],[-0.5,-2.5],[0.5,-2.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.999998863071,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[18.037,7.71],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.485,0],[0,-2.485],[2.485,0],[0,2.485]],"o":[[2.485,0],[0,2.485],[-2.485,0],[0,-2.485]],"v":[[0,-4.5],[4.5,0],[0,4.5],[-4.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.222633780685,0.583897729013,0.345252512016,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[18.037,7.71],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.038,0],[0,-3.038],[3.038,0],[0,3.038]],"o":[[3.038,0],[0,3.038],[-3.038,0],[0,-3.038]],"v":[[0,-5.5],[5.5,0],[0,5.5],[-5.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.999998863071,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[18.037,7.71],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.599,-0.373],[0,0],[0,0],[-0.363,-0.484],[0,0],[-0.214,-0.28],[0,0],[0,0],[0,0],[-1.178,-1.419],[0,0],[-0.373,0],[0,0],[-0.021,0.022],[-0.298,0.55],[-1.048,4.087],[0,0],[0,0],[0.479,0.123],[0,0],[0,0],[0.125,-0.285],[0,0],[0.066,-0.288],[0.021,-0.084],[0.007,-0.027],[0.011,-0.027],[0.01,-0.022],[0.015,-0.024],[0.067,-0.052],[0.252,0.127],[0.008,0.024],[0,0],[0,0],[0.662,0],[0,0],[0.074,-0.597],[0,0],[0,0],[0.006,-0.035],[0.005,-0.017],[0.03,-0.057],[0.092,-0.068],[0.068,-0.014],[0.064,0.025],[0.016,0.028],[0.005,0.017],[0.002,0.009],[0.001,0.006],[0.001,0.006],[0.001,0.047],[0.001,0.22],[-0.001,0.587],[0,0],[0.623,0],[0,0],[0.073,-0.6],[0,0],[0.012,-0.409],[0,0],[0.003,-0.028],[0.007,-0.031],[0.03,-0.059],[0.106,-0.074],[0.118,-0.003],[0.068,0.045],[0.01,0.022],[0.004,0.015],[0.001,0.01],[0.001,0.012],[0.001,0.03],[0.001,0.27],[-0.005,0.709],[0,0],[0.625,0],[0,0],[0,-0.662]],"o":[[0,0],[-0.494,-0.522],[0,0],[0,0],[-0.466,0.355],[0,0],[0.211,0.28],[0,0],[0,0],[0,0],[0.939,2.307],[0,0],[0.254,0.242],[0,0],[0.016,-0.014],[0.128,-0.135],[0.594,-1.102],[0,0],[0,0],[0.053,-0.491],[0,0],[0,0],[-0.318,-0.047],[0,0],[-0.081,0.361],[-0.033,0.144],[-0.01,0.041],[-0.002,0.009],[-0.002,0.007],[-0.005,0.01],[-0.01,0.015],[-0.065,0.05],[-0.19,-0.095],[-0.027,-0.083],[0,0],[0,-0.663],[0,0],[-0.612,0],[0,0],[0,0],[0,0.008],[-0.001,0.008],[-0.001,0.008],[-0.012,0.024],[-0.047,0.031],[-0.076,0.004],[-0.137,-0.065],[-0.024,-0.041],[-0.012,-0.034],[-0.002,-0.013],[-0.001,-0.013],[-0.002,-0.032],[-0.001,-0.108],[0,-0.444],[0,0],[-0.06,-0.608],[0,0],[-0.614,0],[0,0],[-0.009,0.437],[0,0],[-0.002,0.033],[-0.001,0.01],[-0.001,0.007],[-0.01,0.021],[-0.062,0.043],[-0.12,0.002],[-0.116,-0.077],[-0.018,-0.036],[-0.009,-0.03],[-0.004,-0.023],[-0.002,-0.026],[-0.004,-0.12],[-0.001,-0.544],[0,0],[-0.058,-0.611],[0,0],[-0.662,0],[0,0]],"v":[[-4.809,-0.954],[-6.807,-3.062],[-8.688,-3.305],[-8.805,-3.224],[-9.376,-2.787],[-9.576,-1.237],[-8.396,0.334],[-7.757,1.177],[-7.122,1.996],[-7.079,2.051],[-7.051,2.116],[-4.15,7.256],[-4.046,7.365],[-3.07,7.742],[6.089,7.742],[6.146,7.691],[6.794,6.726],[9.309,-0.599],[9.87,-3.188],[9.885,-3.294],[9.143,-4.368],[9.038,-4.389],[8.574,-4.458],[7.827,-4.045],[7.786,-3.916],[7.553,-2.883],[7.471,-2.533],[7.445,-2.429],[7.424,-2.366],[7.404,-2.319],[7.374,-2.265],[7.26,-2.142],[6.73,-2.091],[6.479,-2.382],[6.454,-2.539],[6.454,-4.823],[5.255,-6.023],[4.71,-6.023],[3.516,-4.966],[3.507,-4.845],[3.48,-3.876],[3.473,-3.794],[3.464,-3.755],[3.421,-3.639],[3.275,-3.466],[3.044,-3.372],[2.762,-3.416],[2.546,-3.615],[2.503,-3.708],[2.486,-3.78],[2.48,-3.809],[2.477,-3.838],[2.473,-3.97],[2.471,-4.478],[2.473,-6.13],[2.467,-6.253],[1.273,-7.336],[0.516,-7.336],[-0.68,-6.274],[-0.689,-6.152],[-0.721,-4.84],[-0.758,-3.868],[-0.766,-3.774],[-0.777,-3.706],[-0.82,-3.588],[-0.982,-3.399],[-1.255,-3.31],[-1.544,-3.393],[-1.717,-3.594],[-1.749,-3.676],[-1.764,-3.742],[-1.77,-3.798],[-1.773,-3.884],[-1.779,-4.493],[-1.771,-6.529],[-1.777,-6.653],[-2.973,-7.742],[-3.609,-7.742],[-4.809,-6.542]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.999998863071,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[12.153,14.234],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.382,-0.651],[-0.626,0],[0,0],[-0.215,-0.989],[-0.481,0],[0,0],[-0.141,-1.079],[-0.474,-0.07],[0,0],[0,0],[0.105,-0.983],[0,0],[0,0],[0,0],[0,0],[0.651,-1.205],[0.207,-0.217],[0.076,-0.052],[0.031,-0.016],[0.013,-0.005],[0.006,-0.002],[0.003,-0.001],[0,0],[0,0],[0,0],[0,0],[0,0],[0.459,0.491],[0,0],[0.952,2.329],[0.41,0.543],[0,0],[-0.918,0.7],[0,0],[0,0],[-0.824,-0.869],[0,0],[0,0],[-1.215,0]],"o":[[0.81,0],[0.402,-0.421],[0,0],[1.055,0],[0.363,-0.262],[0,0],[1.117,0],[0.354,-0.273],[0,0],[0,0],[0.957,0.248],[0,0],[0,0],[0,0],[0,0],[-1.06,4.136],[-0.325,0.604],[-0.104,0.109],[-0.038,0.026],[-0.016,0.008],[-0.007,0.003],[-0.003,0.001],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.656,0],[0,0],[-1.254,-1.51],[-0.405,-0.518],[0,0],[-0.682,-0.907],[0,0],[0,0],[0.998,-0.622],[0,0],[0,0],[0,-1.215],[0,0]],"v":[[-2.938,-8.742],[-1.041,-7.652],[0.551,-8.336],[1.308,-8.336],[3.457,-6.605],[4.745,-7.023],[5.29,-7.023],[7.468,-5.111],[8.755,-5.447],[9.221,-5.378],[9.43,-5.336],[10.916,-3.188],[10.881,-2.977],[10.322,-0.387],[10.32,-0.377],[10.318,-0.368],[7.708,7.2],[6.906,8.381],[6.635,8.617],[6.532,8.68],[6.488,8.7],[6.468,8.708],[6.459,8.711],[6.455,8.713],[6.453,8.714],[6.451,8.715],[6.371,8.742],[-3.034,8.742],[-4.793,7.995],[-4.883,7.895],[-7.917,2.557],[-9.16,0.937],[-10.339,-0.637],[-9.948,-3.583],[-9.375,-4.019],[-9.18,-4.154],[-6.045,-3.75],[-5.773,-3.463],[-5.773,-6.542],[-3.574,-8.742]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[12.118,14.234],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/ui/tests/BUILD.gn b/ui/tests/BUILD.gn
index bc01c58..5798ea0c 100644
--- a/ui/tests/BUILD.gn
+++ b/ui/tests/BUILD.gn
@@ -11,6 +11,7 @@
   deps = [
     "//base/test:test_support",
     "//testing/gtest",
+    "//ui/anchor:unit_tests",
     "//ui/base",
     "//ui/color:unit_tests",
     "//ui/menus:unit_tests",
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index b7716b3..3885f2e 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -94,6 +94,7 @@
     "accessible_pane_view.h",
     "actions/action_view_controller.h",
     "actions/action_view_interface.h",
+    "anchor/view_anchor.h",
     "animation/animation_abort_handle.h",
     "animation/animation_builder.h",
     "animation/animation_delegate_views.h",
@@ -345,6 +346,7 @@
     "accessible_pane_view.cc",
     "actions/action_view_controller.cc",
     "actions/action_view_interface.cc",
+    "anchor/view_anchor.cc",
     "animation/animation_abort_handle.cc",
     "animation/animation_builder.cc",
     "animation/animation_delegate_views.cc",
@@ -575,6 +577,7 @@
     "//ui/accessibility",
     "//ui/accessibility/platform",
     "//ui/actions",
+    "//ui/anchor:impl",
     "//ui/base/clipboard",
     "//ui/base/dragdrop/mojom",
     "//ui/base/emoji",
@@ -603,6 +606,7 @@
     "//components/vector_icons",
     "//third_party/abseil-cpp:absl",
     "//ui/accessibility:ax_enums_mojo",
+    "//ui/anchor",
     "//ui/base",
     "//ui/base/clipboard",
     "//ui/base/cursor",
@@ -1220,6 +1224,7 @@
     "accessibility/accessibility_paint_checks_unittest.cc",
     "accessible_pane_view_unittest.cc",
     "actions/action_view_controller_unittest.cc",
+    "anchor/view_anchor_unittest.cc",
     "animation/animation_builder_unittest.cc",
     "animation/bounds_animator_unittest.cc",
     "animation/bubble_slide_animator_unittest.cc",
diff --git a/ui/views/anchor/view_anchor.cc b/ui/views/anchor/view_anchor.cc
new file mode 100644
index 0000000..1f008f8
--- /dev/null
+++ b/ui/views/anchor/view_anchor.cc
@@ -0,0 +1,49 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/anchor/view_anchor.h"
+
+#include <memory>
+
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+ViewAnchorImpl::ViewAnchorImpl(View* anchor_view)
+    : view_tracker_(anchor_view) {}
+
+ViewAnchorImpl::~ViewAnchorImpl() = default;
+
+std::unique_ptr<ui::AnchorImpl> ViewAnchorImpl::Clone() const {
+  return std::make_unique<ViewAnchorImpl>(const_cast<View*>(view()));
+}
+
+bool ViewAnchorImpl::IsEmpty() const {
+  return view() == nullptr;
+}
+
+gfx::Rect ViewAnchorImpl::GetScreenBounds() const {
+  return view() ? view()->GetAnchorBoundsInScreen() : gfx::Rect();
+}
+
+Widget* ViewAnchorImpl::GetWidget() {
+  return view() ? view()->GetWidget() : nullptr;
+}
+
+bool ViewAnchorImpl::IsView() const {
+  return true;
+}
+
+views::View* ViewAnchorImpl::GetView() {
+  return view();
+}
+
+}  // namespace views
+
+namespace ui {
+
+Anchor::Anchor(views::View* anchor_view)
+    : impl_(std::make_unique<views::ViewAnchorImpl>(anchor_view)) {}
+
+}  // namespace ui
diff --git a/ui/views/anchor/view_anchor.h b/ui/views/anchor/view_anchor.h
new file mode 100644
index 0000000..bef55796
--- /dev/null
+++ b/ui/views/anchor/view_anchor.h
@@ -0,0 +1,40 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANCHOR_VIEW_ANCHOR_H_
+#define UI_VIEWS_ANCHOR_VIEW_ANCHOR_H_
+
+#include <memory>
+
+#include "base/memory/raw_ptr.h"
+#include "ui/anchor/anchor.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/view.h"
+#include "ui/views/view_tracker.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class VIEWS_EXPORT ViewAnchorImpl : public ui::AnchorImpl {
+ public:
+  explicit ViewAnchorImpl(View* anchor_view);
+  ~ViewAnchorImpl() override;
+  std::unique_ptr<ui::AnchorImpl> Clone() const override;
+  bool IsEmpty() const override;
+  gfx::Rect GetScreenBounds() const override;
+  Widget* GetWidget() override;
+  bool IsView() const override;
+  View* GetView() override;
+
+ private:
+  View* view() { return view_tracker_.view(); }
+  const View* view() const { return view_tracker_.view(); }
+
+  ViewTracker view_tracker_;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_ANCHOR_VIEW_ANCHOR_H_
diff --git a/ui/views/anchor/view_anchor_unittest.cc b/ui/views/anchor/view_anchor_unittest.cc
new file mode 100644
index 0000000..69415c3
--- /dev/null
+++ b/ui/views/anchor/view_anchor_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/anchor/view_anchor.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace views::test {
+
+class ViewAnchorTest : public ViewsTestBase {
+ public:
+  ViewAnchorTest() = default;
+  ViewAnchorTest(const ViewAnchorTest&) = delete;
+  ViewAnchorTest& operator=(const ViewAnchorTest&) = delete;
+  ~ViewAnchorTest() override = default;
+
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+    widget_ = CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET);
+    view_ = widget_->SetContentsView(std::make_unique<View>());
+    view_->SetBounds(10, 20, 30, 40);
+    widget_->Show();
+  }
+
+  void TearDown() override {
+    view_ = nullptr;
+    widget_.reset();
+    ViewsTestBase::TearDown();
+  }
+
+ protected:
+  std::unique_ptr<Widget> widget_;
+  raw_ptr<View> view_ = nullptr;
+};
+
+TEST_F(ViewAnchorTest, BasicProperties) {
+  ui::Anchor anchor(view_);
+  EXPECT_FALSE(anchor.IsEmpty());
+  EXPECT_TRUE(anchor.IsView());
+  EXPECT_EQ(anchor.GetView(), view_);
+}
+
+TEST_F(ViewAnchorTest, GetScreenBounds) {
+  ui::Anchor anchor(view_);
+  EXPECT_EQ(anchor.GetScreenBounds(), view_->GetBoundsInScreen());
+}
+
+TEST_F(ViewAnchorTest, ViewDeleted) {
+  ui::Anchor anchor(view_);
+  EXPECT_FALSE(anchor.IsEmpty());
+  EXPECT_TRUE(anchor.IsView());
+
+  // Delete the view. The anchor should become empty.
+  view_.ClearAndDelete();
+
+  EXPECT_TRUE(anchor.IsEmpty());
+  EXPECT_TRUE(anchor.IsView());
+  EXPECT_EQ(anchor.GetView(), nullptr);
+  EXPECT_EQ(anchor.GetScreenBounds(), gfx::Rect());
+}
+
+TEST_F(ViewAnchorTest, WidgetDestroyed) {
+  ui::Anchor anchor(view_);
+  EXPECT_FALSE(anchor.IsEmpty());
+  EXPECT_TRUE(anchor.IsView());
+
+  // Destroy the widget. This will also destroy the view.
+  view_ = nullptr;
+  widget_.reset();
+
+  EXPECT_TRUE(anchor.IsEmpty());
+  EXPECT_TRUE(anchor.IsView());
+  EXPECT_EQ(anchor.GetView(), nullptr);
+  EXPECT_EQ(anchor.GetScreenBounds(), gfx::Rect());
+}
+
+}  // namespace views::test
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index 74b26961..f07904ca 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -1411,8 +1411,8 @@
   test::ButtonTestApi(frame->close_)
       .NotifyClick(ui::MouseEvent(
           ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
-          ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-          ui::EF_NONE, ui::EF_NONE));
+          ui::EventTimeForNow() + GetDoubleClickInterval(), ui::EF_NONE,
+          ui::EF_NONE));
   EXPECT_TRUE(bubble->IsClosed());
 }
 
@@ -1441,8 +1441,8 @@
   test::ButtonTestApi(frame->minimize_)
       .NotifyClick(ui::MouseEvent(
           ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
-          ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-          ui::EF_NONE, ui::EF_NONE));
+          ui::EventTimeForNow() + GetDoubleClickInterval(), ui::EF_NONE,
+          ui::EF_NONE));
   EXPECT_TRUE(minimize_waiter.Wait());
   EXPECT_TRUE(bubble->IsMinimized());
 }
@@ -1471,8 +1471,7 @@
   EXPECT_FALSE(bubble->IsMinimized());
   EXPECT_FALSE(widget->IsClosed());
 
-  task_environment()->FastForwardBy(
-      base::Milliseconds(GetDoubleClickInterval()));
+  task_environment()->FastForwardBy(GetDoubleClickInterval());
   anchor.widget().SetBounds(gfx::Rect(10, 10, 100, 100));
 
   ui::MouseEvent mouse_event_1(ui::EventType::kMousePressed, gfx::Point(),
@@ -1483,10 +1482,10 @@
   EXPECT_FALSE(widget->IsClosed());
   EXPECT_FALSE(bubble->IsMinimized());
 
-  test::ButtonTestApi(ok_button).NotifyClick(ui::MouseEvent(
-      ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-      ui::EF_NONE, ui::EF_NONE));
+  test::ButtonTestApi(ok_button).NotifyClick(
+      ui::MouseEvent(ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
+                     ui::EventTimeForNow() + GetDoubleClickInterval(),
+                     ui::EF_NONE, ui::EF_NONE));
   EXPECT_TRUE(widget->IsClosed());
 }
 
diff --git a/ui/views/input_event_activation_protector.cc b/ui/views/input_event_activation_protector.cc
index ef58c7c4..64d3057 100644
--- a/ui/views/input_event_activation_protector.cc
+++ b/ui/views/input_event_activation_protector.cc
@@ -62,8 +62,7 @@
     }
   }
 
-  const base::TimeDelta kShortInterval =
-      base::Milliseconds(GetDoubleClickInterval());
+  const base::TimeDelta kShortInterval = GetDoubleClickInterval();
   const bool short_event_after_last_event =
       event.time_stamp() < last_event_timestamp_ + kShortInterval;
   last_event_timestamp_ = event.time_stamp();
diff --git a/ui/views/metrics.h b/ui/views/metrics.h
index 4315afe..3cafdf7c 100644
--- a/ui/views/metrics.h
+++ b/ui/views/metrics.h
@@ -5,22 +5,22 @@
 #ifndef UI_VIEWS_METRICS_H_
 #define UI_VIEWS_METRICS_H_
 
+#include "base/time/time.h"
 #include "ui/views/views_export.h"
 
 namespace views {
 
-// NOTE: All times in this file are/should be expressed in milliseconds.
-
 // The default value for how long to wait before showing a menu button on hover.
 // This value is used if the OS doesn't supply one.
-inline constexpr int kDefaultMenuShowDelay = 400;
+inline constexpr base::TimeDelta kDefaultMenuShowDelay =
+    base::Milliseconds(400);
 
 // Returns the amount of time between double clicks.
-VIEWS_EXPORT int GetDoubleClickInterval();
+VIEWS_EXPORT base::TimeDelta GetDoubleClickInterval();
 
 // Returns the amount of time to wait from hovering over a menu button until
 // showing the menu.
-VIEWS_EXPORT int GetMenuShowDelay();
+VIEWS_EXPORT base::TimeDelta GetMenuShowDelay();
 
 }  // namespace views
 
diff --git a/ui/views/metrics_aura.cc b/ui/views/metrics_aura.cc
index c8a9260b..63e9c853 100644
--- a/ui/views/metrics_aura.cc
+++ b/ui/views/metrics_aura.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "ui/views/metrics.h"
 
@@ -11,27 +12,28 @@
 
 namespace views {
 
-int GetDoubleClickInterval() {
+base::TimeDelta GetDoubleClickInterval() {
 #if BUILDFLAG(IS_WIN)
-  return static_cast<int>(::GetDoubleClickTime());
+  return base::Milliseconds(::GetDoubleClickTime());
 #else
   // TODO(jennyz): This value may need to be adjusted on different platforms.
-  const int kDefaultDoubleClickIntervalMs = 500;
-  return kDefaultDoubleClickIntervalMs;
+  constexpr base::TimeDelta kDefaultDoubleClickInterval =
+      base::Milliseconds(500);
+  return kDefaultDoubleClickInterval;
 #endif
 }
 
-int GetMenuShowDelay() {
+base::TimeDelta GetMenuShowDelay() {
 #if BUILDFLAG(IS_WIN)
-  static int delay = []() {
+  static base::TimeDelta delay = []() {
     DWORD show_delay;
     return SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &show_delay, 0)
-               ? static_cast<int>(show_delay)
+               ? base::Milliseconds(show_delay)
                : kDefaultMenuShowDelay;
   }();
   return delay;
 #else
-  return 0;
+  return base::Milliseconds(0);
 #endif
 }
 
diff --git a/ui/views/metrics_mac.cc b/ui/views/metrics_mac.cc
index c7115b3..12c8e96 100644
--- a/ui/views/metrics_mac.cc
+++ b/ui/views/metrics_mac.cc
@@ -4,22 +4,16 @@
 
 #include "ui/views/metrics.h"
 
-namespace {
-
-// Default double click interval in milliseconds.
-// Same as what gtk uses.
-const int kDefaultDoubleClickInterval = 500;
-
-}  // namespace
-
 namespace views {
 
-int GetDoubleClickInterval() {
+base::TimeDelta GetDoubleClickInterval() {
+  constexpr base::TimeDelta kDefaultDoubleClickInterval =
+      base::Milliseconds(500);
   return kDefaultDoubleClickInterval;
 }
 
-int GetMenuShowDelay() {
-  return 0;
+base::TimeDelta GetMenuShowDelay() {
+  return base::Milliseconds(0);
 }
 
 }  // namespace views
diff --git a/ui/views/selection_controller.cc b/ui/views/selection_controller.cc
index b1a4514..ccf1ab3 100644
--- a/ui/views/selection_controller.cc
+++ b/ui/views/selection_controller.cc
@@ -172,8 +172,7 @@
 void SelectionController::TrackMouseClicks(const ui::MouseEvent& event) {
   if (event.IsOnlyLeftMouseButton()) {
     base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
-    if (!last_click_time_.is_null() &&
-        time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
+    if (!last_click_time_.is_null() && time_delta <= GetDoubleClickInterval() &&
         !View::ExceededDragThreshold(event.root_location() -
                                      last_click_root_location_)) {
       // Upon clicking after a triple click, the count should go back to
diff --git a/ui/views/selection_controller_unittest.cc b/ui/views/selection_controller_unittest.cc
index d963e06..5fb0df1f 100644
--- a/ui/views/selection_controller_unittest.cc
+++ b/ui/views/selection_controller_unittest.cc
@@ -128,7 +128,7 @@
     mouse_location_ = location;
     // Ensure that mouse presses are spaced apart by at least the double-click
     // interval to avoid triggering a double-click.
-    last_event_time_ += base::Milliseconds(views::GetDoubleClickInterval() + 1);
+    last_event_time_ += views::GetDoubleClickInterval() + base::Milliseconds(1);
     controller_->OnMousePressed(
         ui::MouseEvent(ui::EventType::kMousePressed, location, location,
                        last_event_time_, mouse_flags_, button),
diff --git a/ui/views/window/dialog_client_view_unittest.cc b/ui/views/window/dialog_client_view_unittest.cc
index 394c6334..1764b153 100644
--- a/ui/views/window/dialog_client_view_unittest.cc
+++ b/ui/views/window/dialog_client_view_unittest.cc
@@ -605,10 +605,10 @@
   cancel_button.NotifyClick(mouse_event);
   EXPECT_FALSE(widget()->IsClosed());
 
-  cancel_button.NotifyClick(ui::MouseEvent(
-      ui::EventType::kMousePressed, gfx::PointF(), gfx::PointF(),
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-      ui::EF_NONE, ui::EF_NONE));
+  cancel_button.NotifyClick(
+      ui::MouseEvent(ui::EventType::kMousePressed, gfx::PointF(), gfx::PointF(),
+                     ui::EventTimeForNow() + GetDoubleClickInterval(),
+                     ui::EF_NONE, ui::EF_NONE));
   EXPECT_TRUE(widget()->IsClosed());
 }
 
@@ -642,8 +642,7 @@
   EXPECT_FALSE(widget()->IsClosed());
 
   ui::GestureEvent tap_event2(
-      0, 0, 0,
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
+      0, 0, 0, ui::EventTimeForNow() + GetDoubleClickInterval(),
       ui::GestureEventDetails(ui::EventType::kGestureTap));
   cancel_button.NotifyClick(tap_event2);
   EXPECT_TRUE(widget()->IsClosed());
@@ -665,10 +664,10 @@
   cancel_button.NotifyClick(touch_event);
   EXPECT_FALSE(widget()->IsClosed());
 
-  ui::TouchEvent touch_event2(
-      ui::EventType::kTouchPressed, gfx::PointF(), gfx::PointF(),
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-      ui::PointerDetails(ui::EventPointerType::kTouch));
+  ui::TouchEvent touch_event2(ui::EventType::kTouchPressed, gfx::PointF(),
+                              gfx::PointF(),
+                              ui::EventTimeForNow() + GetDoubleClickInterval(),
+                              ui::PointerDetails(ui::EventPointerType::kTouch));
   cancel_button.NotifyClick(touch_event2);
   EXPECT_TRUE(widget()->IsClosed());
 }
@@ -692,8 +691,7 @@
                    static_cast<int>(ui::mojom::DialogButton::kOk));
   SizeAndLayoutWidget();
   widget()->Show();
-  task_environment()->FastForwardBy(
-      base::Milliseconds(GetDoubleClickInterval() * 2));
+  task_environment()->FastForwardBy(GetDoubleClickInterval() * 2);
 
   // Create another widget on top, change window's bounds, click event to the
   // old widget should be ignored.
@@ -707,10 +705,10 @@
   cancel_button.NotifyClick(mouse_event);
   EXPECT_FALSE(widget()->IsClosed());
 
-  cancel_button.NotifyClick(ui::MouseEvent(
-      ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-      ui::EF_NONE, ui::EF_NONE));
+  cancel_button.NotifyClick(
+      ui::MouseEvent(ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
+                     ui::EventTimeForNow() + GetDoubleClickInterval(),
+                     ui::EF_NONE, ui::EF_NONE));
   EXPECT_TRUE(widget()->IsClosed());
   widget1->CloseNow();
 }
@@ -723,8 +721,7 @@
                    static_cast<int>(ui::mojom::DialogButton::kOk));
   SizeAndLayoutWidget();
   widget()->Show();
-  task_environment()->FastForwardBy(
-      base::Milliseconds(GetDoubleClickInterval() * 2));
+  task_environment()->FastForwardBy(GetDoubleClickInterval() * 2);
 
   // Create another widget on top, close the top window, click event to the old
   // widget should be ignored.
@@ -738,10 +735,10 @@
   cancel_button.NotifyClick(mouse_event);
   EXPECT_FALSE(widget()->IsClosed());
 
-  cancel_button.NotifyClick(ui::MouseEvent(
-      ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
-      ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-      ui::EF_NONE, ui::EF_NONE));
+  cancel_button.NotifyClick(
+      ui::MouseEvent(ui::EventType::kMousePressed, gfx::Point(), gfx::Point(),
+                     ui::EventTimeForNow() + GetDoubleClickInterval(),
+                     ui::EF_NONE, ui::EF_NONE));
   EXPECT_TRUE(widget()->IsClosed());
 }
 #endif  // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_FUCHSIA)
@@ -753,8 +750,7 @@
                    static_cast<int>(ui::mojom::DialogButton::kOk));
   SizeAndLayoutWidget();
   widget()->Show();
-  task_environment()->FastForwardBy(
-      base::Milliseconds(GetDoubleClickInterval() * 2));
+  task_environment()->FastForwardBy(GetDoubleClickInterval() * 2);
 
   UniqueWidgetPtr widget1(std::make_unique<Widget>());
   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_TOOLTIP);
@@ -778,8 +774,7 @@
                    static_cast<int>(ui::mojom::DialogButton::kOk));
 
   const base::TimeTicks kNow = ui::EventTimeForNow();
-  const base::TimeDelta kShortClickInterval =
-      base::Milliseconds(GetDoubleClickInterval());
+  const base::TimeDelta kShortClickInterval = GetDoubleClickInterval();
 
   // Should ignore clicks right after the dialog is shown.
   ui::MouseEvent mouse_event(ui::EventType::kMousePressed, gfx::Point(),
@@ -1027,7 +1022,7 @@
   std::unique_ptr<ui::KeyEvent> KeyEventDelayed() {
     return std::make_unique<ui::KeyEvent>(
         ui::EventType::kKeyPressed, ui::VKEY_RETURN, ui::EF_NONE,
-        ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()));
+        ui::EventTimeForNow() + GetDoubleClickInterval());
   }
 
   std::unique_ptr<ui::MouseEvent> MouseEventNow() {
@@ -1039,8 +1034,8 @@
   std::unique_ptr<ui::MouseEvent> MouseEventDelayed() {
     return std::make_unique<ui::MouseEvent>(
         ui::EventType::kMousePressed, gfx::PointF(), gfx::PointF(),
-        ui::EventTimeForNow() + base::Milliseconds(GetDoubleClickInterval()),
-        ui::EF_NONE, ui::EF_NONE);
+        ui::EventTimeForNow() + GetDoubleClickInterval(), ui::EF_NONE,
+        ui::EF_NONE);
   }
 };
 
diff --git a/ui/wm/core/cursor_util.cc b/ui/wm/core/cursor_util.cc
index 55775fb7..c6c05a0 100644
--- a/ui/wm/core/cursor_util.cc
+++ b/ui/wm/core/cursor_util.cc
@@ -342,7 +342,7 @@
       {12, 12},
       /*is_animated=*/true}},
     {{CursorType::kNoDrop, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}},
-    {{CursorType::kCopy, IDR_AURA_CURSOR_COPY, {9, 9}, {18, 18}}},
+    {{CursorType::kCopy, IDR_AURA_CURSOR_COPY_LOTTIE, {8, 7}, {8, 7}}},
     /*CursorType::kNone*/ {},
     {{CursorType::kNotAllowed, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}},
     {{CursorType::kZoomIn, IDR_AURA_CURSOR_ZOOM_IN, {10, 10}, {20, 20}}},
@@ -473,7 +473,7 @@
       {12, 12},
       /*is_animated=*/true}},
     {{CursorType::kNoDrop, IDR_AURA_CURSOR_BIG_NO_DROP, {10, 10}, {20, 20}}},
-    {{CursorType::kCopy, IDR_AURA_CURSOR_BIG_COPY, {21, 11}, {42, 22}}},
+    {{CursorType::kCopy, IDR_AURA_CURSOR_COPY_LOTTIE, {8, 7}, {8, 7}}},
     /*CursorType::kNone*/ {},
     {{CursorType::kNotAllowed,
       IDR_AURA_CURSOR_BIG_NO_DROP,
diff --git a/ui/wm/core/cursor_util_unittest.cc b/ui/wm/core/cursor_util_unittest.cc
index 6a48d99..0a00a0a 100644
--- a/ui/wm/core/cursor_util_unittest.cc
+++ b/ui/wm/core/cursor_util_unittest.cc
@@ -199,7 +199,7 @@
       {SK_ColorBLUE, SK_ColorGREEN, SkColorSetRGB(173, 8, 8),
        CursorType::kNoDrop},
       // Similarly, the copy cursor has green in it.
-      {SK_ColorBLUE, SK_ColorRED, SkColorSetRGB(19, 137, 16),
+      {SK_ColorBLUE, SK_ColorRED, SkColorSetRGB(57, 149, 88),
        CursorType::kCopy},
   };
 
diff --git a/v8 b/v8
index 5962611..eda6309a 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 596261193b6c808f82e6bcd0150f39129793f1f3
+Subproject commit eda6309abc2088b5d77b91470c3d971bdc5d962b